-
Notifications
You must be signed in to change notification settings - Fork 38
/
tutorial.m
141 lines (108 loc) · 5.19 KB
/
tutorial.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
%% Load the raw data
rawData = load('exampleData.mat'); % run tutorial_exampleData to generate this
nTrials = rawData.nTrials; % number of trials
unitOfTime = 'ms';
binSize = 1; % TODO some continuous observations might need up/down-sampling if binSize is not 1!?
%% Specify the fields to load
expt = buildGLM.initExperiment(unitOfTime, binSize, [], rawData.param);
expt = buildGLM.registerContinuous(expt, 'LFP', 'Local Field Potential', 1); % continuous obsevation over time
expt = buildGLM.registerContinuous(expt, 'eyepos', 'Eye Position', 2); % 2 dimensional observation
expt = buildGLM.registerTiming(expt, 'dotson', 'Motion Dots Onset'); % events that happen 0 or more times per trial (sparse)
expt = buildGLM.registerTiming(expt, 'dotsoff', 'Motion Dots Offset');
expt = buildGLM.registerTiming(expt, 'saccade', 'Saccade Timing');
expt = buildGLM.registerSpikeTrain(expt, 'sptrain', 'Our Neuron'); % Spike train!!!
expt = buildGLM.registerSpikeTrain(expt, 'sptrain2', 'Neighbor Neuron');
expt = buildGLM.registerValue(expt, 'coh', 'Coherence'); % information on the trial, but not associated with time
expt = buildGLM.registerValue(expt, 'choice', 'Direction of Choice');
%% Convert the raw data into the experiment structure
expt.trial = rawData.trial;
%verifyTrials(expt); % checks if the formats are correct
%% Build 'designSpec' which specifies how to generate the design matrix
% Each covariate to include in the model and analysis is specified.
dspec = buildGLM.initDesignSpec(expt);
binfun = expt.binfun;
bs = basisFactory.makeSmoothTemporalBasis('boxcar', 100, 10, binfun);
bs.B = 0.1 * bs.B;
%% Instantaneous Raw Signal without basis
dspec = buildGLM.addCovariateRaw(dspec, 'LFP', [], bs);
%% Spike history
dspec = buildGLM.addCovariateSpiketrain(dspec, 'hist', 'sptrain', 'History filter');
%% Coupling filter
dspec = buildGLM.addCovariateSpiketrain(dspec, 'coupling', 'sptrain2', 'Coupling from neuron 2');
%% Duration boxcar
dspec = buildGLM.addCovariateBoxcar(dspec, 'dots', 'dotson', 'dotsoff', 'Motion dots stim');
%% Acausal Timing Event
bs = basisFactory.makeSmoothTemporalBasis('boxcar', 300, 8, binfun);
offset = -200;
dspec = buildGLM.addCovariateTiming(dspec, 'saccade', [], [], bs, offset);
%% Coherence
% a box car that depends on the coh value
bs = basisFactory.makeSmoothTemporalBasis('raised cosine', 200, 10, binfun);
stimHandle = @(trial, expt) trial.coh * basisFactory.boxcarStim(binfun(trial.dotson), binfun(trial.dotsoff), binfun(trial.duration));
dspec = buildGLM.addCovariate(dspec, 'cohKer', 'coh-dep dots stimulus', stimHandle, bs);
%% 2-D eye position
bs = basisFactory.makeSmoothTemporalBasis('raised cosine', 40, 4, binfun);
dspec = buildGLM.addCovariateRaw(dspec, 'eyepos', [], bs);
%buildGLM.summarizeDesignSpec(dspec); % print out the current configuration
%% Compile the data into 'DesignMatrix' structure
trialIndices = 1:10; %(nTrials-1); % use all trials except the last one
dm = buildGLM.compileSparseDesignMatrix(dspec, trialIndices);
%% Visualize the design matrix
endTrialIndices = cumsum(binfun([expt.trial(trialIndices).duration]));
X = dm.X(1:endTrialIndices(3),:);
mv = max(abs(X), [], 1); mv(isnan(mv)) = 1;
X = bsxfun(@times, X, 1 ./ mv);
figure(742); clf; imagesc(X);
%buildGLM.visualizeDesignMatrix(dm, 1); % optionally plot the first trial
%% Get the spike trains back to regress against
y = buildGLM.getBinnedSpikeTrain(expt, 'sptrain', dm.trialIndices);
%% Do some processing on the design matrix
dm = buildGLM.removeConstantCols(dm);
colIndices = buildGLM.getDesignMatrixColIndices(dspec, 'LFP');
dm = buildGLM.zscoreDesignMatrix(dm, [colIndices{:}]);
dm = buildGLM.addBiasColumn(dm); % DO NOT ADD THE BIAS TERM IF USING GLMFIT
%% Least squares for initialization
tic
wInit = dm.X \ y;
toc
%% Use matRegress for Poisson regression
% it requires `fminunc` from MATLAB's optimization toolbox
addpath('matRegress')
fnlin = @nlfuns.exp; % inverse link function (a.k.a. nonlinearity)
lfunc = @(w)(glms.neglog.poisson(w, dm.X, y, fnlin)); % cost/loss function
opts = optimoptions(@fminunc, 'Algorithm', 'trust-region', ...
'GradObj', 'on', 'Hessian','on');
[wml, nlogli, exitflag, ostruct, grad, hessian] = fminunc(lfunc, wInit, opts);
wvar = diag(inv(hessian));
%% Alternative maximum likelihood Poisson estimation using glmfit
% [w, dev, stats] = glmfit(dm.X, y, 'poisson', 'link', 'log');
% wvar = stats.se.^2;
%% Visualize
ws = buildGLM.combineWeights(dm, wml);
wvar = buildGLM.combineWeights(dm, wvar);
fig = figure(2913); clf;
nCovar = numel(dspec.covar);
for kCov = 1:nCovar
label = dspec.covar(kCov).label;
subplot(nCovar, 1, kCov);
errorbar(ws.(label).tr, ws.(label).data, sqrt(wvar.(label).data));
title(label);
end
return
%{
%% Specify the model
hasBias = true;
model = buildGLM.buildModel(dspec, 'Poisson', 'exp', hasBias);
%% Do regression
[w, stats] = fitGLM(model, dm, y);
%}
%% Visualize fit
visualizeFit(w, model, dspec, vparam(1)); % ???
%% Simulate from model for test data
testTrialIndices = nTrial; % test it on the last trial
dmTest = compileSparseDesignMatrix(expt, dspec, testTrialIndices);
yPred = generatePrediction(w, model, dmTest);
ySamp = simulateModel(w, model, dmTest);
%% Validate model
gof = goodnessOfFit(w, stats, model, dmTest);
visualizeGoodnessOfFit(gof);