# Finding peaks of data

I want to find peaks in my data.

My code in a reduced form so far:

data = Table[Import["/files/abs" <> ToString[i] <> ".csv", "CSV"], {i, 12}];
ListLinePlot[Drop[data, {5}]]


data[[5]] is dropped, because abs5.csv is empty.

The input files have the following structure:

{{700.044, 0.122124}, {699.037, 0.12329}, ... , {400.974, 0.307371}, {400.047, 0.310131}}


data is a list of those.

If I try to find the peaks of e.g. data[[3]] with FindPeaks it gives me an error:

FindPeaks[data[[3]]]

FindPeaks::arg: The argument
{{400,1.86096},{401,1.86188}, ... ,{448,1.5799},{449,1.52985},<<251>>}
at position 1 is not a consistent list of real values.


Is it a problem, that the peaks are kind of "weak"? Would trying to find local maxima be a better approach?

I'm new to Mathematica. So don't judge me, if this question/approach is silly ;)

UPDATE: (MarcoB's comment)

peak = FindPeaks[data[[3, All, 2]]]

{{16, 0.134554}, {20, 0.136414}, ... , {222, 0.205652}, {301, 0.310131}}


ListPlot[{data[[3]], peak}]

As you can see, the y values of the peaks are correct, but FindPeaks changed the x values to the position in the list.

Is there a workaround for this?

• FindPeaks only deals with the y values in the list. Try evaluating it on  data[[3,All,2]] – MarcoB May 20 '15 at 19:15
• This works, but it deletes the x values and replaces them with the position in the list. Is there a warkaround for this? – kaos May 20 '15 at 19:20
• yep, that will add one step, but see my answer below – MarcoB May 20 '15 at 19:25
• What were you trying to accomplish with the last expression? The peak position is a list of points, from which you can certainly extract the wavelengths as well, but what do you want to obtain from the plot? Points to highlight the calculated position of the peaks? could you expand on what you would like to see? – MarcoB May 20 '15 at 19:34
• I added one way to highlight the found peak positions in the spectrum plot in my answer. Was that any closer to what you were after? – MarcoB May 20 '15 at 19:38

## 1 Answer

Let's create a fake spectrum with two peaks:

spectrum = Table[
{lambda, Exp[-(lambda - 350)^2/(50^2)] + Exp[-(lambda - 430)^2/(25^2)]},
{lambda, 200., 800., 1.}
];

ListLinePlot[spectrum, PlotRange -> All]


Now let's use FindPeaks to find the positions of those peaks, using only the absorbance values, i.e. the $y$ values in the list above:

peakpositions = FindPeaks[ spectrum[[All, 2]] ]

(* Out: {{151, 1.00004}, {229, 1.08134}} *)


The output corresponds to pairs of {peak position in original array, value at peak}. We can use those positions to look up the wavelengths at the maximum for those two peaks:

peakwavelengths = spectrum[[#1, 1]] & @@@ peakpositions

(* Out: {350., 428.} *)


... which is hopefully acceptably close to the 350 and 430 nm that I had "programmed" in.

We can also highlight those peak positions in the plot:

ListLinePlot[spectrum, PlotRange -> All,
GridLines -> {peakwavelenghts, None},
GridLinesStyle -> Directive[Red, Thick]
]


Peak wavelengths could also be extracted using the following alternative to what is shown above:

peakwavelengths = spectrum[[First /@ peakpositions, 1]]


To obtain a list of the peak wavelengths together with the spectral values at those wavelengths, the following two expressions are equivalent:

spectrum[[#]]& @@@ peakpositions
spectrum[[ First /@ peakpositions ]]

(* Out:
{{350., 1.00004}, {428., 1.08134}}
{{350., 1.00004}, {428., 1.08134}}
*)

• Thank you, this works so far. Is there a way to merge the two lists together? For your example: {{350.,1.00004},{428.,1.08134}} – kaos May 20 '15 at 19:37
• Yes, it's actually easier :-) Use: spectrum[[#]]& @@@ peakpositions` – MarcoB May 20 '15 at 19:39
• Unfortunatly the university was just closed. I will try it as soon as Im home and mark the question as solved, if it works. – kaos May 20 '15 at 19:56