-
Notifications
You must be signed in to change notification settings - Fork 8
/
sample_params.m
649 lines (564 loc) · 26.1 KB
/
sample_params.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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
function [posterior, mcmc] = sample_params(trace, params, times_init, amps_init, taus_init)
% SAMPLE_PARAMS Uses the Gibbs sampler described in Merel et al, J. Neuro.
% Meths. 2016 to sample from the posterior of the latent variables given
% some noisy physiological trace (e.g. a voltage-clamp or trace imaging
% trace)
% [posterior, mcmc] = SAMPLE_PARAMS(trace, params, times_init, amps_init,
% taus_init) samples the posterior distribution of the parameters given
% some phsyiological trace. The inputs to the function are
% trace a 1 x T vector of the noisy data
% params a struct containging all of the necessary values for
% running the algorithm. See the code for GET_PARAMS for
% details.
% times_init an N x 1 vector of the initialization times
% amps_init an N x 1 vector of the initialization amplitudes
% taus_init an N x 1 vector of the initialization time constants
% where K is the number of initial events.
%
% The outputs from this function are posterior and mcmc. The struct
% posterior has these fields:
% amp a 1 x L* vector of amplitude samples
% base a 1 x L vector of baseline samples
% tau1 a 1 x L* vector of rise tau samples
% tau2 a 1 x L* vector of fall tau samples
% num_events a 1 x L vector of the number of event samples
% phi an L x 3 matrix of phi samples
% noise a 1 x L vector of samples for the noise variance
% obj a 1 x L vector of the objective function value for each sweep
% times a 1 x L* vector of the event time samples
% where L is the number of Gibbs sweeps (including burn-in) and L* is the
% the sum number of infered events for each sweep (i.e.
% sum(posterior.num_events). This structure is more memory efficient than
% other options. Using this structure is not too difficult. The features
% postiorior.amp(i), postiorior.tau1(i), postiorior.tau2(i), and
% postiorior.times(i) all come from the same event. And the events from
% i-th sweep can be indexed like this (ignoring boundary cases):
% posterior.amp(sum(posterior.num_events(1:i-1))+1:...
% sum(posterior.num_events(1:i-1))+posterior.num_events(i))
% The output mcmc is a stuct which contains some information on the
% accept/reject statistics for the sampler. It has fields:
% addMoves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the add proposals
% timeMoves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the time proposals
% dropMoves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the drop proposals
% ampMoves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the amplitude proposals
% tau1Moves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the rise time proposals
% tau2Moves a 1 x 2 vector where the first entry is the number of
% accepts and the second is the total number of proposals
% for the fall time proposals
% number of samples in the trace
T = length(trace);
% unpack params struct for convenience
% see function get_params.m for information on the parameters for the
% algorithim
% params for priors
% rate
p_event=params.p_event;
% time constant bounds
tau1_min = params.tau1_min/params.dt;
tau1_max = params.tau1_max/params.dt;
tau2_min = params.tau2_min/params.dt;
tau2_max = params.tau2_max/params.dt;
% event amplitude bounds
a_min = params.a_min;
a_max = params.a_max;
% baseline bounds
b_min = params.b_min;
b_max = params.b_max;
% ar noise process params
% see Chib and Greenberg, Journal of Econometrics, 1994
% number of timesteps for filter
p = params.p;
% filter coefficient prior mean (MVN prior)
phi_0 = params.phi_0;
% precision/inverse covariance for filter coefficient prior (MVN)
Phi_0 = params.Phi_0;
% params for inverse gamma prior on white-noise noise variance
nu_0 = params.nu_0;
sig2_0 = params.sig2_0;
% if we don't want to use only a subset of the trace for noise estimation,
% then set subset to full trace
if isempty(params.noise_est_subset)
params.noise_est_subset = 1:length(trace);
end
% parameters to balance sampling rates for different params
adddrop = params.add_drop_sweeps;
event_time_sweeps = params.event_time_sweeps;
amp_sweeps = params.amp_sweeps;
baseline_sweeps = params.baseline_sweeps;
tau1_sweeps = params.tau1_sweeps;
tau2_sweeps = params.tau2_sweeps;
% initial proposal variances for different params
time_proposal_var = params.time_proposal_var/params.dt;
tau1_std = params.tau1_prop_std/params.dt; %proposal variance of tau parameters
tau2_std = params.tau2_prop_std/params.dt; %proposal variance of tau parameters
a_std = params.amp_prop_std; %proposal variance of amplitude
b_std = params.baseline_prop_std; %propasal variance of baseline
% max length of event
event_samples = params.event_samples;
ef_init = genEfilt([mean([tau1_min tau1_max]) mean([tau2_min tau2_max])],event_samples);
%dont let events get within x bins of eachother
exclusion_bound = params.exclusion_bound/params.dt;
% number of gibbs sweeps to do
num_sweeps = params.num_sweeps;
burn_in_sweeps = params.burn_in_sweeps;
total_sweeps = num_sweeps + burn_in_sweeps;
% initialize arrays to hold samples and objective
samples_a = [];
samples_b = [];
samples_s = [];
samples_tau_rise = [];
samples_tau_fall = [];
samples_phi = [];
samples_noise = [];
N_sto = [];
objective = [];
%initialize arrays for event features and noiseless trace
this_samp_amps = amps_init; % amplitudes
this_samp_times = times_init;
this_samp_taus = cell(length(times_init),1); % array of lists of event this_samp_taus
phi = [1 zeros(1,p)];
efs = cell(1,length(times_init));
N = length(times_init);
% init some values
noiseless_trace = zeros(1,T); %initial trace is set to baseline
baseline = min(trace); %initial baseline value
N = length(this_samp_times); %number of events in trace
residual = trace - noiseless_trace; %trace - prediction
% prior expected number of events for this trace
e_num_events = p_event*T;
if params.noise_known
phi = params.phi_known;
noise_var = params.noise_var_known;
else
noise_var = params.noise_var_init;
end
% add initial events
for i = 1:length(this_samp_times)
% proposed tau and build exp filter
this_samp_taus{i} = taus_init(i,:);
efs{i} = genEfilt(this_samp_taus{i}, event_samples);
% add event
[~, noiseless_trace, residual] = ...
add_event(this_samp_times(1:i-1),noiseless_trace,residual,efs{i},...
amps_init(i),this_samp_taus{i},trace,this_samp_times(i),i);
end
if isempty(taus_init)
taus_init = [mean([tau1_min tau1_max]) mean([tau2_min tau2_max])];
end
% re-estimate the ar process parameters
if ~params.noise_known
if p > 0
e = residual(params.noise_est_subset)'; % this is Tx1 (after transpose)
E = [];
for ip = 1:p
E = [E e((p+1-ip):(end-ip))];
end
e = e((p+1):end);
Phi_n = Phi_0 + noise_var^(-1)*(E'*E); %typo in paper
phi_cond_mean = Phi_n\(Phi_0*phi_0 + noise_var^(-1)*E'*e);
sample_phi = 1;
while sample_phi
phi = [1 mvnrnd(phi_cond_mean,inv(Phi_n))];
phi_poly = -phi;
phi_poly(1) = 1;
if all(abs(roots(phi_poly))<1) %check stability
sample_phi = 0;
end
end
end
% re-estimate the noise variance
df = (numel(noiseless_trace(params.noise_est_subset))); %DOF (possibly numel(ci(ti,:))-1)
d1 = -predAR(residual(params.noise_est_subset),phi,p,1 )/df;
nu0 = nu_0; %nu_0 or 0
d0 = sig2_0; %sig2_0 or 0
A_samp = 0.5 * (df - p + nu0); %nu0 is prior
B_samp = 1/(0.5 * df * (d1 + d0)); %d0 is prior
noise_var = 1/gamrnd(A_samp,B_samp); %this could be inf but it shouldn't be
end
%% loop over sweeps to generate samples
addMoves = [0 0]; %first elem is number successful, second is number total
dropMoves = [0 0];
timeMoves = [0 0];
ampMoves = [0 0];
tau1Moves = [0 0];
tau2Moves = [0 0];
for i = 1:total_sweeps
% do event time moves
for ii = 1:event_time_sweeps
for ni = 1:N%for each event
proposed_time = this_samp_times(ni)+(time_proposal_var*randn); %add in noise
% bouncing off edges
while proposed_time>T || proposed_time<0
if proposed_time<0
proposed_time = -(proposed_time);
elseif proposed_time>T
proposed_time = T-(proposed_time-T);
end
end
%if its too close to another event, reject this move
if any(abs(proposed_time-this_samp_times([1:(ni-1) (ni+1):end]))<exclusion_bound)
continue
end
%create the proposal this_samp_times_tmp and noiseless_trace_tmp
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] = ...
remove_event(this_samp_times,noiseless_trace,residual,...
efs{ni},this_samp_amps(ni),this_samp_taus{ni},trace,this_samp_times(ni),ni);
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] = ...
add_event(this_samp_times_tmp,noiseless_trace_tmp,...
residual_tmp,efs{ni},this_samp_amps(ni),this_samp_taus{ni},trace,proposed_time,ni);
%accept or reject
prior_ratio = 1;
ratio = exp(sum((1/(2*noise_var))*...
( predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ) )))*prior_ratio;
if ratio>1 %accept
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
timeMoves = timeMoves + [1 1];
time_proposal_var = time_proposal_var + .1*rand*time_proposal_var/(i);
elseif rand<ratio %accept
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
timeMoves = timeMoves + [1 1];
time_proposal_var = time_proposal_var + .1*rand*time_proposal_var/(i);
else
%reject - do nothing
time_proposal_var = time_proposal_var - .1*rand*time_proposal_var/(i);
timeMoves = timeMoves + [0 1];
end
end
end
% update amplitude of each event
for ii = 1:amp_sweeps
for ni = 1:N
%sample with random walk proposal
proposed_amp = this_samp_amps(ni)+(a_std*randn); %with bouncing off min and max
while proposed_amp>a_max || proposed_amp<a_min
if proposed_amp<a_min
proposed_amp = a_min+(a_min-proposed_amp);
elseif proposed_amp>a_max
proposed_amp = a_max-(proposed_amp-a_max);
end
end
% update sample with proposal
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] = ...
remove_event(this_samp_times,noiseless_trace,residual,...
efs{ni},this_samp_amps(ni),this_samp_taus{ni},trace,this_samp_times(ni),ni);
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] = ...
add_event(this_samp_times_tmp,noiseless_trace_tmp,residual_tmp,...
efs{ni},proposed_amp,this_samp_taus{ni},trace,this_samp_times(ni),ni);
this_samp_amps_tmp = this_samp_amps;
this_samp_amps_tmp(ni) = proposed_amp;
%accept or reject - include a prior?
prior_ratio = 1;
ratio = exp(sum((1/(2*noise_var))*( predAR(residual_tmp,phi,p,1) - predAR(residual,phi,p,1) )))*prior_ratio;
if ratio>1 %accept
this_samp_amps = this_samp_amps_tmp;
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
ampMoves = ampMoves + [1 1];
a_std = a_std + 2*.1*rand*a_std/(i);
elseif rand<ratio %accept
this_samp_amps = this_samp_amps_tmp;
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
ampMoves = ampMoves + [1 1];
a_std = a_std + 2*.1*rand*a_std/(i);
else
%reject - do nothing
a_std = a_std - .1*rand*a_std/(i);
ampMoves = ampMoves + [0 1];
end
end
end
% update baseline of each trial
for ii = 1:baseline_sweeps
%sample with random walk proposal
proposed_baseline = baseline+(b_std*randn); %with bouncing off min and max
while proposed_baseline>b_max || proposed_baseline<b_min
if proposed_baseline<b_min
proposed_baseline = b_min+(b_min-proposed_baseline);
elseif proposed_baseline>b_max
proposed_baseline = b_max-(proposed_baseline-b_max);
end
end
% update with proposal
[noiseless_trace_tmp, residual_tmp] = ...
remove_base(noiseless_trace,residual,baseline,trace);
[noiseless_trace_tmp, residual_tmp] = ...
add_base(noiseless_trace_tmp,residual_tmp,proposed_baseline,trace);
%accept or reject - include a prior?
prior_ratio = 1;
ratio = exp(sum((1/(2*noise_var))*(predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ))))*prior_ratio;
if ratio>1 %accept
baseline = proposed_baseline;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
b_std = b_std + 2*.1*rand*b_std/(i);
elseif rand<ratio %accept
baseline = proposed_baseline;
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
b_std = b_std + 2*.1*rand*b_std/(i);
else
%reject - do nothing
b_std = b_std - .1*rand*b_std/(i);
end
end
if i>1
%% this is the section that updates the number of events (add/drop)
% loop over add/drop a few times
% define insertion proposal distribution as the likelihood function
% define removal proposal distribution as uniform over events
% perhaps better is to choose smarter removals.
for ii = 1:adddrop
%propose a uniform add
%pick a random point
proposed_time = T*rand;
%dont add if we have too many events or the proposed new location
%is too close to another one
if ~any(abs(proposed_time-this_samp_times)<exclusion_bound)
%must add event to each trial (at mean location or sampled -- more appropriate if sampled, but make sure no trial's event violates exclusion)
residual_tmp = residual;
% initialize amplitude based on value of trace around event
start_ind = max(1,floor(proposed_time));
end_ind = min(start_ind + params.a_init_window*2,length(residual));
[local_max,tmpi_tmp] = max(residual(start_ind:end_ind));
proposed_time = tmpi_tmp + start_ind - 1;
a_init = max(local_max + a_std*randn,a_min);
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] =...
add_event(this_samp_times,noiseless_trace,residual_tmp,...
ef_init,a_init,taus_init(1,:),trace,proposed_time, N+1);
this_samp_amps_tmp = [this_samp_amps a_init];
%accept or reject
% prior probs
fprob = 1;%1/T(1);%forward probability
rprob = 1;%1/(N+1);%reverse (remove at that spot) probability
ratio = exp(sum((1./(2*noise_var)).*...
( predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ) )))*...
(rprob/fprob)*e_num_events/(N+1);
if (ratio>1)||(ratio>rand) %accept
this_samp_amps = this_samp_amps_tmp;
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
this_samp_taus{N+1} = taus_init(1,:);
efs{N+1} = ef_init;
residual = residual_tmp;
addMoves = addMoves + [1 1];
else
%reject - do nothing
addMoves = addMoves + [0 1];
end
N = length(this_samp_times);
end
% delete
if N>0%i.e. we if have at least one event
%propose a uniform removal
proposed_event_i = randi(N);%pick one of the events at random
%must remove event from each trial
residual_tmp = residual;
%always remove the ith event (the ith event of each trial is linked)
[this_samp_times_tmp, noiseless_trace_tmp, residual_tmp] =...
remove_event(this_samp_times,noiseless_trace,residual_tmp,...
efs{proposed_event_i},this_samp_amps(proposed_event_i),...
this_samp_taus{proposed_event_i},trace,this_samp_times(proposed_event_i),...
proposed_event_i);
%accept or reject
%reverse probability
rprob = 1;%1/T(1);
%compute forward prob
fprob = 1;%1/N;
%posterior times reverse prob/forward prob
ratio = exp(sum((1./(2*noise_var)).*( predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ) )))*(rprob/fprob)*N/e_num_events;%((T(1)-e_num_events(1))/e_num_events(1));
if (ratio>1)||(ratio>rand)%accept
this_samp_amps(proposed_event_i) = [];
this_samp_times = this_samp_times_tmp;
noiseless_trace = noiseless_trace_tmp;
this_samp_taus(proposed_event_i) = [];
efs(proposed_event_i) = [];
residual = residual_tmp;
dropMoves = dropMoves + [1 1];
else
%reject - do nothing
dropMoves = dropMoves + [0 1];
end
N = length(this_samp_times);
end
end
end
%% this is the section that updates rise tau
% update tau (via random walk sampling)
for ii = 1:tau1_sweeps
for ni = 1:N
% propose new rise tau
proposed_tau = this_samp_taus{ni};
proposed_tau(1) = proposed_tau(1)+(tau1_std*randn); %with bouncing off min and max
tau_max = min([proposed_tau(2) tau1_max]);
tau_min = tau1_min;
while proposed_tau(1)>tau_max || proposed_tau(1)<tau_min
if proposed_tau(1) < tau_min
proposed_tau(1) = tau_min+(tau_min-proposed_tau(1));
elseif proposed_tau(1)>tau_max
proposed_tau(1) = tau_max -(proposed_tau(1)-tau_max);
end
end
ef_ = genEfilt(proposed_tau,event_samples);%exponential filter
% udpate with proposal
[~, noiseless_trace_tmp, residual_tmp] = ...
remove_event(this_samp_times,noiseless_trace,residual,...
efs{ni},this_samp_amps(ni),this_samp_taus{ni},trace,...
this_samp_times(ni),ni);
[~, noiseless_trace_tmp, residual_tmp] = ...
add_event(this_samp_times,noiseless_trace_tmp,residual_tmp,...
ef_,this_samp_amps(ni),proposed_tau,trace,this_samp_times(ni),ni);
%accept or reject
prior_ratio = 1;
% prior_ratio = (gampdf(proposed_tau(1),1.5,1))/(gampdf(tau(1),1.5,1));
ratio = exp(sum(sum((1./(2*noise_var)).*...
( predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ) ))))*prior_ratio;
if ratio>1 %accept
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
this_samp_taus{ni} = proposed_tau;
efs{ni} = ef_;
tau1Moves = tau1Moves + [1 1];
tau1_std = tau1_std + .1*rand*tau1_std/(i);
elseif rand<ratio %accept
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
this_samp_taus{ni} = proposed_tau;
efs{ni} = ef_;
tau1Moves = tau1Moves + [1 1];
tau1_std = tau1_std + .1*rand*tau1_std/(i);
else
%reject - do nothing
tau1_std = tau1_std - .1*rand*tau1_std/(i);
tau1Moves = tau1Moves + [0 1];
end
end
end
%% this is the section that updates fall tau
% update tau (via random walk sampling)
for ii = 1:tau2_sweeps
for ni = 1:N
% update both tau values
proposed_tau = this_samp_taus{ni};
proposed_tau(2) = proposed_tau(2)+(tau2_std*randn);
tau_min = max([proposed_tau(1) tau2_min]);
tau_max = tau2_max;
while proposed_tau(2)>tau_max || proposed_tau(2)<proposed_tau(1)
if proposed_tau(2)<tau_min
proposed_tau(2) = tau_min+(tau_min-proposed_tau(2));
elseif proposed_tau(2)>tau_max
proposed_tau(2) = tau_max-(proposed_tau(2)-tau_max);
end
end
ef_ = genEfilt(proposed_tau,event_samples);%exponential filter
% update proposal
[~, noiseless_trace_tmp, residual_tmp] = ...
remove_event(this_samp_times,noiseless_trace,residual,...
efs{ni},this_samp_amps(ni),this_samp_taus{ni},trace,this_samp_times(ni),ni);
[~, noiseless_trace_tmp, residual_tmp] = ...
add_event(this_samp_times,noiseless_trace_tmp,residual_tmp,...
ef_,this_samp_amps(ni),proposed_tau,trace,this_samp_times(ni),ni);
%accept or reject
prior_ratio = 1;
% prior_ratio = gampdf(proposed_tau(2),12,1)/gampdf(tau(2),12,1);
ratio = exp(sum(sum((1./(2*noise_var)).*( predAR(residual_tmp,phi,p,1 ) - predAR(residual,phi,p,1 ) ))))*prior_ratio;
if ratio>1 %accept
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
this_samp_taus{ni} = proposed_tau;
efs{ni} = ef_;
tau2Moves = tau2Moves + [1 1];
tau2_std = tau2_std + .1*rand*tau2_std/(i);
elseif rand<ratio %accept
noiseless_trace = noiseless_trace_tmp;
residual = residual_tmp;
this_samp_taus{ni} = proposed_tau;
efs{ni} = ef_;
tau2Moves = tau2Moves + [1 1];
tau2_std = tau2_std + .1*rand*tau2_std/(i);
else
%reject - do nothing
tau2_std = tau2_std - .1*rand*tau2_std/(i);
tau2Moves = tau2Moves + [0 1];
end
end
end
% re-estimate the ar process parameters
if ~params.noise_known
if p>0 %&& i>(num_sweeps/100)
e = residual(params.noise_est_subset)'; % this is Tx1 (after transpose)
E = [];
for ip = 1:p
E = [E e((p+1-ip):(end-ip))];
end
e = e((p+1):end);
Phi_n = Phi_0 + noise_var^(-1)*(E'*E); %typo in paper
phi_cond_mean = Phi_n\(Phi_0*phi_0 + noise_var^(-1)*E'*e);
% keyboard
sample_phi = 1;
while sample_phi
phi = [1 mvnrnd(phi_cond_mean,inv(Phi_n))];
phi_poly = -phi;
phi_poly(1) = 1;
if all(abs(roots(phi_poly))<1) %check stability
sample_phi = 0;
end
end
end
% re-estimate the noise variance
df = (numel(noiseless_trace(params.noise_est_subset))); %DOF (possibly numel(ci(ti,:))-1)
d1 = -predAR(residual(params.noise_est_subset),phi,p,1 )/df;
nu0 = nu_0; %nu_0 or 0
d0 = sig2_0; %sig2_0 or 0
A_samp = 0.5 * (df - p + nu0); %nu0 is prior
B_samp = 1/(0.5 * df * (d1 + d0)); %d0 is prior
noise_var = 1/gamrnd(A_samp,B_samp); %this could be inf but it shouldn't be
end
%store samples
N_sto = [N_sto N];
samples_a = [samples_a this_samp_amps]; %trial amplitudes
samples_b = [samples_b baseline]; %trial baselines
samples_s = [samples_s this_samp_times]; %shared events
for event_i = 1:N
samples_tau_rise = [samples_tau_rise this_samp_taus{event_i}(1)]; %save tau values
samples_tau_fall = [samples_tau_fall this_samp_taus{event_i}(2)];
end
samples_phi = [samples_phi; phi];
samples_noise = [samples_noise noise_var];
%store overall logliklihood as well
objective = [objective -T/2*log(noise_var) + predAR(residual,phi,p,1 )/(2*noise_var) + N*log(e_num_events) - log(factorial(N))];
end
%% build output structs
%details about what the mcmc did
%addMoves, dropMoves, and timeMoves give acceptance probabilities for each subclass of move
mcmc.addMoves=addMoves;
mcmc.timeMoves=timeMoves;
mcmc.dropMoves=dropMoves;
mcmc.ampMoves=ampMoves;
mcmc.tau1Moves=tau1Moves;
mcmc.tau2Moves=tau2Moves;
posterior.amp=samples_a;
posterior.base=samples_b;
posterior.tau1=samples_tau_rise;
posterior.tau2=samples_tau_fall;
posterior.num_events = N_sto;
posterior.phi=samples_phi;
posterior.noise = samples_noise;
posterior.obj = objective;
posterior.times = samples_s;