Extract maximum values from two different vectors when their associated location vectors crosses

Dear all,
I have four vectors, two with peak values and two vectors with associated location values based on two peak analysis.
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
I want create a new vector with the maximum value from vector pks1 and from pks2 when loc1 and loc2 have the approximately same value (~+-2).
I.e. loc1 and loc2 cross at position 1,2 and 5 (10.1 and 10.4, 15.2 and 15.8, 35.6 and 35.9), so my new vector will be: final=[10 5 5 4 1000].
Can anyone help me out?
Thanks in advance!

6 Comments

Why wouldn't it be [10 5 1000]. Where does the additional 5 and 4 come from?
Thank you for replying. The values 5 and 4 is included since there is a peak at time 29.2s and another one at 32.1s in pks1. These peaks does not occur in pks2, but must be included in the new vector
I see. But what would the general rule be for different datasets?
Is the following an accurate algorithm for what you want to do?
  • First, select all of the peaks defined by pks1
  • Next, if a value of loc2 is near loc1, and the associated value of pks2 is larger than pks1, use the pks2 value instead.
Finding the max pks values for loc values that are within 2 units is easy. It's just unclear what to do with the unpaired loc values.
% Find indices of loc1 & loc2 that are within 2 units of each other
% locsAreClose(n,m) determines if loc1(n) and loc2(m) are within +/-2
locsAreClose = abs(loc1(:)-loc2(:).')<=2; %rows@loc1, cols@roc2
% Find the max between all pks pairs
maxPairs = max(pks1(:),pks2(:).');
% Output the max for each pair
out = maxPairs(locsAreClose);
Per Vatsvag's answer moved here as a comment.
Thanks for all replies
The cyclist: Yes ,the algorithm you describe is correct!
Adam Danz: In principle I need to account for all peaks in pks1, but also considered that the maximum peak force may occur in the second sensor (pks2) for an event where both the sensors are triggered. The pks1-sensor have triggered 5 times and the pks2-sensor have triggered 3 times, which means that my new vector must contain 5 values. Since the second sensor have triggered at the same time (+-2s) as the first sensor (pks1) then I want to use the maximum of those.

Sign in to comment.

 Accepted Answer

"I need to account for all peaks in pks1, but also considered that the maximum peak force may occur in the second sensor (pks2)"
Just a small adjustment is needed in the code from my comment under your question.
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
% Find indices of loc1 & loc2 that are within 2 units of each other
% locsAreClose(n,m) determines if loc1(n) and loc2(m) are within +/-2
locsAreClose = abs(loc1(:)-loc2(:).')<=2; %rows@loc1, cols@roc2
% Find the max between all pks pairs
maxPairs = max(pks1(:),pks2(:).');
% Output
pksMax = pks1;
pksMax(any(locsAreClose,2)) = maxPairs(locsAreClose);
[update]
For n peak/loc vectors, just combine the vectors except for loc1 and pks1. So, this can work for any number of loc/pks vectors.
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
loc3=[15.3 29 35.6 44];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
pks3=[7 6 50 90];
loc23 = [loc2, loc3]; % combine them into 1 vector
pks23 = [pks2, pks3]; % combine them into 1 vector
% Find indices of loc1 & loc23 that are within 2 units of each other
locsAreClose = abs(loc1(:)-loc23(:).')<=2; %rows@loc1, cols@loc23
% Find the max between all pks pairs
maxPairs = max(pks1(:),pks23(:).');
maxPairs(~locsAreClose) = -inf;
maxVals = max(maxPairs,[],2); % a vector of all max values
% Output
pksMax = pks1;
pksMax(any(locsAreClose,2)) = maxVals(any(locsAreClose,2));

2 Comments

Per Vatsvag's answer moved here as a comment.
Adam Danz:Thank you for the swift reply and excellent help!
You have just saved me for a ton of manual work!
Glad I could help! Thanks to the cyclist too for helping to define the requirements.

Sign in to comment.

More Answers (2)

% The data
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
% Find the values of loc2 that are close to loc1, and their corresponding
% indices
[isClose,closeIndex] = ismembertol(loc2,loc1,2,'DataScale',1);
% Define the initial guess of the true peaks to be all the pks1 values
truePeaks = pks1;
% Overwrite the close ones with pks2
truePeaks(closeIndex(isClose)) = pks2(isClose);

3 Comments

Extended to your three-variable problem:
% The data
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
loc3=[15.3 29 35.6 44];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
pks3=[7 6 50 90];
% Find the values of loc2 that are close to loc1, and their corresponding
% indices
[isClose,closeIndex] = ismembertol(loc2,loc1,2,'DataScale',1);
% Define the initial guess of the true peaks to be all the pks1 values
truePeaks = pks1;
% Overwrite the close ones with pks2
truePeaks(closeIndex(isClose)) = pks2(isClose);
% Find the values of loc3 that are close to loc1, and their corresponding
% indices
[isClose,closeIndex] = ismembertol(loc3,loc1,2,'DataScale',1);
% Overwrite the close ones with pks3
truePeaks(closeIndex(isClose)) = pks3(isClose);
Note that the only change (besides your new data) was to repeat the finding close values and overwriting, which is done in exactly the same way.
Also, as an aside, it is generally a terrible idea to name your variable dynamically (loc1, loc2, etc). It would have been better to use cell arrays: loc{1}, loc{2}, etc.
See this question to learn why.
It's not as simple as that. loc1(2) is close to loc2(2) and loc3(1) and for this data, the pks3(1) value is greatest so your solution works. Change the pks3(1) value so that it's less than pks(2) and the solution no longer works.
% v-- now pks2(2) > pks3(1)
pks2=[8 7 1000];
pks3=[5 6 50 90];

Sign in to comment.

If I wish to extend this problem to three variables (/sensors),
E.g.:
loc1=[10.4 15.8 29.2 32.1 35.9];
loc2=[10.1 15.2 35.6];
loc3=[15.3 29 35.6 44];
pks1=[10 1 5 4 100];
pks2=[8 5 1000];
pks3=[7 6 50 90]
Any suggestions?
Also, thank you the cyclist for your answer!

6 Comments

I updated my answer to show a solution for 3 pks/loc vectors. It combines loc2&3 as well as pks 2&3 so this answer can be expanded to any number of pks and loc vectors.
Moved Per Vatsvag's "answer" here (and formatted it a bit), because it was actually a comment.
Dear Adam,
I am not able to get your code with 3 variables working properly.
A new example:
% Sensor 1 (15 events)
time1=[1213 1373 1795 2659 4348 5020 5491 5667 8537 8953 9173 10536 10826 10991 11489];
pks1=[404 998 891 1844 329 428 1025 335 2354 549 997 438 7531 614 545];
% Sensor 2 (14 events)
time2=[1373 1795 2659 3051 4348 5020 5491 5667 8537 8953 9173 10826 10991 11489];
pks2=[1372 1065 1327 323 568 461 989 504 1322 532 440 7650 566 484];
% Sensor 3 (11 events)
time3=[1373 1795 2659 4348 5491 8537 8953 9173 10826 10991 11489];
pks3=[1547 920 931 601 1058 1628 652 638 5332 741 397];
I have in total 16 different "events" from these sensors.
My new vector shall be, a= [404 1547 1065 1844 323 601 461 1058 504 2354 652 997 438 7650 741 545];
If I use your code and combine time1 and time2 into 1 vector I will have a new vector (1x11) which is a12=[1547 1065 1844 601 1058 2354 652 997 7650 741 545].
If I combine time2 and time3 into 1 vector I will have a new vector (1x15) which is a23=[404 1547 1065 1844 601 461 1058 504 2354 652 997 438 7650 741 545];
I am then missing event #5, peak=323 at time= 3051 which occur on sensor 2.
Do you have any suggestions?
Thank you in advance.
@Per,
I think you probably don't fully realize this, but the problem is that you keep slightly changing the requirements for the solution.
First, it was just that you needed to compare a 2nd set of peaks.
Next, it was that you had a 3rd set of peaks -- but it seemed that the 1st set was "definitive", in that it had all the possible locations.
Now, it seems that locs1 does not have all the locations, so we need to modify again.
So, lesson for next time -- lay out the whole problem at the beginning.
Also, please try to see how Adam and I have been using this forum. Answers only for things that are actually answers, and comments when you are replying to something someone else wrote.
This is an interesting project.
In your original question you described, "I need to account for all peaks in pks1, but also considered that the maximum peak force may occur in the second sensor (pks2)"""
In my multi-vector solution, pks1 & loc1 are the reference vectors which are compared against all other vectors combined. Data from pks1 & loc1 are not combined with any other data.
From your comment above, it seems that you've used a different implementation where loc1 and loc2 (which I assume are time1 and time2, let's not change variable names because that will make it difficult to follow the comments) are combined and then compared against loc3&4.
The correct implementation of my multi-vector answer is to simply substitute your pks and time vectors into the pks and locs variables from my answer.
loc1=[1213 1373 1795 2659 4348 5020 5491 5667 8537 8953 9173 10536 10826 10991 11489];
loc2=[1373 1795 2659 3051 4348 5020 5491 5667 8537 8953 9173 10826 10991 11489];
loc3=[1373 1795 2659 4348 5491 8537 8953 9173 10826 10991 11489];
pks1=[404 998 891 1844 329 428 1025 335 2354 549 997 438 7531 614 545];
pks2=[1372 1065 1327 323 568 461 989 504 1322 532 440 7650 566 484];
pks3=[1547 920 931 601 1058 1628 652 638 5332 741 397];
%% THE REST OF THIS BELOW IS THE SAME AS IN MY ANSWER
loc23 = [loc2, loc3]; % combine them into 1 vector
pks23 = [pks2, pks3]; % combine them into 1 vector
% Find indices of loc1 & loc23 that are within 2 units of each other
locsAreClose = abs(loc1(:)-loc23(:).')<=2; %rows@loc1, cols@loc23
% Find the max between all pks pairs
maxPairs = max(pks1(:),pks23(:).');
maxPairs(~locsAreClose) = -inf;
maxVals = max(maxPairs,[],2); % a vector of all max values
% Output
pksMax = pks1;
pksMax(any(locsAreClose,2)) = maxVals(any(locsAreClose,2));
The result is
pksMax =
Columns 1 through 11
404 1547 1065 1844 601 461 1058 504 2354 652 997
Columns 12 through 15
438 7650 741 545
But that doesn't match your expected output "a" however it does match the expected output of the rule you defined.
For example, your a(5) is 323. My pksMax(5) is 601. The 5th element of locs1 (time1) is 4348 which is close to the 5th element of locs2 and the 4th element of locs3. The associated pks values are [329, 568, 601]. Clearly 601 is the max value. 323 isn't even an option. So either your expected values in 'a' are incorrect or the rule has changed (as the cyclist mentioned above).
ps, the biggest lesson to learn here (and one that most of us learned the hard way) is to have a well planned set of rules before the first line of code is written. That's not to say that you won't need to make small adjustments as you go along. But following a planned sketch is much easier than sketching it out as you go. I'd bet that every 1 minute spent planning an algorithm before implementing it can save 15-30 minutes of troubleshooting and re-writing.
Adam and the cyclist:
Thank you for all your help so far.
The problem has changed, but is related, so instead of making a new threat I thought it would be easier just to continue on this one.
The following algorithm applies:
  • First, select all of the peaks defined by pks1, pks2 and pks3.
  • Next, identify the maximum value from pks1,pks2 and pks3 for each "event". The events are given by the location vector in time and shall be defined as "same event" when the time cross +-2 seconds. I.e. loc1(2) and loc2(1) ~1373s.
  • The new vector shall contain all the maximum values from all the identified events. 16 events have been identified by comparing the values in the 3 loc-vectors.
  • There may be 1, 2 or 3 peak values in one event.
Example: Only one peak value in an event. I.e. new vector must include 323.
Sensor 2: loc2(4),pks2(4) / time=3051s and peak=323
Example: Two peak values in an event. I.e. new vector must include 1547.
Sensor 2: loc2(1),pks2(1) / time=1373s and peak=1372
Sensor 3: loc3(1),pks3(1) / time=1373s and peak=1547
Example: Three peak values in an event. I.e. new vector must include 1065.
Sensor 1: loc1(3),pks1(3) / time=1795s and peak=891
Sensor 2: loc2(2),pks2(2) / time=1795s and peak=1065
Sensor 3: loc3(2),pks3(2) / time=1795s and peak=920
  • The new vector shall contain 16 values given the number of events.
I have attached a plot illustrating the identified events from the different sensors.
If anything is unclear please let me know!
Thanks again for all help.
I will comment on questions/answers accordingly (blame a new user) from now on.

Sign in to comment.

Products

Release

R2018a

Community Treasure Hunt

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

Start Hunting!