1 """
2 Line-based and matrix-based plotting commands using MatPlotLib.
3
4 Before importing this file, you will probably want to do something
5 like:
6
7 from matplotlib import rcParams
8 rcParams['backend']='TkAgg'
9
10 to select a backend, or else select an appropriate one in your
11 matplotlib.rc file (if any). There are many backends available for
12 different GUI or non-GUI uses.
13
14 $Id: pylabplots.py 10921 2010-02-16 18:46:32Z antolikjan $
15 """
16 __version__='$Revision: 10921 $'
17
18 import re
19 import os
20 import copy
21 import errno
22
23 try:
24 import matplotlib
25 import pylab
26 except ImportError:
27 print "Warning: Could not import matplotlib; pylab plots will not work."
28
29 import numpy
30 from math import pi
31
32 from numpy.oldnumeric import arange, sqrt, array, floor, transpose, argmax, argmin, cos, sin, log10, Float
33 from numpy import outer,arange,ones,zeros
34
35 from numpy.fft.fftpack import fft2
36 from numpy.fft.helper import fftshift
37 from numpy import abs
38
39 import topo
40 from topo.base.sheetview import SheetView
41 from topo.base.arrayutil import octave_output, centroid, wrap
42 from topo.base.sheet import Sheet
43 from topo.base.arrayutil import wrap
44 from topo.misc.filepath import normalize_path
45 from topo.misc.util import frange
46 import topo.analysis.vision
47 from topo.plotting.plot import make_template_plot, Plot
48 import param
49 from param import ParameterizedFunction
50 from param.parameterized import ParamOverrides
51 from topo.pattern.basic import SineGrating, RawRectangle, OrientationContrast
52 from topo.plotting.plotgroup import create_plotgroup, plotgroups
53 from topo.base.cf import CFSheet
54
55 from topo.analysis.featureresponses import Feature, PatternPresenter, FeatureCurves
56 from topo.analysis.featureresponses import SinusoidalMeasureResponseCommand, PositionMeasurementCommand, SingleInputResponseCommand, FeatureCurveCommand, UnitCurveCommand
57
58
59
61 """Parameterized command for plotting using Matplotlib/Pylab."""
62
63 file_dpi = param.Number(
64 default=100.0,bounds=(0,None),softbounds=(0,1000),doc="""
65 Default DPI when rendering to a bitmap.
66 The nominal size * the dpi gives the final image size in pixels.
67 E.g.: 4"x4" image * 80 dpi ==> 320x320 pixel image.""")
68
69 file_format = param.String(default="png",doc="""
70 Which image format to use when saving images.
71 The output can be png, ps, pdf, svg, or any other format
72 supported by Matplotlib.""")
73
74
75
76
77
78
79 filename = param.String(default=None,doc="""
80 Optional base of the filename to use when saving images;
81 if None the plot will be displayed interactively.
82
83 The actual name is constructed from the filename base plus the
84 suffix plus the current simulator time plus the file_format.""")
85
86 filename_suffix = param.String(default="",doc="""
87 Optional suffix to be used for disambiguation of the filename.""")
88
89 title = param.String(default=None,doc="""
90 Optional title to be used when displaying the plot interactively.""")
91
92 __abstract = True
93
94
96 """
97 Helper function to set the title (if not None) of this PyLab plot window.
98 """
99
100
101
102
103
104
105
106
107 if title is not None:
108 try:
109 manager = pylab.get_current_fig_manager()
110 manager.window.title(title)
111 except:
112 pass
113
114
131
132
133
135 """
136 Simple line plotting for any vector or list of numbers.
137
138 Intended for interactive debugging or analyzing from the command
139 prompt. See MatPlotLib's pylab functions to create more elaborate
140 or customized plots; this is just a simple example.
141
142 An optional string can be supplied as a title for the figure, if
143 desired. At present, this is only used for the window, not the
144 actual body of the figure (and will thus not appear when the
145 figure is saved).
146
147 The style argument allows different line/linespoints style for
148 the plot: 'r-' for red solid line, 'bx' for blue x-marks, etc.
149 See http://matplotlib.sourceforge.net/matplotlib.pylab.html#-plot
150 for more possibilities.
151
152 The label argument can be used to identify the line in a figure legend.
153
154 Ordinarily, the x value for each point on the line is the index of
155 that point in the vec array, but a explicit list of xvalues can be
156 supplied; it should be the same length as vec.
157
158 Execution of multiple vectorplot() commands with different styles
159 will result in all those styles overlaid on a single plot window.
160 """
161
162
163 - def __call__(self,vec,xvalues=None,style='-',label=None,**params):
173
174
175
177 """
178 Simple plotting for any matrix as a bitmap with axes.
179
180 Like MatLab's imagesc, scales the values to fit in the range 0 to 1.0.
181 Intended for interactive debugging or analyzing from the command
182 prompt. See MatPlotLib's pylab functions to create more elaborate
183 or customized plots; this is just a simple example.
184 """
185
186 plot_type = param.Callable(default=pylab.gray,doc="""
187 Matplotlib command to generate the plot, e.g. pylab.gray or pylab.hsv.""")
188
189
190 - def __call__(self,mat,aspect=None,colorbar=True,**params):
191 p=ParamOverrides(self,params)
192
193 p.plot_type()
194 pylab.figure(figsize=(5,5))
195 pylab.imshow(mat,interpolation='nearest',aspect=aspect)
196 if colorbar and (mat.min()!= mat.max()): pylab.colorbar()
197 self._generate_figure(p)
198
199
201 """
202 Simple plotting for any matrix as a 3D wireframe with axes.
203
204 Uses Matplotlib's beta-quality features for 3D plotting. These
205 usually work fine for wireframe plots, although they don't always
206 format the axis labels properly, and do not support removal of
207 hidden lines. Note that often the plot can be rotated within the
208 window to make such problems go away, and then the best result can
209 be saved if needed.
210
211 Other than the default "wireframe", the type can be "contour" to
212 get a contour plot, or "surface" to get a solid surface plot, but
213 surface plots currently fail in many cases, e.g. for small
214 matrices.
215
216 If you have trouble, you can try matrixplot3d_gnuplot instead.
217 """
218
219
220 - def __call__(self,mat,type="wireframe",**params):
221 p=ParamOverrides(self,params)
222
223 from mpl_toolkits.mplot3d import axes3d
224
225 fig = pylab.figure()
226 ax = axes3d.Axes3D(fig)
227
228
229 rn,cn = mat.shape
230 c = outer(ones(rn),arange(cn*1.0))
231 r = outer(arange(rn*1.0),ones(cn))
232
233 if type=="wireframe":
234 ax.plot_wireframe(r,c,mat)
235 elif type=="surface":
236
237 ax.plot_surface(r,c,mat)
238 elif type=="contour":
239
240 ax.contour3D(r,c,mat)
241 else:
242 raise ValueError("Unknown plot type "+str(type))
243
244 ax.set_xlabel('R')
245 ax.set_ylabel('C')
246 ax.set_zlabel('Value')
247
248 self._generate_figure(p)
249
250
251
253 """
254 Simple plotting for any matrix as a 3D surface with axes.
255
256 Currently requires the gnuplot-py package to be installed, plus
257 the external gnuplot program; likely to be removed once Matplotlib
258 supports 3D plots better.
259
260 Unlikely to work on non-UNIX systems.
261
262 Should return when it completes, but for some reason the Topographica
263 prompt is not available until this command finishes.
264 """
265 import Gnuplot
266 import Numeric
267 from os import system
268
269 psviewer="gv"
270 g = Gnuplot.Gnuplot(debug=0)
271 r,c = mat.shape
272 x = arange(r*1.0)
273 y = arange(c*1.0)
274
275
276 m = numpy.asarray(mat,dtype="float32").tolist()
277
278 g("set data style lines")
279 g("set hidden3d")
280 g("set xlabel 'R'")
281 g("set ylabel 'C'")
282 g("set zlabel 'Value'")
283 if title: g.title(title)
284
285 if outputfilename:
286 g("set terminal postscript eps color solid 'Times-Roman' 14")
287 g("set output '"+outputfilename+"'")
288 g.splot(Gnuplot.GridData(m,x,y, binary=1))
289
290 system(psviewer+" "+outputfilename+" &")
291
292 else:
293 g.splot(Gnuplot.GridData(m,x,y, binary=1))
294 raw_input('Please press return to continue...\n')
295
296
297
299 """
300 Compute and plot the histogram of the supplied data.
301
302 See help(pylab.hist) for help on the histogram function itself.
303
304 If given, colors is an iterable collection of matplotlib.colors
305 (see help (matplotlib.colors) ) specifying the bar colors.
306
307 Example use:
308 histogramplot([1,1,1,2,2,3,4,5],title='hist',colors='rgb',bins=3,normed=1)
309 """
310
311
312 - def __call__(self,data,colors=None,**params):
313 p=ParamOverrides(self,params,allow_extra_keywords=True)
314
315 pylab.figure(figsize=(4,2))
316 n,bins,bars = pylab.hist(data,**(p.extra_keywords()))
317
318
319
320 if colors: [bar.set_fc(color) for bar,color in zip(bars,colors)]
321
322 self._generate_figure(p)
323
324
325
327 """
328 Compute and show the gradient plot of the supplied data.
329 Translated from Octave code originally written by Yoonsuck Choe.
330
331 If the data is specified to be cyclic, negative differences will
332 be wrapped into the range specified (1.0 by default).
333 """
334
335
336 - def __call__(self,data,cyclic=True,cyclic_range=1.0,**params):
337 p=ParamOverrides(self,params)
338
339 r,c = data.shape
340 dx = numpy.diff(data,1,axis=1)[0:r-1,0:c-1]
341 dy = numpy.diff(data,1,axis=0)[0:r-1,0:c-1]
342
343 if cyclic:
344
345 dx = wrap(0,cyclic_range,dx)
346 dy = wrap(0,cyclic_range,dy)
347
348
349
350 dx = 0.5*cyclic_range-abs(dx-0.5*cyclic_range)
351 dy = 0.5*cyclic_range-abs(dy-0.5*cyclic_range)
352
353 super(gradientplot,self).__call__(sqrt(dx*dx+dy*dy),**p)
354
355
356
358 """
359 Compute and show the 2D Fast Fourier Transform (FFT) of the supplied data.
360
361 Example:: fftplot(topo.sim["V1"].sheet_views["OrientationPreference"].view()[0],filename="out")
362 """
363
365 p=ParamOverrides(self,params)
366 fft_plot=1-abs(fftshift(fft2(data-0.5, s=None, axes=(-2,-1))))
367 super(fftplot,self).__call__(fft_plot,**p)
368
369
370
372 """
373 Plots the activity in a sheet.
374
375 Gets plot's extent from sheet.bounds.aarect(). Adds a title and
376 allows the selection of a colormap. If activity is not given,
377 the sheet's current activity is used.
378 """
379
380
381
382 - def __call__(self,sheet,activity=None,cmap=None,**params):
383 p=ParamOverrides(self,params)
384
385 l,b,r,t = sheet.bounds.aarect().lbrt()
386 if activity is None:
387 activity = sheet.activity
388 if cmap is None:
389 cmap=pylab.cm.Greys
390 pylab.imshow(activity, extent=(l,r,b,t),cmap=cmap)
391
392 self._generate_figure(p)
393
394
395
397 """
398 By default, plot the XPreference and YPreference preferences for all
399 Sheets for which they are defined, using MatPlotLib.
400
401 If sheet_views other than XPreference and YPreference are desired,
402 the names of these can be passed in as arguments.
403 """
404
405 xsheet_view_name = param.String(default='XPreference',doc="""
406 Name of the SheetView holding the X position locations.""")
407
408 ysheet_view_name = param.String(default='YPreference',doc="""
409 Name of the SheetView holding the Y position locations.""")
410
411 axis = param.Parameter(default=[-0.5,0.5,-0.5,0.5],doc="""
412 Four-element list of the plot bounds, i.e. [xmin, xmax, ymin, ymax].""")
413
415 p=ParamOverrides(self,params)
416
417 for sheet in topo.sim.objects(Sheet).values():
418 if ((p.xsheet_view_name in sheet.sheet_views) and
419 (p.ysheet_view_name in sheet.sheet_views)):
420
421 x = sheet.sheet_views[p.xsheet_view_name].view()[0]
422 y = sheet.sheet_views[p.ysheet_view_name].view()[0]
423
424 pylab.figure(figsize=(5,5))
425
426
427
428
429
430
431
432 isint=pylab.isinteractive()
433 pylab.ioff()
434 for r,c in zip(y,x):
435 pylab.plot(c,r,"k-")
436 for r,c in zip(transpose(y),transpose(x)):
437 pylab.plot(c,r,"k-")
438
439 pylab.xlabel('x')
440 pylab.ylabel('y')
441
442
443
444 pylab.axis(p.axis)
445 p.title='Topographic mapping to '+sheet.name+' at time '+topo.sim.timestr()
446
447 if isint: pylab.ion()
448 p.filename_suffix="_"+sheet.name
449 self._generate_figure(p)
450
451
453 """
454 Use matplotlib to make a plot combining a bitmap and line-based overlays.
455 """
456
457 plot_template = param.List(default=[{'Hue':'OrientationPreference'}],doc="""
458 Template for the underlying bitmap plot.""")
459
460 overlay = param.List(default=[('contours','OcularPreference',0.5,'black'),
461 ('arrows','DirectionPreference','DirectionSelectivity','white')],doc="""
462 List of overlaid plots, where each list item may be a 4-tuple
463 specifying either a contour line or a field of arrows::
464
465 ('contours',map-name,contour-value,line-color)
466
467 ('arrows',arrow-location-map-name,arrow-size-map-name,arrow-color)
468
469 Any number or combination of contours and arrows may be supplied.""")
470
471 normalize = param.Boolean(default='Individually',doc="""
472 Type of normalization, if any, to use. Options include 'None',
473 'Individually', and 'AllTogether'. See
474 topo.plotting.plotgroup.TemplatePlotGroup.normalize for more
475 details.""")
476
477
479 p=ParamOverrides(self,params)
480
481 for template in p.plot_template:
482
483 for sheet in topo.sim.objects(Sheet).values():
484 name=template.keys().pop(0)
485 plot=make_template_plot(template,sheet.sheet_views,sheet.xdensity,sheet.bounds,p.normalize,name=template[name])
486 if plot:
487 bitmap=plot.bitmap
488 pylab.figure(figsize=(5,5))
489 isint=pylab.isinteractive()
490 pylab.ioff()
491
492 pylab.imshow(bitmap.image,origin='lower',interpolation='nearest')
493 pylab.axis('off')
494
495 for (t,pref,sel,c) in p.overlay:
496 v = pylab.flipud(sheet.sheet_views[pref].view()[0])
497
498 if (t=='contours'):
499 pylab.contour(v,[sel,sel],colors=c,linewidths=2)
500
501 if (t=='arrows'):
502 s = pylab.flipud(sheet.sheet_views[sel].view()[0])
503 scale=int(pylab.ceil(log10(len(v))))
504 X=pylab.array([x for x in xrange(len(v)/scale)])
505 v_sc=pylab.zeros((len(v)/scale,len(v)/scale))
506 s_sc=pylab.zeros((len(v)/scale,len(v)/scale))
507 for i in X:
508 for j in X:
509 v_sc[i][j]=v[scale*i][scale*j]
510 s_sc[i][j]=s[scale*i][scale*j]
511 pylab.quiver(scale*X,scale*X,-cos(2*pi*v_sc)*s_sc,-sin(2*pi*v_sc)*s_sc,color=c,edgecolors=c,minshaft=3,linewidths=1)
512
513 p.title='%s overlaid with %s at time %s' %(plot.name,pref,topo.sim.timestr())
514 if isint: pylab.ion()
515 p.filename_suffix="_"+sheet.name
516 self._generate_figure(p)
517
518
519
521 """
522 Plot a tuning curve for a feature, such as orientation, contrast, or size.
523
524 The curve datapoints are collected from the curve_dict for
525 the units at the specified coordinates in the specified sheet
526 (where the units and sheet may be set by a GUI, using
527 topo.analysis.featureresponses.UnitCurveCommand.sheet and
528 topo.analysis.featureresponses.UnitCurveCommand.coords,
529 or by hand).
530 """
531
532 coords = param.List(default=[(0,0)],doc="""
533 List of coordinates of units to measure.""")
534
535 sheet = param.ObjectSelector(
536 default=None,doc="""
537 Name of the sheet to use in measurements.""")
538
539 x_axis = param.String(default="",doc="""
540 Feature to plot on the x axis of the tuning curve""")
541
542
543
544 plot_type = param.Callable(default=pylab.plot,doc="""
545 Matplotlib command to generate the plot.""")
546
547 unit = param.String(default="",doc="""
548 String to use in labels to specify the units in which curves are plotted.""")
549
550 __abstract = True
551
552
555
557 n = n % len(seq)
558 return seq[n:] + seq[:n]
559
561 """Return the x, y, and x ticks values for the specified curve from the curve_dict"""
562 x_values=sorted(curve.keys())
563 y_values=[curve[key].view()[0][i_value,j_value] for key in x_values]
564 return x_values,y_values,x_values
565
567 x = [];
568 y= [];
569 num_ticks = 5;
570 y.append(ticks[0])
571 x.append(0)
572 for i in xrange(0,num_ticks):
573 y.append(y[-1]+numpy.pi/(num_ticks+1));
574 x.append(x[-1]+numpy.pi/(num_ticks+1));
575 y.append(y[-1]+numpy.pi/(num_ticks+1));
576 x.append(3.14)
577 return (x,y)
578
579
581 p=ParamOverrides(self,params)
582 sheet = p.sheet
583 for coordinate in p.coords:
584 i_value,j_value=sheet.sheet2matrixidx(coordinate[0],coordinate[1])
585
586 f = pylab.figure(figsize=(7,7))
587 isint=pylab.isinteractive()
588 pylab.ioff()
589
590 pylab.ylabel('Response',fontsize='large')
591 pylab.xlabel('%s (%s)' % (p.x_axis.capitalize(),p.unit),fontsize='large')
592 pylab.title('Sheet %s, coordinate(x,y)=(%0.3f,%0.3f) at time %s' %
593 (sheet.name,coordinate[0],coordinate[1],topo.sim.timestr()))
594 p.title='%s: %s Tuning Curve' % (topo.sim.name,p.x_axis.capitalize())
595
596 self.first_curve=True
597 for curve_label in sorted(sheet.curve_dict[p.x_axis].keys()):
598 x_values,y_values,ticks=self._curve_values(i_value,j_value,sheet.curve_dict[p.x_axis][curve_label])
599
600 x_tick_values,ticks = self._reduce_ticks(ticks)
601 labels = [self._format_x_tick_label(x) for x in ticks]
602 pylab.xticks(x_tick_values, labels,fontsize='large')
603 pylab.yticks(fontsize='large')
604 p.plot_type(x_values, y_values, label=curve_label,lw=3.0)
605 self.first_curve=False
606
607 if isint: pylab.ion()
608 pylab.legend(loc=2)
609 self._generate_figure(p)
610
611
612
614 """
615 Same as tuning_curve, but rotates the curve so that minimum y
616 values are at the minimum x value to make the plots easier to
617 interpret. Such rotation is valid only for periodic quantities
618 like orientation or direction, and only if the correct period
619 is set.
620
621 At present, the y_values and labels are rotated by an amount
622 determined by the minmum y_value for the first curve plotted
623 (usually the lowest contrast curve).
624 """
625
626 cyclic_range = param.Number(default=pi,bounds=(0,None),softbounds=(0,10),doc="""
627 Range of the cyclic quantity (e.g. pi for the orientation of
628 a symmetric stimulus, or 2*pi for motion direction or the
629 orientation of a non-symmetric stimulus).""")
630
631 unit = param.String(default="degrees",doc="""
632 String to use in labels to specify the units in which curves are plotted.""")
633
634
635
636
637
638
641
642
644 """
645 Return the x, y, and x ticks values for the specified curve from the curve_dict.
646
647 With the current implementation, there may be cases (i.e.,
648 when the lowest contrast curve gives a lot of zero y_values)
649 in which the maximum is not in the center. This may
650 eventually be changed so that the preferred orientation is in
651 the center.
652 """
653 if self.first_curve==True:
654 x_values= sorted(curve.keys())
655 y_values=[curve[key].view()[0][i_value,j_value] for key in x_values]
656
657 min_arg=argmin(y_values)
658 x_min=x_values[min_arg]
659 y_min=y_values[min_arg]
660 y_values=self._rotate(y_values, n=min_arg)
661 self.ticks=self._rotate(x_values, n=min_arg)
662 self.ticks+=[x_min]
663 x_max=min(x_values)+self.cyclic_range
664 x_values.append(x_max)
665 y_values.append(y_min)
666
667 self.x_values=x_values
668 else:
669 y_values=[curve[key].view()[0][i_value,j_value] for key in self.ticks]
670
671 return self.x_values,y_values,self.ticks
672
673
674
676 """
677 Given a CF sheet receiving a CFProjection, plot
678 the mapping of the dests CF centers on the src sheet.
679 """
680 if isinstance(dest,str):
681 from topo import sim
682 dest = sim[dest]
683 plot_coord_mapping(dest.projections()[proj].coord_mapper,
684 dest,style=style)
685
686
687
689 """
690 Plot a coordinate mapping for a sheet.
691
692 Given a CoordinateMapperFn (as for a CFProjection) and a sheet
693 of the projection, plot a grid showing where the sheet's units
694 are mapped.
695 """
696
697 from pylab import plot,hold,ishold
698
699 xs = sheet.sheet_rows()
700 ys = sheet.sheet_cols()
701
702 hold_on = ishold()
703 if not hold_on:
704 plot()
705 hold(True)
706
707 for y in ys:
708 pts = [mapper(x,y) for x in xs]
709 plot([u for u,v in pts],
710 [v for u,v in pts],
711 style)
712
713 for x in xs:
714 pts = [mapper(x,y) for y in ys]
715 plot([u for u,v in pts],
716 [v for u,v in pts],
717 style)
718
719 hold(hold_on)
720
721
722
724 """
725 Plots parameter values associated with an AttributeTrackingTF.
726 Example call:
727 VT=AttributeTrackingTF(function=HE, debug_params=['a', 'b',], units=[(0,0),(1,1)], step=1)
728 plot_tracked_attributes(VT,0,10000,attrib_names=['a'],units=[(0,0)], filename='V1')
729 """
730
731
732 raw = param.Boolean(default=False)
733
734 attrib_names = param.List(default=[])
735
736 ylabel = param.String(default="")
737
738
739 units = param.List(default=[])
740
741 ybounds = param.Parameter(default=(None,None))
742
743
744
745 - def __call__(self,output_fn,init_time=0,final_time=None,**params):
746 p=ParamOverrides(self,params)
747
748 if final_time is None:
749 final_time=topo.sim.time()
750
751 attrs = p.attrib_names if len(p.attrib_names)>0 else output_fn.attrib_names
752 for a in attrs:
753 pylab.figure(figsize=(6,4))
754 isint=pylab.isinteractive()
755 pylab.ioff()
756 pylab.grid(True)
757 ylabel=p.ylabel
758 pylab.ylabel(a+" "+ylabel)
759 pylab.xlabel('Iteration Number')
760
761 coords = p.units if len(p.units)>0 else output_fn.units
762 for coord in coords:
763 y_data=[y for (x,y) in output_fn.values[a][coord]]
764 x_data=[x for (x,y) in output_fn.values[a][coord]]
765 if p.raw==True:
766 plot_data=zip(x_data,y_data)
767 pylab.save(normalize_path(p.filename+a+'(%.2f, %.2f)' %(coord[0], coord[1])),plot_data,fmt='%.6f', delimiter=',')
768
769
770 pylab.plot(x_data,y_data, label='Unit (%.2f, %.2f)' %(coord[0], coord[1]))
771 (ymin,ymax)=p.ybounds
772 pylab.axis(xmin=init_time,xmax=final_time,ymin=ymin,ymax=ymax)
773
774 if isint: pylab.ion()
775 pylab.legend(loc=0)
776 p.title=topo.sim.name+': '+a
777 p.filename_suffix=a
778 self._generate_figure(p)
779
780
781
782
783
784
785
787 """
788 This function computes the modulation ratios of neurons in the
789 specified sheets and plots their histograms. See
790 analysis.vision.complexity for more info.
791 """
792
793
794 - def __call__(self,fullmatrix,simple_sheet_name=None,complex_sheet_name=None,bins=frange(0,2.0,0.1,inclusive=True),**params):
795 p=ParamOverrides(self,params)
796
797 from topo.analysis.vision import complexity
798 if (topo.sim.objects().has_key(simple_sheet_name) and topo.sim.objects().has_key(complex_sheet_name)):
799 v1s = complexity(fullmatrix[topo.sim[simple_sheet_name]]).flatten()
800 v1c = complexity(fullmatrix[topo.sim[complex_sheet_name]]).flatten()
801 import matplotlib.ticker as mticker
802
803 v1c = numpy.concatenate((array(v1c),array(v1c)),axis=1)
804 pylab.figure()
805 n = pylab.subplot(311)
806 pylab.hist(v1s,bins)
807 pylab.axis([0,2.0,0,4100])
808 n.yaxis.set_major_locator(mticker.MaxNLocator(3))
809
810 n = pylab.subplot(312)
811 pylab.hist(v1c,bins)
812 pylab.axis([0,2.0,0,4100])
813 n.yaxis.set_major_locator(mticker.MaxNLocator(3))
814
815 n = pylab.subplot(313)
816 pylab.hist(numpy.concatenate((array(v1s),array(v1c)),axis=1),bins)
817 pylab.axis([0,2.0,0,4100])
818 n.yaxis.set_major_locator(mticker.MaxNLocator(3))
819
820 self._generate_figure(p)
821
822
823
825 """Measure a position preference map by collating the response to patterns."""
826
827 scale = param.Number(default=0.3)
828
834
835
836 pg= create_plotgroup(name='Position Preference',category="Preference Maps",
837 doc='Measure preference for the X and Y position of a Gaussian.',
838 pre_plot_hooks=[measure_position_pref.instance()],
839 plot_hooks=[topographic_grid.instance()],
840 normalize='Individually')
841
842 pg.add_plot('X Preference',[('Strength','XPreference')])
843 pg.add_plot('Y Preference',[('Strength','YPreference')])
844 pg.add_plot('Position Preference',[('Red','XPreference'),
845 ('Green','YPreference')])
846
847
848
850 """
851 Calculate center of gravity (CoG) for each CF of each unit in each CFSheet.
852
853 Unlike measure_position_pref and other measure commands, this one
854 does not work by collating the responses to a set of input patterns.
855 Instead, the CoG is calculated directly from each set of incoming
856 weights. The CoG value thus is an indirect estimate of what
857 patterns the neuron will prefer, but is not limited by the finite
858 number of test patterns as the other measure commands are.
859
860 Measures only one projection for each sheet, as specified by the
861 proj_name parameter. The default proj_name of '' selects the
862 first non-self connection, which is usually useful to examine for
863 simple feedforward networks, but will not necessarily be useful in
864 other cases.
865 """
866
867 proj_name = param.String(default='',doc="""
868 Name of the projection to measure; the empty string means 'the first
869 non-self connection available'.""")
870
872 p=ParamOverrides(self,params)
873
874 measured_sheets = [s for s in topo.sim.objects(CFSheet).values()
875 if hasattr(s,'measure_maps') and s.measure_maps]
876
877
878
879
880
881
882 requested_proj=p.proj_name
883 for sheet in measured_sheets:
884 for proj in sheet.in_connections:
885 if (proj.name == requested_proj) or \
886 (requested_proj == '' and (proj.src != sheet)):
887 self._update_proj_cog(proj)
888 if requested_proj=='':
889 print "measure_cog: Measured %s projection %s from %s" % \
890 (proj.dest.name,proj.name,proj.src.name)
891 break
892
893
895 """Measure the CoG of the specified projection and register corresponding SheetViews."""
896
897 sheet=proj.dest
898 rows,cols=sheet.activity.shape
899 xpref=zeros((rows,cols),Float)
900 ypref=zeros((rows,cols),Float)
901
902 for r in xrange(rows):
903 for c in xrange(cols):
904 cf=proj.cfs[r,c]
905 r1,r2,c1,c2 = cf.input_sheet_slice
906 row_centroid,col_centroid = centroid(cf.weights)
907 xcentroid, ycentroid = proj.src.matrix2sheet(
908 r1+row_centroid+0.5,
909 c1+col_centroid+0.5)
910
911 xpref[r][c]= xcentroid
912 ypref[r][c]= ycentroid
913
914 sheet.sheet_views['XCoG']=SheetView((xpref,sheet.bounds), sheet.name,
915 sheet.precedence,topo.sim.time(),sheet.row_precedence)
916
917 sheet.sheet_views['YCoG']=SheetView((ypref,sheet.bounds), sheet.name,
918 sheet.precedence,topo.sim.time(),sheet.row_precedence)
919
920
921 pg= create_plotgroup(name='Center of Gravity',category="Preference Maps",
922 doc='Measure the center of gravity of each ConnectionField in a Projection.',
923 pre_plot_hooks=[measure_cog.instance()],
924 plot_hooks=[topographic_grid.instance(xsheet_view_name="XCoG",ysheet_view_name="YCoG")],
925 normalize='Individually')
926 pg.add_plot('X CoG',[('Strength','XCoG')])
927 pg.add_plot('Y CoG',[('Strength','YCoG')])
928 pg.add_plot('CoG',[('Red','XCoG'),('Green','YCoG')])
929
930
932 """
933 Measures orientation tuning curve(s) of a particular unit using a
934 full-field sine grating stimulus.
935
936 The curve can be plotted at various different values of the
937 contrast (or actually any other parameter) of the stimulus. If
938 using contrast and the network contains an LGN layer, then one
939 would usually specify michelson_contrast as the
940 contrast_parameter. If there is no explicit LGN, then scale
941 (offset=0.0) can be used to define the contrast. Other relevant
942 contrast definitions (or other parameters) can also be used,
943 provided they are defined in PatternPresenter and the units
944 parameter is changed as appropriate.
945 """
946
947 coords = param.Parameter(default=None,doc="""Ignored; here just to suppress warning.""")
948
949 pattern_presenter = param.Callable(
950 default=PatternPresenter(pattern_generator=SineGrating(),
951 contrast_parameter="michelson_contrast"))
952
953
954 create_plotgroup(template_plot_type="curve",name='Orientation Tuning Fullfield',category="Tuning Curves",doc="""
955 Plot orientation tuning curves for a specific unit, measured using full-field sine gratings.
956 Although the data takes a long time to collect, once it is ready the plots
957 are available immediately for any unit.""",
958 pre_plot_hooks=[measure_or_tuning_fullfield.instance()],
959 plot_hooks=[cyclic_tuning_curve.instance(x_axis="orientation")])
960
961
962
964 """
965 Measures orientation tuning curve(s) of a particular unit.
966
967 Uses a circular sine grating patch as the stimulus on the
968 retina.
969
970 The curve can be plotted at various different values of the
971 contrast (or actually any other parameter) of the stimulus. If
972 using contrast and the network contains an LGN layer, then one
973 would usually specify weber_contrast as the contrast_parameter. If
974 there is no explicit LGN, then scale (offset=0.0) can be used to
975 define the contrast. Other relevant contrast definitions (or
976 other parameters) can also be used, provided they are defined in
977 PatternPresenter and the units parameter is changed as
978 appropriate.
979 """
980
981 num_orientation = param.Integer(default=12)
982
983 static_parameters = param.List(default=["size","x","y"])
984
994
995
996 create_plotgroup(template_plot_type="curve",name='Orientation Tuning',category="Tuning Curves",doc="""
997 Measure orientation tuning for a specific unit at different contrasts,
998 using a pattern chosen to match the preferences of that unit.""",
999 pre_plot_hooks=[measure_or_tuning.instance()],
1000 plot_hooks=[cyclic_tuning_curve.instance(x_axis="orientation")],
1001 prerequisites=['XPreference'])
1002
1003
1004
1005
1007 """
1008 Measure receptive field size of one unit of a sheet.
1009
1010 Uses an expanding circular sine grating stimulus at the preferred
1011 orientation and retinal position of the specified unit.
1012 Orientation and position preference must be calulated before
1013 measuring size response.
1014
1015 The curve can be plotted at various different values of the
1016 contrast (or actually any other parameter) of the stimulus. If
1017 using contrast and the network contains an LGN layer, then one
1018 would usually specify weber_contrast as the contrast_parameter. If
1019 there is no explicit LGN, then scale (offset=0.0) can be used to
1020 define the contrast. Other relevant contrast definitions (or
1021 other parameters) can also be used, provided they are defined in
1022 PatternPresenter and the units parameter is changed as
1023 appropriate.
1024 """
1025 size=None
1026
1027 static_parameters = param.List(default=["orientation","x","y"])
1028
1029 num_sizes = param.Integer(default=10,bounds=(1,None),softbounds=(1,50),
1030 doc="Number of different sizes to test.")
1031
1032 max_size = param.Number(default=1.0,bounds=(0.1,None),softbounds=(1,50),
1033 doc="Maximum extent of the grating")
1034
1035 x_axis = param.String(default='size',constant=True)
1036
1037
1039 p=ParamOverrides(self,params)
1040 self.params('sheet').compute_default()
1041 sheet=p.sheet
1042
1043 for coord in p.coords:
1044
1045
1046 self.orientation=pi*self._sheetview_unit(sheet,coord,'OrientationPreference')
1047 self.x=self._sheetview_unit(sheet,coord,'XPreference',default=coord[0])
1048 self.y=self._sheetview_unit(sheet,coord,'YPreference',default=coord[1])
1049 self._compute_curves(p,sheet)
1050
1051
1052
1054 return [Feature(name="phase",range=(0.0,2*pi),step=2*pi/p.num_phase,cyclic=True),
1055 Feature(name="frequency",values=p.frequencies),
1056 Feature(name="size",range=(0.0,self.max_size),step=1.0/p.num_sizes,cyclic=False)]
1057
1058
1059 create_plotgroup(template_plot_type="curve",name='Size Tuning',category="Tuning Curves",
1060 doc='Measure the size preference for a specific unit.',
1061 pre_plot_hooks=[measure_size_response.instance()],
1062 plot_hooks=[tuning_curve.instance(x_axis="size",unit="Diameter of stimulus")],
1063 prerequisites=['OrientationPreference','XPreference'])
1064
1065
1066
1068 """
1069 Measures contrast response curves for a particular unit.
1070
1071 Uses a circular sine grating stimulus at the preferred
1072 orientation and retinal position of the specified unit.
1073 Orientation and position preference must be calulated before
1074 measuring contrast response.
1075
1076 The curve can be plotted at various different values of the
1077 contrast (or actually any other parameter) of the stimulus. If
1078 using contrast and the network contains an LGN layer, then one
1079 would usually specify weber_contrast as the contrast_parameter. If
1080 there is no explicit LGN, then scale (offset=0.0) can be used to
1081 define the contrast. Other relevant contrast definitions (or
1082 other parameters) can also be used, provided they are defined in
1083 PatternPresenter and the units parameter is changed as
1084 appropriate.
1085 """
1086
1087 static_parameters = param.List(default=["size","x","y"])
1088
1089 contrasts = param.List(class_=int,default=[10,20,30,40,50,60,70,80,90,100])
1090
1091 relative_orientations = param.List(class_=float,default=[0.0, pi/6, pi/4, pi/2])
1092
1093 x_axis = param.String(default='contrast',constant=True)
1094
1095 units = param.String(default=" rad")
1096
1098 p=ParamOverrides(self,params)
1099 self.params('sheet').compute_default()
1100 sheet=p.sheet
1101
1102 for coord in p.coords:
1103 orientation=pi*self._sheetview_unit(sheet,coord,'OrientationPreference')
1104 self.curve_parameters=[{"orientation":orientation+ro} for ro in self.relative_orientations]
1105
1106 self.x=self._sheetview_unit(sheet,coord,'XPreference',default=coord[0])
1107 self.y=self._sheetview_unit(sheet,coord,'YPreference',default=coord[1])
1108
1109 self._compute_curves(p,sheet,val_format="%.4f")
1110
1115
1116
1117 create_plotgroup(template_plot_type="curve",name='Contrast Response',category="Tuning Curves",
1118 doc='Measure the contrast response function for a specific unit.',
1119 pre_plot_hooks=[measure_contrast_response.instance()],
1120 plot_hooks=[tuning_curve.instance(x_axis="contrast",unit="%")],
1121 prerequisites=['OrientationPreference','XPreference'])
1122
1123
1124
1126 """
1127 Measures the response to a center sine grating disk and a surround
1128 sine grating ring at different contrasts of the central disk.
1129
1130 The central disk is set to the preferred orientation of the unit
1131 to be measured. The surround disk orientation (relative to the
1132 central grating) and contrast can be varied, as can the size of
1133 both disks.
1134 """
1135
1136 pattern_presenter = param.Callable(
1137 default=PatternPresenter(pattern_generator=OrientationContrast(),
1138 contrast_parameter="weber_contrast"))
1139
1140 size=None
1141
1142
1143 sizecenter=param.Number(default=0.5,bounds=(0,None),doc="""
1144 The size of the central pattern to present.""")
1145
1146 sizesurround=param.Number(default=1.0,bounds=(0,None),doc="""
1147 The size of the surround pattern to present.""")
1148
1149 thickness=param.Number(default=0.5,bounds=(0,None),softbounds=(0,1.5),doc="""Ring thickness.""")
1150
1151 contrastsurround=param.Number(default=100,bounds=(0,100),doc="""Contrast of the surround.""")
1152
1153 contrastcenter=param.Number(default=100,bounds=(0,100),doc="""Contrast of the center.""")
1154
1155 x_axis = param.String(default='orientationsurround',constant=True)
1156
1157 orientation_center = param.Number(default=0.0,softbounds=(0.0,numpy.pi),doc="""
1158 Orientation of the center grating patch""")
1159
1160 units = param.String(default="%")
1161
1162 static_parameters = param.List(default=["x","y","sizecenter","sizesurround","orientationcenter","thickness","contrastcenter"])
1163
1164 curve_parameters=param.Parameter([{"contrastsurround":30},{"contrastsurround":60},{"contrastsurround":80},{"contrastsurround":90}],doc="""
1165 List of parameter values for which to measure a curve.""")
1166
1167 or_surrounds = []
1168
1185
1190
1191 create_plotgroup(template_plot_type="curve",name='Orientation Contrast',category="Tuning Curves",
1192 doc='Measure the response of one unit to a center and surround sine grating disk.',
1193 pre_plot_hooks=[measure_orientation_contrast.instance()],
1194 plot_hooks=[tuning_curve.instance(x_axis="orientationsurround",unit="%")],
1195 prerequisites=['OrientationPreference','XPreference'])
1196
1197
1198
1200
1201 static_parameters = param.List(default=["size","x","y"])
1202
1203 x_axis = param.String(default='contrast',constant=True)
1204
1205 units = param.String(default=" rad")
1206
1208 p=ParamOverrides(self,params)
1209 self.params('sheet').compute_default()
1210 sheet=p.sheet
1211 self.x = 0.0
1212 self.y = 0.0
1213 for coord in p.coords:
1214 self._compute_curves(p,sheet,val_format="%.4f")
1215
1217 return [Feature(name="orientation",values=[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0],cyclic=True),
1218 Feature(name="contrast",values=[100],cyclic=False)]
1219
1220 import types
1221 __all__ = list(set([k for k,v in locals().items()
1222 if isinstance(v,types.FunctionType) or
1223 (isinstance(v,type) and issubclass(v,ParameterizedFunction))
1224 and not v.__name__.startswith('_')]))
1225