-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetCinvorModelCopy.m
149 lines (137 loc) · 5.29 KB
/
setCinvorModelCopy.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
% setCinvorModel.m
%
% usage: setCinvorModel()
% by: Taosheng Liu
% purpose:
%
% Specify a neuronal model of voxels. Assume neuronal tuning to
% feature ranges from 0 to 360 deg (e.g., direction), and each voxel is made
% up of a mixture of neural tuning functions. In the default setting,
% assume we have 100 voxels, with each voxel containing 180 neurons, which
% are randomly tuning to all possible 360 directions (spaced every 4 deg).
% nvox: number of voxels; neuronsPerVox: number of neurons per voxel
% weighting: distribution of neuronal tuning within a voxel, default to random weighting
% ntuning: number of tuning functions, evenly spaced to cover the 0-360 range
% kappa: concentraion parameter of individual neurons's tuning width, using von Mises function
% myWeights: fixed selection of weights (must use weighting=fixed)
% s
function m = setCinvorModel(e,varargin)
% get arguments
getArgs(varargin, {'kappa=10','amplitude=1','noise=4','nVoxels=78','neuronsPerVox=30','weighting=random','nTuning=30','myWeights=0','uniformFactor=0','tao=0.031','exponent=2'});
% range of orientations span 180
rangeScalFac=360/e.totalRangeDeg;
% sanity checks
if rem(neuronsPerVox, nTuning)~=0
disp('(setCinvorModel) We would like to have each voxel contain all possible tuning values');
keyboard
end
if rem(e.totalRangeDeg, nTuning)~=0
disp('(setCinvorModel) It would make more sense to have n set of possible tuning functions such as it can be divided by 360');
keyboard
end
% how many sets of the complete neuron tuning is in each voxel
nset=neuronsPerVox/nTuning;
%in case we have fewer possible tuning values
setScaleFac=e.totalRangeDeg/nTuning;
prefStimPerSet= setScaleFac*(0:nTuning-1);
prefStim=[];
for stim=1:nset
prefStim=[prefStim,prefStimPerSet];
end
%generate weights for each voxel, returns a nVoxels by neuronsPerVox matrix
if strcmp(weighting,'random')
covarianceMat = zeros(neuronsPerVox);
for i = 1:neuronsPerVox
for j = 1:neuronsPerVox
dist = min(abs(i-j),abs(abs(i-j)-neuronsPerVox));
covarianceMat(i,j) = exp(-((dist/tao).^exponent));
end
end
[V,D]=eig(covarianceMat);D(D<0)=0;covarianceMat=V*D*V'; %approximate as positive semidefinite
mu = zeros(1,neuronsPerVox);
ws = mvnrnd(mu,covarianceMat,nVoxels);
%for i=1:nVoxels
%thisW=uniformFactor*ones(1,neuronsPerVox)+rand(1,neuronsPerVox); %for each voxel, generate random weights for each tuning function
% thisW=thisW/sum(thisW); %normalize these weights, so that they sum to 1
% ws(i,:)=thisW;
%end
elseif strcmp(weighting,'fixed')
if(myWeights == 0)
disp('No weights submitted. Please pass weights.');
keyboard
end
ws = myWeights;
else
disp('(setCinvorModel) Other weighting scheme is not implemented yet');
end
for i = 1:nTuning
angle=d2r(1:e.totalRangeDeg);
neuralResponse(i,1:length(angle)) = circ_vmpdf(angle*rangeScalFac,d2r(prefStim(i))*rangeScalFac, kappa);
end
%put these parameters in the m structure
m.ws=ws;
m.weighting=weighting;
m.nVoxels=nVoxels;
m.neuronsPerVox=neuronsPerVox;
m.nTuning=nTuning;
m.prefStim=prefStim;
m.kappa=kappa;
m.amplitude = amplitude;
m.noise = noise;
m.rangeScaleFac=rangeScalFac;
m.neuralResponse = neuralResponse;
m.uniformFactor = uniformFactor;
m.covarianceMat = covarianceMat;
m.tao = tao;
m.exponent = exponent;
if e.plotModel
clf
mlrSmartfig(e.figTitle,'reuse');clf
% show some neuronal tuning curves
subplot(3,2,1);hold on;
angle=0:0.01:d2r(e.totalRangeDeg);
int=neuronsPerVox/9; %select 9 neurons to plot
for i=1:int:neuronsPerVox
thisNeuralTuning=circ_vmpdf(angle*rangeScalFac,d2r(prefStim(i))*rangeScalFac, kappa);
plot(r2d(angle),thisNeuralTuning,getcolor(ceil(i/int)));
end
ylabel('Response');
xlabel('Stim values');
title('Tuning curves of 10 representative neurons');
% show some voxel tuning curves
subplot(3,2,3); hold on
%plotVox=10; %select 10 voxels to plot
plotVox=nVoxels; %select 10 voxels to plot
voxIdx=1:nVoxels/plotVox:nVoxels;
plotAngles=1:1:e.totalRangeDeg; %stimulus values used to generate voxel tuning curve
for istim=1:length(plotAngles)
thisStimVal=d2r(plotAngles(istim));
resp=[];
%for each voxel, get all neuronal responses for the current stimulus
for j=1:neuronsPerVox
thisPrefStim=d2r(prefStim(j));
resp(:,j)=circ_vmpdf(repmat(thisStimVal,1,plotVox)*rangeScalFac, thisPrefStim*rangeScalFac, kappa);
end
wresp=resp.*ws(voxIdx,:); %weight the neuronal response with pre-generated weights
voxResp(:,istim)=sum(wresp,2); %sum across all neurons within a voxel
end
m.voxResp = voxResp %**
for v=1:plotVox
plot(plotAngles, voxResp(v,:), getcolor(v));
end
ylabel('Response');
xlabel('Stim values');
title('Tuning profile for 10 randomly selected voxels');
%for a single stimulus, plot the neuronal population response
subplot(3,2,5); hold on
testAngle=round(rand*e.totalRangeDeg); %value of the test stimulus, can be any angle
%for each neuronal tuning channel, caculate its response to the test stimulus
for i=1:length(prefStimPerSet)
popResp(i)=circ_vmpdf(d2r(testAngle)*rangeScalFac, d2r(prefStimPerSet(i))*rangeScalFac, kappa);
end
plot(prefStimPerSet, popResp, 'o-','lineWidth',2);
ylabel('Response');
xlabel('Preferred stim');
vline(testAngle);
title(['Neuronal population response to a stimulus at ', num2str(testAngle)]);
end