Google Answers Logo
View Question
 
Q: Mathematical Source Code - Exact Peak Location (Peak Searching) ( No Answer,   2 Comments )
Question  
Subject: Mathematical Source Code - Exact Peak Location (Peak Searching)
Category: Science > Math
Asked by: nikolas-ga
List Price: $30.00
Posted: 20 Jan 2005 13:41 PST
Expires: 19 Feb 2005 13:41 PST
Question ID: 460605
Hi. Let's say that I have this data of 20 points:
==========
x       y
----------
1	2
2	3
3	4
4	3
5	2
6	5
7	10
8	20
9	13
10	10
11	5
12	4
13	6
14	4
15	3
16	2
17	7
18	15
19	28
20	12
-----------

I would like to have the mathematical background of locating peaks in
a XY graph chart. Source code, preferably in VB.NET or C# (C++ or Java
is ok too) would be greately appreciated and required.
Please take into account that this method must be fullprof in the following way:
a) Sensitivity. The main two peaks are (8,20) and (19,28). The others
(eg (3,4)) must be excluded because their area is very small. I am
saying this because I beleive that examining where the slope changes
is not good enough.
b) Shoulders (very wide peaks) must be excluded. I guess this is a
question of fitting parameters but I can't tell for sure. (The data
above does not present shoulders but it is common in graphs)

Thank you in advance!
Answer  
There is no answer at this time.

Comments  
Subject: Re: Mathematical Source Code - Exact Peak Location (Peak Searching)
From: jamesmcg-ga on 24 Jan 2005 14:59 PST
 
Well here's some java source code that will do the locating.
Basically, it compares each element in the List, with the Y value
before and next, to find all  local peaks.

It then filters out the small ones, by testing if the peak is below
the average for the entire sample, and then generates a local average
(ie the average of the 3 samples before and next) and checks if the
peak is signficantly higher (in terms of a percentage of the total
average) than the local average (this should eliminate shoulders).

You will need to tweak peakPercentage to say how sharp a peak needs
(18% is the highest value that will get both peaks, but 0% will also
get both peaks as the others are below the total average) to be and
searchDepth to say how wide a shoulder is acceptable.

I havn't done any searching for mathmatical formulas or more advanced
methods of such peak searching, rather stuck with a rather simple
method that I put together while thinking about the question.



import java.util.ArrayList;
import java.util.List;


/**
 * @author James McGuigan
 */

public class XYMapping {

	public List X;
	public List Y;
	
	public List PeakX = new ArrayList();
	public List PeakY = new ArrayList();
	public double YAverage = 0;
	public double peakPercentage = 0.10; 
	public int    searchDepth    = 2;
	

	/**
	 * @param X = List of doubles for X coords - assumes they are evenly spaced 
	 * @param Y = List of doubles for Y coords
	 * @param peakPercentage = how high (as percentage of total average)
	 * @param searchDepth = how far to search for the local average
	 */
	public XYMapping(List X, List Y, double peakPercentage, int searchDepth) {
		super();
		this.X = X;
		this.Y = Y;
		this.peakPercentage = peakPercentage;
		this.searchDepth    = searchDepth;
		this.FindPeaks();
	}
	
	public void FindPeaks() {
		double Ytotal = 0;
		for(int i=0;i<this.Y.size();i++) {
			Ytotal += ((Double)this.Y.get(i)).doubleValue();
		} this.YAverage = Ytotal / this.Y.size();  
		
		
		double peak = 0.0;  
		for(int i=0;i<this.X.size();i++) {
			double current = ((Double)this.Y.get(i)).doubleValue();
			double last = 0;
			double next = 0;
			if(i-1 > 0)             last = ((Double)this.Y.get(i-1)).doubleValue();
			if(i+1 < this.X.size()) next = ((Double)this.Y.get(i+1)).doubleValue();

			// are we at a local peak
			if(current > last  && current > next)
	  		{ 
				// test height above average to weed out shoulders
				// use an absolute height value to weed out small hills
				double total = current;
				int squares = 1;
				for(int d=1;d<=searchDepth;d++) {
					if(i-d > 0) { // test for out of bounds 
						total += ((Double)this.Y.get(i-d)).doubleValue();
						squares++;
					}
					if(i+d < this.X.size()) {
						total += ((Double)this.Y.get(i+d)).doubleValue();
						squares++;
					}						
				}				
				double average = total / squares;
				double minPeakSize = average + (this.YAverage * this.peakPercentage); 
				
				// test if the peak is higher than mid point of graph
				// and significantly higher than sourounding points
				if(current > this.YAverage  					
				&& (current - average) > minPeakSize) { //this.heightAboveAverage) {
					this.PeakX.add(this.X.get(i));
					this.PeakY.add(this.Y.get(i));
				}
			}
		}	
		
		for(int i=0;i<this.PeakX.size();i++) {
			System.out.print("Peak " + i + " = X:");
			System.out.print(this.PeakX.get(i));
			System.out.print("\tY:");
			System.out.print(this.PeakY.get(i));
			System.out.print("\n");
		}
	}
	
	public static void main(String[] args) {
		int[] xarray = {1,2,3,4,5,6,7,  8, 9,10,11,12,13,14,15,16,17,18,19,20};
		int[] yarray = {2,3,4,3,2,5,10,20,13,10, 5, 4, 6, 4, 3, 2, 7,15,28,12};
		List X = new ArrayList();
		List Y = new ArrayList();
		for(int i=0;i<xarray.length;i++) { X.add(new Double(xarray[i])); 
		                                   Y.add(new Double(yarray[i])); };
		
		double peakPercentage = 0.18; // 18% - highest value that still find
both peaks in sample data
		int searchDepth = 3;  
		XYMapping mapper = new XYMapping(X,Y,peakPercentage,searchDepth);
	}
}



Code Output:
Peak 0 = X:8.0	Y:20.0
Peak 1 = X:19.0	Y:28.0
Subject: Re: Mathematical Source Code - Exact Peak Location (Peak Searching)
From: nikolas-ga on 25 Jan 2005 13:18 PST
 
Dear jamesmcg-ga,
thanks for the very well written comment. Although it has no
mathematical formulas it is certainly exactly on the point. I would
like to comment on the java source (grateful for that too). I haven't
tested it with many points but I find the rules for peak search very
strict. The var:
----
double minPeakSize = average + (this.YAverage * this.peakPercentage);
----
has always a very high value due to average (I admit though that with
many points this will be more or less normalized). What is the purpose
of adding average?
The same for the (current - average) which is often negative: 
----
if.....
&& (current - average) > minPeakSize
----

Anyway, thanks for time you spent!

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy