73
73
% ClockOffset difference that is at least this
74
74
% many seconds away from the median. (default: 1)
75
75
%
76
+ % 'WinsorThreshold' : Error threshold beyond which clock offset deviations are considered
77
+ % outliers, and therefore penalized less severely (linear instead of quadratic).
78
+ % (default: 0.0001)
79
+ %
76
80
% 'ClockResetMaxJitter' : Maximum tolerable jitter (in seconds of error) for clock
77
81
% reset handling. (default: 5)
78
82
%
365
369
temp(id ).time_series = {};
366
370
temp(id ).time_stamps = {};
367
371
temp(id ).clock_times = [];
368
- temp(id ).clock_values = [];
372
+ temp(id ).offset_values = [];
369
373
if temp(id ).srate > 0
370
374
temp(id ).sampling_interval = 1 / temp(id ).srate;
371
375
else
391
395
% read [CollectionTime]
392
396
temp(id ).clock_times(end + 1 ) = fread(f ,1 ,' double' );
393
397
% read [OffsetValue]
394
- temp(id ).clock_values (end + 1 ) = fread(f ,1 ,' double' );
398
+ temp(id ).offset_values (end + 1 ) = fread(f ,1 ,' double' );
395
399
catch e
396
400
% an error occurred (perhaps a chopped-off file): emit a
397
401
% warning and scan forward to the next recognized chunk
431
435
if ~isempty(temp(k ).time_stamps)
432
436
try
433
437
clock_times = temp(k ).clock_times;
434
- clock_values = temp(k ).clock_values ;
438
+ offset_values = temp(k ).offset_values ;
435
439
if isempty(clock_times )
436
440
error(' No clock offset values present.' ); end
437
441
catch
447
451
% importer should be able to deal with recordings where the computer that served a stream
448
452
% was restarted or hot-swapped during an ongoing recording, or the clock was reset otherwise
449
453
time_diff = diff(clock_times );
450
- value_diff = abs(diff(clock_values ));
454
+ value_diff = abs(diff(offset_values ));
451
455
% points where a glitch in the timing of successive clock measurements happened
452
456
time_glitch = (time_diff < 0 | (((time_diff - median(time_diff )) ./ median(abs(time_diff - median(time_diff )))) > opts .ClockResetThresholdStds & ...
453
457
((time_diff - median(time_diff )) > opts .ClockResetThresholdSeconds )));
472
476
ranges = {[1 ,length(clock_times )]};
473
477
end
474
478
475
- % calculate clock offset mappings for each data range
479
+ % Calculate clock offset mappings for each data range
476
480
mappings = {};
477
481
for r= 1 : length(ranges )
478
482
idx = ranges{r };
479
483
if idx(1 ) ~= idx(2 )
480
- % to accomodate the Winsorizing threshold (in seconds) we rescale the data (robust_fit sets it to 1 unit)
481
- mappings{r } = robust_fit([ones(idx(2 )-idx(1 )+1 ,1 ) clock_times(idx(1 ): idx(2 ))' ]/opts .WinsorThreshold , clock_values(idx(1 ): idx(2 ))' /opts .WinsorThreshold );
484
+ Ax = clock_times(idx(1 ): idx(2 ))' / opts .WinsorThreshold ;
485
+ y = offset_values(idx(1 ): idx(2 ))' / opts .WinsorThreshold ;
486
+ fit_params = robust_fit([ones(size(Ax )) Ax ], y );
487
+ fit_params(1 ) = fit_params(1 )*opts .WinsorThreshold ;
488
+ mappings{r } = fit_params ;
482
489
else
483
- mappings{r } = [clock_values (idx(1 )) 0 ]; % just one measurement
490
+ mappings{r } = [offset_values (idx(1 )) 0 ]; % just one measurement
484
491
end
485
492
end
486
493
@@ -781,7 +788,7 @@ function close_file(f,filename)
781
788
% minimize 1/2*sum(huber(A*x - y))
782
789
%
783
790
% Based on the ADMM Matlab codes also found at:
784
- % http ://www .stanford.edu/~boyd/papers/distr_opt_stat_learning_admm .html
791
+ % https ://web .stanford.edu/~boyd/papers/admm_distr_stats .html
785
792
%
786
793
% Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
787
794
% 2013-03-04
@@ -790,15 +797,21 @@ function close_file(f,filename)
790
797
rho = 1 ; end
791
798
if ~exist(' iters' ,' var' )
792
799
iters = 1000 ; end
800
+
801
+ x_offset = min(A(: , 2 ));
802
+ A(: , 2 ) = A(: , 2 ) - x_offset ;
793
803
Aty = A ' *y ;
794
- L = sparse(chol(A ' *A ,' lower' )); U = L ' ;
804
+ L = chol( A ' *A , ' lower' );
805
+ L = sparse(L );
806
+ U = sparse(L ' );
795
807
z = zeros(size(y )); u = z ;
796
808
for k = 1 : iters
797
809
x = U \ (L \ (Aty + A ' *(z - u )));
798
810
d = A * x - y + u ;
799
811
z = rho /(1 + rho )*d + 1 /(1 + rho )*max(0 ,(1 -(1 + 1 / rho )./abs(d ))).*d ;
800
812
u = d - z ;
801
813
end
814
+ x(1 ) = x(1 ) - x(2 )*x_offset ;
802
815
end
803
816
804
817
0 commit comments