1 """
2 Vision-specific analysis functions.
3
4 $Id: featureresponses.py 7714 2008-01-24 16:42:21Z antolikjan $
5 """
6 __version__='$Revision: 7714 $'
7
8 from math import pi,sin,cos
9
10 import numpy
11 from numpy.oldnumeric import Float
12 from numpy import zeros, array, size, object_
13
14
15 import param
16 from param import normalize_path
17
18 try:
19 import matplotlib
20 import pylab
21 except ImportError:
22 param.Parameterized(name=__name__).warning("Could not import matplotlib; module will not be useable.")
23 from topo.command.basic import ImportErrorRaisingFakeModule
24 pylab = ImportErrorRaisingFakeModule("matplotlib")
25
26
27
28
29 import topo
30 from topo.base.cf import CFSheet
31 from topo.base.sheetview import SheetView
32 from topo.plotting.plotgroup import create_plotgroup
33 from topo.command.analysis import measure_sine_pref
34
35 from topo import numbergen
36
37 max_value = 0
38 global_index = ()
39
53
54
55
57 global global_index
58 global max_value
59 """This function expects as an input a object of type FullMatrix which contains
60 responses of all neurons in a sheet to stimuly with different varying parameter values.
61 One of these parameters (features) has to be phase. In such case it computes the classic
62 modulation ratio (see Hawken et al. for definition) for each neuron and returns them as a matrix.
63 """
64 rows,cols = full_matrix.matrix_shape
65 complexity = zeros(full_matrix.matrix_shape)
66 complex_matrix = zeros(full_matrix.matrix_shape,object_)
67 fftmeasure = zeros(full_matrix.matrix_shape,Float)
68 i = 0
69 for f in full_matrix.features:
70 if f.name == "phase":
71
72 phase_index = i
73 break
74 i=i+1
75 sum = 0.0
76 res = 0.0
77 average = 0.0
78 for x in range(rows):
79 for y in range(cols):
80 complex_matrix[x,y] = []
81 max_value=-0.01
82 global_index = ()
83 _complexity_rec(x,y,(),0,full_matrix)
84
85
86
87 iindex = array(global_index)
88 sum = 0.0
89 for i in range(size(full_matrix.features[phase_index].values)):
90 iindex[phase_index] = i
91 sum = sum + full_matrix.full_matrix[tuple(iindex.tolist())][x][y]
92
93
94 average = sum / float(size(full_matrix.features[phase_index].values))
95
96 res = 0.0
97
98 for i in range(size(full_matrix.features[phase_index].values)):
99 iindex[phase_index] = i
100 res = res + abs(full_matrix.full_matrix[tuple(iindex.tolist())][x][y] - average)
101 complex_matrix[x,y] = complex_matrix[x,y] + [full_matrix.full_matrix[tuple(iindex.tolist())][x][y]]
102
103 if x==43 and y==43:
104 pylab.figure()
105 ax = pylab.subplot(111)
106 z = complex_matrix[x,y][:]
107 z.append(z[0])
108 pylab.plot(z,linewidth=4)
109 pylab.axis(xmin=0.0,xmax=numpy.pi)
110 ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(4))
111 pylab.xticks([0,len(z)/2,len(z)-1], ['0','pi/2','pi'])
112 pylab.savefig(normalize_path(str(topo.sim.time()) + str(complex_matrix[x,y][0])+ 'modulation_response[43,43].png'))
113
114 if x==45 and y==45:
115 pylab.figure()
116 ax = pylab.subplot(111)
117 z = complex_matrix[x,y][:]
118 z.append(z[0])
119 pylab.plot(z,linewidth=4)
120 pylab.axis(xmin=0.0,xmax=numpy.pi)
121 ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(4))
122 pylab.xticks([0,len(z)/2,len(z)-1], ['0','pi/2','pi'])
123 pylab.savefig(normalize_path(str(topo.sim.time()) + str(complex_matrix[x,y][0])+ 'modulation_response[45,45].png'))
124
125 fft = numpy.fft.fft(complex_matrix[x,y]+complex_matrix[x,y]+complex_matrix[x,y]+complex_matrix[x,y],2048)
126 first_har = 2048/len(complex_matrix[0,0])
127 if abs(fft[0]) != 0:
128 fftmeasure[x,y] = 2 *abs(fft[first_har]) /abs(fft[0])
129 else:
130 fftmeasure[x,y] = 0
131 return fftmeasure
132
133
135
136 """ This function allows and alternative computation of orientation tuning curve where
137 for each given orientation the response is computed as a maximum of AC or DC component
138 across the phases instead of the maximum used as a standard in Topographica"""
139
140 i = 0
141 for f in full_matrix.features:
142 if f.name == "phase":
143 phase_index = i
144 if f.name == "orientation":
145 orientation_index = i
146 if f.name == "frequency":
147 frequency_index = i
148 i=i+1
149 print sheet.curve_dict
150 if not sheet.curve_dict.has_key("orientationACDC"):
151 sheet.curve_dict["orientationACDC"]={}
152 sheet.curve_dict["orientationACDC"][curve_label]={}
153
154 rows,cols = full_matrix.matrix_shape
155 for o in xrange(size(full_matrix.features[orientation_index].values)):
156 s_w = zeros(full_matrix.matrix_shape)
157 for x in range(rows):
158 for y in range(cols):
159 or_response=[]
160 for p in xrange(size(full_matrix.features[phase_index].values)):
161 index = [0,0,0]
162 index[phase_index] = p
163 index[orientation_index] = o
164 index[frequency_index] = 0
165 or_response.append(full_matrix.full_matrix[tuple(index)][x][y])
166
167 fft = numpy.fft.fft(or_response+or_response+or_response+or_response,2048)
168 first_har = 2048/len(or_response)
169 s_w[x][y] = numpy.maximum(2 *abs(fft[first_har]),abs(fft[0]))
170 s = SheetView((s_w,sheet.bounds), sheet.name , sheet.precedence, topo.sim.time(),sheet.row_precedence)
171 sheet.curve_dict["orientationACDC"][curve_label].update({full_matrix.features[orientation_index].values[o]:s})
172
173
174
176 r = numbergen.UniformRandom(seed=1023)
177 preference_map = topo.sim[sheet_name].sheet_views['PhasePreference']
178 offset_magnitude = 0.03
179 datax = []
180 datay = []
181 (v,bb) = preference_map.view()
182 for z in zeros(66):
183 x = (r() - 0.5)*2*diameter
184 y = (r() - 0.5)*2*diameter
185 rand = r()
186 xoff = sin(rand*2*pi)*offset_magnitude
187 yoff = cos(rand*2*pi)*offset_magnitude
188 xx = max(min(x+xoff,diameter),-diameter)
189 yy = max(min(y+yoff,diameter),-diameter)
190 x = max(min(x,diameter),-diameter)
191 y = max(min(y,diameter),-diameter)
192 [xc1,yc1] = topo.sim[sheet_name].sheet2matrixidx(xx,yy)
193 [xc2,yc2] = topo.sim[sheet_name].sheet2matrixidx(x,y)
194 if((xc1==xc2) & (yc1==yc2)): continue
195 datax = datax + [v[xc1,yc1]]
196 datay = datay + [v[xc2,yc2]]
197
198 for i in range(0,len(datax)):
199 datax[i] = datax[i] * 360
200 datay[i] = datay[i] * 360
201 if(datay[i] > datax[i] + 180): datay[i]= datay[i]- 360
202 if((datax[i] > 180) & (datay[i]> 180)): datax[i] = datax[i] - 360; datay[i] = datay[i] - 360
203 if((datax[i] > 180) & (datay[i] < (datax[i]-180))): datax[i] = datax[i] - 360;
204
205 f = pylab.figure()
206 ax = f.add_subplot(111, aspect='equal')
207 pylab.plot(datax,datay,'ro')
208 pylab.plot([0,360],[-180,180])
209 pylab.plot([-180,180],[0,360])
210 pylab.plot([-180,-180],[360,360])
211 ax.axis([-180,360,-180,360])
212 pylab.xticks([-180,0,180,360], [-180,0,180,360])
213 pylab.yticks([-180,0,180,360], [-180,0,180,360])
214 pylab.grid()
215 pylab.savefig(normalize_path(str(topo.sim.timestr()) + sheet_name + "_scatter.png"))
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
246 """
247 Compute modulation ratio for each neuron, to distinguish complex from simple cells.
248
249 Uses full_matrix data obtained from measure_or_pref().
250
251 If there is a sheet named as specified in simple_sheet_name,
252 also plots its phase preference as a scatter plot.
253 """
254 import topo
255 measured_sheets = [s for s in topo.sim.objects(CFSheet).values()
256 if hasattr(s,'measure_maps') and s.measure_maps]
257
258 for sheet in measured_sheets:
259
260 complx = array(complexity(full_matrix[sheet]))/2.0
261
262 sheet.sheet_views['ComplexSelectivity']=SheetView((complx,sheet.bounds), sheet.name , sheet.precedence, topo.sim.time(),sheet.row_precedence)
263 import topo.command.pylabplot
264 topo.command.pylabplot.plot_modulation_ratio(full_matrix,simple_sheet_name=simple_sheet_name,complex_sheet_name=complex_sheet_name,filename=filename)
265
266
267 try:
268 phase_preference_scatter_plot(simple_sheet_name,diameter=0.24999)
269 except AttributeError:
270 print "Skipping phase preference scatter plot; could not analyze region %s." \
271 % simple_sheet_name
272
273
275 """Macro for measuring orientation preference and then analyzing its complexity."""
281
282
283 pg= create_plotgroup(name='Orientation Preference and Complexity',category="Preference Maps",
284 doc='Measure preference for sine grating orientation.',
285 pre_plot_hooks=[measure_and_analyze_complexity.instance()])
286 pg.add_plot('Orientation Preference',[('Hue','OrientationPreference')])
287 pg.add_plot('Orientation Preference&Selectivity',[('Hue','OrientationPreference'),
288 ('Confidence','OrientationSelectivity')])
289 pg.add_plot('Orientation Selectivity',[('Strength','OrientationSelectivity')])
290 pg.add_plot('Modulation Ratio',[('Strength','ComplexSelectivity')])
291 pg.add_plot('Phase Preference',[('Hue','PhasePreference')])
292 pg.add_static_image('Color Key','command/or_key_white_vert_small.png')
293