I am trying to find the valley in a sequence of numbers of around 2000 length. It is a plot of the sequence of numbers

Always prominently there will be two peaks. But the value and location might change. I need to find the valley, defined as the lowest point between the two peak values.

I tried using the following code:

% sums = list of positive integers generated from an analysis
inverted_sums = double(max(sums) - sums); % inverting the sequnce
[~,locs] = findpeaks(inverted_sums) % finding the peaks

But the above code returns many valleys with even a small difference, including the correct one. How do I solve it?


The following code will find the lowest point between two prominent peaks.

%Smoothing the data
movAvgFiltOrder = 8;
b = filter(ones(1,movAvgFiltOrder)/movAvgFiltOrder,1,sums); 

% finding peaks from the smoothed curve
[vals,pos] = findpeaks(b);
idx = find(vals>mean([min(vals),max(vals)])); % removing peaks which are below the average, 
%this is helpfull if some lower amplitude peaks are caught at sides of the prominent peaks.

peak_pos1 = pos(idx(1)); % farthest prominent peak on one side of valley
peak_pos2 = pos(idx(end)); % farthest prominent peak on other side of valley

% correcting the peak positions for filter delay (Coarse tuning)
peak_pos1 = peak_pos1 -  movAvgFiltOrder/2;
peak_pos2 = peak_pos2 -  movAvgFiltOrder/2;

% Looking for any other peaks nearby (Fine Tuning)
tuning_range = min(movAvgFiltOrder,floor(abs((peak_pos2-peak_pos1-1)/2)));
p1 = peak_pos1-tuning_range:peak_pos1+tuning_range;
p2 = peak_pos2-tuning_range:peak_pos2+tuning_range;
[~,r1] = max(sums(p1));
[~,r2] = max(sums(p2));
peak_pos1 = p1(r1);
peak_pos2 = p2(r2);

% Identifying valley
valley = sums(peak_pos1:peak_pos2);

% finding minimum point in valley
[min_val,pos_min_val] = min(valley);
valley_amplitude = min_val; % amplitude of minimum point
valley_position  = peak_pos1+pos_min_val-1; % finding the valley point in the entire array

This valley_position will give the poisition of the lowest point between major peaks.

| improve this answer | |
  • $\begingroup$ It worked very beautifully for me.. Thank you.. please replace the 'a' with 'sums' in valley = a(peak_pos1:peak_pos2); $\endgroup$ – Prashant Jun 9 '18 at 5:03
  • $\begingroup$ Hi @prashanth.. if you found answer useful, please upvote the answer. $\endgroup$ – srk_cb Jun 10 '18 at 1:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.