function [ seg, seg_ind, percent_covered ] = MG_Segment_Vel_One_Player(t, x, params)
% MG_SEGMENT_VEL_ONE_PLAYER - return list of segments of one player
% [ seg, seg_ind, percent_covered ] = MG_Segment_Vel_One_Player(t, x, params) -
% input:
% t - time (put [] to use default
)
% x - position
% params (optional), with fields:
% .min_seg_time (default 0.2 sec)- min length (in sec) of segment
% 2012-11-19:
% NEED TO CHECK HOW ALL, E.G IDYO 'Y' MATRIX LOOKS WITH THIS
% SET TO 0.1 => 5HZ (1 cycle = 2 strokes).
% .max_seg_time (default 8 sec) - same, max
% .min_seg_length (default 30 ticks ~= 3cm)
% .remove_threshold - compute without threshold (all segments)
% output:
% seg - cell array of velocity segments [in ticks-per-sec]
% seg_ind - indecies of segments
% percent_covered - percent from signal covered by segments
%
% 2012-10-31:
% allow working without as input, just used to compute ,
% get it instead from MG_Default_Const
%
% 2016-08-30:
% params.butter_filter (default = 0) - add option to make Pos => Vel using Butter instead of Bfilt (for Jason project)
const = MG_Default_Const;
% Default Values for Optional Inputs %
if ~exist('params','var'),
params = [];
end
if ~isfield(params,'min_seg_time'),
params.min_seg_time = const.min_seg_time;
end
if ~isfield(params,'max_seg_time'),
params.max_seg_time = const.max_seg_time;
end
if ~isfield(params,'min_seg_length'), % minimal displacement
params.min_seg_length = const.min_seg_length;
end
if ~isfield(params, 'butter_filter'),
params.butter_filter = 0;
end
% get abs velociy
if params.butter_filter,
v0 = vel_acc_with_butter(x);
v = abs(v0);
% v = v / 50; % bring to same units as coming from bfilt, without './ dt'
else
v = abs(vel_acc_with_bfilt(x));
end
% convert from speed-per-sample to speed-per-sec
if ~isempty(t),
dt = mean(diff(t));
else
cnst = MG_Default_Const;
dt = 1 / cnst.Samples_Per_Sec;
end
v = v / dt;
% all non-zero (segments) points, binary signal
% 30-Aug-2016 - parse by 'almost zero' to work with butter-filter. need to see if it changes other things
z = v > 0;
if params.butter_filter,
% 04-09-2016: deal with butter_filter not reaching zero in segment% boundaries.
% soloution: add to exact zero points (as below) pairs of points that crosses zero, treat them as 'two zero' points' (longer stop),
% and create segments as before
% 07-09-2016: fix false-alarms coming from tiny jitter at start
z ( abs(v0) < 0.001 ) = 0;
v0 ( abs(v0) < 0.001 ) = 0;
ix = find( abs( sign(v0) - [0; sign(v0(1:end-1))] ) == 2 ); % get +2 & -2, both directons, of zero-crossing
z( ix - 1 ) = 0; % point before cross
z( ix ) = 0; % point after cross
end
% 11-Aug-09:
% (+) for both diff, we add dummy-element to have correct placement
% (+) we want the boundary to include the first 0-vel on both sides, so we
% take one sample before the change for start-of-index, and the change
% sample for end-of-segment
% start of segments
a = find( diff([z(1); z]) > 0 ) - 1;
% end of segments
b = find( diff([z(1); z]) < 0);
% if not start or end of segment found, reutrn nothing
if isempty(a) || isempty(b),
seg = [];
seg_ind = [];
percent_covered = 0;
return
end
% ignore partial first segment
if b(1) < a(1),
b = b(2:end);
end
% ignore partial last segment
if a(end) >= b(end),
a = a(1:end-1);
end
if length(a) == (length(b) - 1) && a(1) == b(1), % 07.09.16 - boundary case
b = b(2:end);
end
% so we expect them to be the same length, giving start\end of non-zero segments
if length(a) ~= length(b),
error( 'strange, differnt length of start/end points')
end
len = b - a + 1;
too_short = find( len < round( params.min_seg_time / dt ) ); % we convert the time request for segment length to number-of-samples
too_long = find( len > round( params.max_seg_time / dt ) );
ok = setdiff( 1 : length(len), union(too_short,too_long) );
if isempty(ok),
seg = []; seg_ind = []; percent_covered = 0;
return
end
seg_ind = [a(ok), b(ok)];
% 09_07_29 = remove small segments (in position)
for k = 1 : size(seg_ind,1),
if abs( x(seg_ind(k,1)) - x(seg_ind(k,2)) ) < params.min_seg_length,
mark(k) = 0;
else
mark(k) = 1; %#ok<*AGROW>
end
end
% 09_11_03 = remove segments with NaN from MG_Clean_Sessions
for k = 1 : size(seg_ind,1),
if ~isempty( find( isnan( x( seg_ind(k,1):seg_ind(k,2) ) ), 1 ) ),
mark(k) = 0;
else
mark(k) = 1;
end
end
seg_ind = seg_ind( find(mark), : ); %#ok
if isempty(seg_ind),
seg = [];
percent_covered = 0;
return
end
total_seg_len = 0;
for k = 1 : size(seg_ind,1),
seg{k} = v(seg_ind(k,1):seg_ind(k,2));
total_seg_len = total_seg_len + length( seg{k} );
end
percent_covered = round( 100*(total_seg_len / length(v)) );