-
Notifications
You must be signed in to change notification settings - Fork 0
/
fitoriWrapped.m
238 lines (199 loc) · 5.8 KB
/
fitoriWrapped.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
function [pars, err] = fitoriWrapped( oo, rr, ss, fixedpars, oriflag, n, initPars)
% FITORIWRAPPED fit orientation tuning data with orituneWrapped curve,
% which uses wrapped Gaussians (peak repeats every 360 degrees) instead of
% simple Gaussians
%
% syntax is pars = fitoriWrapped(oo,rr), where oo are the orientations,
% rr are the responses, and pars = [Dp, Rp, Rn, Ro, sigma];
%
% fitoriWrapped(xx) assumes oo = xx(1,:) and rr = xx(2,:)
%
% fitori(oo,rr,ss) lets you specify the weights ss
% (default: [])
%
% fitori(oo,rr,ss,fixedpars) lets you specify the value of certain
% parameters (put NaN if you don't want to specify). DEFAULT: [],
% which means all NaNs.
%
% fitoriWrapped(oo,rr,ss,fixedpars,oriflag) if oriflag is set to 'ori' Rn is
% set to zero (useful if data are in the range of 0 to 180).
%
% Example:
% % underlying parameters (see oritune for their meaning)
% realpars = [30 100 10 5 20]
%
% % make the data based on those parameters
% oo = 0:15:360;
% dd = orituneWrapped(realpars,oo) + normrnd( 0, 5, 1, length(oo));
%
% % fit the parameters
% pars = fitoriWrapped(oo,dd);
%
% % look at the results
% figure;
% plot(oo,dd, 'ko', 'MarkerFaceC','k'); hold on
% plot( 0:360, orituneWrapped(pars, 0:360), 'k-' );
% plot( 0:360, orituneWrapped(realpars, 0:360), ':' );
% set(gca,'xtick',0:45:360);
%
% SEE ALSO: orituneWrapped, oritune, circstats, circstats360
% 1997 Matteo Carandini
% 1999 Matteo Carandini, corrected pref ori bias
% 2008-05 LB added oriflag
% 2008-11 LB changed maxRp to the 2*max(rr) instead of max(rr)
% 2009-03 LB fixed a small bug when estimating the start value of sigma
% 2009-03 LB fixed some bugs related to oriflag
% 2009-03 LB added the output argument err
% 2009-05 SK added n
% 2009-07 MC added example of usage
% 2014-06 MC changed behavior of 'ori' flag, used to impose Rp=Rn, but
% that's buggy
% 2015-10 SS intriduced wrapped Gaussians (also orituneWrapped)
% part of the Matteobox toolbox
if nargin < 6
n = 5;
end
if nargin < 7
initPars = [];
end
if nargin <5
oriflag = '';
end
if ~strcmp(oriflag, 'ori') && ~strcmp(oriflag, '')
error('<fitori> Unknown oriflag option %s', oriflag);
end
% if strcmp(oriflag, 'ori')
% fixedpars(3) = 0; % set Rn to zero for now
% end
if nargin >= 4 && isempty(fixedpars)
fixedpars = [ NaN NaN NaN NaN NaN ];
end
if nargin<4, fixedpars = [ NaN NaN NaN NaN NaN ]; end
if nargin <3 || isempty(ss)
ss = zeros(size(rr));
end
if nargin == 1,
oo = oo(1,:);
rr = oo(2,:);
end
oo = oo(:);
rr = rr(:);
ss = ss(:);
if any(size(oo)~=size(rr)),
error('oo and rr have different sizes');
end
if ~any(rr)
err = 0;
pars = [ NaN 0 0 0 NaN ];
return
end
%---------------- make all the rr be>0
minrr = min(rr);
rr = rr-minrr;
%---------------- preferred ori
if isnan(fixedpars(1))
xx = rr.*cos(oo*pi/180);
yy = rr.*sin(oo*pi/180);
a1 = xx(:)\yy(:);
a2 = yy(:)\xx(:);
err1 = norm(yy-a1*xx);
err2 = norm(xx-a2*yy);
if err2 < err1
prefori = 180/pi*atan(1/a2);
else
prefori = 180/pi*atan(a1);
end
minprefori = -180;
maxprefori = 180;
else
prefori = fixedpars(1);
minprefori = fixedpars(1);
maxprefori = fixedpars(1);
end
% plot(xx,a1*xx,'--',a2*yy,yy,'-',xx,yy,'o');
% set(gca,'dataaspectratio',[1 1 1]);
diffangles = abs(angle(exp(i*(oo-prefori)*pi/180)));
%---------------- resp to pref ori
if isnan(fixedpars(2))
rp = mean(rr(find(diffangles==min(diffangles))));
minrp = 0;
maxrp = 2*max(rr);
else
rp = fixedpars(2);
minrp = fixedpars(2);
maxrp = fixedpars(2);
end
%---------------- resp to null ori
if strcmp(oriflag, 'ori')
rn = 0;
minrn = 0;
maxrn = 0;
elseif isnan(fixedpars(3))
rn = mean(rr(find(diffangles==max(diffangles))));
minrn = 0;
maxrn = max(rr);
rn = min(rn, maxrn);
else
rn = fixedpars(3);
minrn = fixedpars(3);
maxrn = fixedpars(3);
end
%--------------- min resp
if isnan(fixedpars(4))
r0 = 0;
minr0 = -max(rr)/5; % allow mildly negative baselines
maxr0 = max(rr);
else
r0 = fixedpars(4)-minrr;
minr0 = fixedpars(4)-minrr;
maxr0 = fixedpars(4)-minrr;
end
%--------------- tuning width sigma
if isnan(fixedpars(5))
minsigma = 0.7*median(diff(unique(oo))); % MC changed 2015-04-16
% minsigma = median(diff(unique(oo)))/2; % 1/2 spacing bet samples
maxsigma = 80;
sigmas = minsigma:3:maxsigma;
errs = zeros(size(sigmas));
for isigma = 1:length(sigmas)
errs(isigma) = norm( oritune([prefori rp rn r0 sigmas(isigma)],oo)-rr )^2;
end
sigma = sigmas(find(errs == min(errs),1));
else
sigma = fixedpars(5);
minsigma = fixedpars(5);
maxsigma = fixedpars(5);
end
if isempty(initPars);
initPars = [ prefori rp rn r0 sigma ];
end
%---------------------------- finally, do the fit -------------------------
[ err, pars ] = fitit( 'orituneWrapped', rr,...
[ minprefori minrp minrn minr0 minsigma ],...
initPars,...
[ maxprefori maxrp maxrn maxr0 maxsigma ],...
[0 1e-4 1e-4 n 400 1], oo, ss );
% [err,pars,exitflag,output] = lsqfit( 'oritune', rr,...
% [ -180 minrp minrn minr0 minsigma ],...
% [ prefori rp rn r0 sigma ],...
% [ 180 maxrp maxrn maxr0 maxsigma ],...
% [], oo, ss );
% add minrr back to the pars:
pars(4) = pars(4)+minrr;
% rr = rr + minrr
% plot( oo, rr, 'o', 0:360, oritune(pars,0:360), '-' )
%-------------------------- make sure Rp is bigger than Rn -------------------
pp = num2cell(pars);
[Dp, Rp, Rn, Ro, sigma] = deal(pp{:});
% if strcmp(oriflag, 'ori')
% if Dp < 0
% Rp = Rn; Dp = mod(Dp+180,360);
% else
% Rn = Rp;
% end
% end
if Rp<Rn
Dp = mod(Dp+180,360);
[Rp, Rn] = deal(Rn, Rp);
end
pars = [Dp, Rp, Rn, Ro, sigma];