2 views (last 30 days)

I have a cell array idp{1x58} which contains the indices of local maxima of each time series. I have another cell array qq{1x58} that contains indices of local minima for every time series.

I want to compare every elemt in the array idp with qq and I want to find the closest values above and below the element in idp.

For ex: idp{1,3} = 411.

Comparing it with qq{1,3}, 376 and 497 are the closest values above and below 411.

How do I do this operation?

Adam Danz
on 4 Dec 2019

Edited: Adam Danz
on 4 Dec 2019

pairs is a cell array the same size as idp and qq. Each element is a 1x2 vector of the values in qq that are just below and above the values in idp.

% Inputs

idp = {381 402 411 359};

qq ={[168 262 498 637],[288,564,669],[88 257 376 497 535],[55 159 217 377 525 681]};

% closest values [below, above] idp

pairs = cellfun(@(a,b)[max(b(b<a)),min(b(b>a))],idp,qq,'UniformOutput',false);

If you'd rather return an nx2 matrix,

pairs = cell2mat(pairs');

Adam Danz
on 4 Dec 2019

"1)Is there a way to get the indices of the cells in [pairs] which have only one element"

Sure, that's easy using cellfun.

If you didn't implement the [-inf,inf] suggestion, this will return a logical array identifying elements of pairs that only have 1 value.

idx = cellfun(@(x)numel(x)<2,pairs);

If you did implement the [-inf,inf] suggestion,

idx = cellfun(@(x)any(isinf(x)),pairs);

"2)Once I have the indices, ... "

You could do it that way but it doesn't sound streamlined. Do you have the idp values prior to the loop that calculates qq? If so, you could to a small test right there in that loop. It would look like this

for i = 1:length(files)

[~,PM{i}]=islocalmin(TFWS{i,:});

loc{i}=PM{:,i}>0.9;

qq{i}=find(loc{:,i});

% Test if there is a min and max in qq for the corresponding idp

if ~Your_Test_Here % FALSE means the test failed and you have to change prominence

loc{i}=PM{:,i} > 0.1;

qq{i}=find(loc{:,i});

end

end

Adam Danz
on 5 Dec 2019

Good work!

I just though of a small improvement you could make but it's not necessary. In your current version, there are two lines that call cellfun() and those lines are identical. A small problem with this approach is that if you ever make changes to one line, you need to make the same changes to the other line and that's often overlooked (imagine you make a change a year from now and forget that you must do the same for the other line).

To avoid that problem, you could wrap the cellfun() line into an anonymous function so that it's only defined once. The first line below has been added and the two celfun() lines have been replaced. Also, I added {i} to (idp{i},qq{i}) -- I think that's what you meant to do.

pairsFunc = @(a,b)cellfun(@(a,b)[max(b(b<a)),min(b(b>a))],a,b,'UniformOutput',false);

for i = 1:length(files)

[~,PM{i}]=islocalmin(TFWS{i,:});

loc{i}=PM{:,i}>0.9;

qq{i}=find(loc{:,i});

pairs = pairsFunc(idp{i},qq{i});

if length(pairs{1,i})==1

loc{i}=PM{:,i}>0.1;

qq{i}=find(loc{:,i});

pairs = pairsFunc(idp{i},qq{i});

end

end

Also note that you're overwriting the pairs variable on each iteration instead of storing the values. Is that really what you want to do?

Sign in to comment.

Sign in to answer this question.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.