FIND function with multiple conditions

12 views (last 30 days)
Nadia Numa
Nadia Numa on 14 Mar 2021
Commented: Mathieu NOE on 16 Mar 2021
Hello!
I have a dataset, state, that is 500x6 data. This dataset presents position and velocity for a circular orbit. As a result, there are cases where an x-position might have 2 options for y-location (1 positive, 1 negative).
The second data, p, set is 1x6: the final position and velocity at the end of an arc. This data may have either positive or negative for y-location for each computation.
The goal is to search the 500x6 data set to find the location (index) where p(1,1:3) = state(i,1:3). The goal is to match position only.
I have tried the following:
temp = min(abs(p(1,1:3) - state(:,1:3))) % tolerance
location = find(abs(p(1,1:3) - state(:,1:3)) == temp)
This method works when the y-location is positive for both z and state. It correctly finds the location in state.
Any recommendations on how to modify the search to correctly find the index when the y-location is negative in both sets? Thank you!

Answers (1)

Mathieu NOE
Mathieu NOE on 15 Mar 2021
hello Nadia
I have tried another approach , by looking at the 2 nearest points to zero crossing points of the vector defined as the difference between position and state .
the index of the 2 points is stored in ind_close
I have tested my code on dummy data
hope it works for you
% dummy data
theta = 0:0.1:2*pi;
p = sin(theta);
s = 0.5*cos(theta);
figure(1),plot(theta,p,'b',theta,s,'r');
legend(' data : position', 'data : state')
%%%%%%%%%%%%%%%%%%% main loop %%%%%%%%%%%%%%%%%%%%%%%%%
dd = p - s; % difference
[ind,theta0,dd0,ind_close,theta0_close,dd0_close] = crossing_V6(dd,theta,0,'linear'); % Zero-Crossing
figure(2)
plot(theta, dd, '*r')
hold on
plot(theta0_close, dd0_close, 'bp')
hold off
grid on
legend('p - s difference', 'nearest points to Zero-Crossings points')
% save data
p(ind_close)
s(ind_close)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ind,t0,s0,indclose,t0close,s0close] = crossing_V6(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth)
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% [ind,t0,s0] = ... also returns the data vector corresponding to
% the t0 values.
%
% [ind,t0,s0,t0close,s0close] additionally returns the data points
% closest to a zero crossing in the arrays t0close and s0close.
%
% This version has been revised incorporating the good and valuable
% bugfixes given by users on Matlabcentral. Special thanks to
% Howard Fishman, Christian Rothleitner, Jonathan Kellogg, and
% Zach Lewis for their input.
% Steffen Brueckner, 2002-09-25
% Steffen Brueckner, 2007-08-27 revised version
% M Noé , 2020-08-20 revised version
% Copyright (c) Steffen Brueckner, 2002-2007
% brueckner@sbrs.net
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) > eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) > eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% Addition:
% Some people like to get the data points closest to the zero crossing,
% so we return these as well
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
indclose = ind + (II-2); %update indices
t0close = t(indclose);
s0close = S(indclose);
end
  2 Comments
Nadia Numa
Nadia Numa on 15 Mar 2021
I found a work around but thank you! I will give this a try.

Sign in to comment.

Categories

Find more on Dates and Time in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!