[422372]: / functions / timefreqfunc / angtimewarp.m

Download this file

138 lines (122 with data), 4.7 kB

  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
function angdataw=angtimewarp(evLatency, newLatency, angdata)
% ANGTIMEWARP - Given two event marker vectors, computes a
% warping of the input angular time series so that its
% evlatencies match newlatencies. Values of the warped
% timeserie that falls between two frames in the original
% timeserie will be linearly interpolated under the
% assumption that phase change is minimal between two
% successive time points.
% Usage:
% >> warpAngs = angtimewarp(evlatency, newlatency, angData)
%
% Necessary inputs:
% evlatency - [vector] time markers on the original time-series, in
% frames. Markers must be ordered by increasing
% latency. If you want to warp the entire time series,
% make sure frame 1 and the last frame are in the vector.
% newlatency - [vector] desired time marker latencies. The original
% time series will be warped so that its time markers (see
% evlatency) match the ones in newlatency. newlatency
% frames must be sorted by ascending latencies in frames.
% Both vectors have to be the same length.
% angData - [vector] original angular time series (in radians).
% Angles should be between -pi and pi.
%
% Optional outputs:
% warpAngs - [vector] warped angular time-course, with values between
% -pi and pi
%
% Example:
% >> angs = 2*pi*rand(1,10)-pi;
% >> warpangs = angtimewarp([1 5 10], [1 6 10], angs)
%
% Authors: Jean Hausser, SCCN/INC/UCSD, 2006
%
% See also: TIMEWARP, PHASECOHER, ERPIMAGE, NEWTIMEF
if min(sort(evLatency) == evLatency) == 0
error('evlatency should be sorted');
return;
end
if min(sort(newLatency) == newLatency) == 0
error('newlatency should be sorted');
return;
end
if length(evLatency) ~= length(newLatency)
error('evlatency and newlatency must have the same length.');
return;
end
if length(evLatency) < 2 || length(newLatency) < 2
error(['There should be at least two events in evlatency and ' ...
'newlatency, that is "begin" and "end"' ]);
return;
end
if evLatency(1) ~= 1
disp(['Assuming old and new time series beginnings are ' ...
'synchronized']);
disp(['Make sure you defined an end event for both old and new time ' ...
'series !']);
evLatency(end+1)=1;
newLatency(end+1)=1;
evLatency = sort(evLatency);
newLatency = sort(newLatency);
end
t = 1:max(evLatency);
for k=1:length(evLatency)-1
for i=evLatency(k):evLatency(k+1)-1
tp(i) = (t(i)-evLatency(k)) * ...
(newLatency(k+1) - newLatency(k))/...
(evLatency(k+1) - evLatency(k)) + ...
newLatency(k);
end
end
%Check what's going on at tp(max(newLatency)), should equal t(max(evLatency))
tp(max(evLatency)) = max(newLatency);
ts = tp-min(newLatency)+1;
angdataw = zeros(1, max(newLatency)-min(newLatency)+1);
k = 0;
for i=1:length(angdataw)
while i > ts(k+1)
k = k+1;
end
if k == 0
angdataw(1) = angdata(1);
else
%Linear interp
angdataw(i) = angdata(k)*(1 - (i-ts(k))/(ts(k+1)-ts(k))) + ...
angdata(k+1)*(1 - (ts(k+1)-i)/(ts(k+1)-ts(k)));
% %Correction because angles have a ring structure
% theta1 = [angdata(k) angdata(k+1) angdataw(i)];
% theta2 = theta1 - min(angdata(k), angdata(k+1));
% theta2max = max(theta2(1), theta2(2));
% if ~ ( (theta2max <= pi & theta2(3) <= theta2max) | ...
% (theta2max >= pi & theta2(3) >= theta2max) | ...
% theta2(3) == theta2(1) | theta2(3) == theta2(2) )
% angdataw(i) = angdataw(i) + pi;
% end
% if angdataw(i) > pi %Make sure we're still on [-pi, pi]
% angdataw(i) = angdataw(i) - 2*pi;
% end
end
end
angdataw = wrap2pi(angdataw);
function a = wrap2pi(a, a_center )
% function a = wrap(a,a_center)
%
% Wraps angles to a range of 2*pi.
% Inverse of Matlab's "unwrap", and better than wrapToPi ( which has
% redundant [-pi,pi])
% Optional input "a_center" defines the center angle. Default is 0, giving
% angles from (-pi,pi], chosen to match angle(complex(-1,0)). Maximum
% possible value is pi.
% T.Hilmer, UH
% 2010.10.18 version 2
% removed code from version 1. Have not bug-checked second input
% "a_center"
if nargin < 2, a_center = 0; end
% new way
a = mod(a,2*pi); % [0 2pi)
% shift
j = a > pi - a_center;
a(j) = a(j) - 2*pi;
j = a < a_center - pi;
a(j) = a(j) + 2*pi;