# How to find local minima of data using PeakDetect

One of the great new function in v10 is PeakDetect.

It can detect peaks (local maxima) according to desired sharpness as shown in this example:

data = Table[{x, (Sin[10 x] + 2) Exp[-x^2]}, {x, -4, 4, .01}];
peaks = Pick[data, PeakDetect[data[[;; , 2]], .01, .0005], 1];
ListPlot[{data, peaks},
PlotStyle -> {Automatic, Directive[Red, PointSize[0.02]]}]


The question is how to find valleys (local minima) of the such data using this new function?

• Apply it to $-f$? – Mark McClure Jul 14 '14 at 1:04
• @MarkMcClure Just saw your comment after I posted it. Yes, that is the first thing I though about also. – Nasser Jul 14 '14 at 1:08
• @MarkMcClure great trick. thanks to you and to Nasser. – Algohi Jul 14 '14 at 1:09

As has been observed

data = Table[{x, (Sin[10 x] + 2) Exp[-x^2]}, {x, -4, 4, .01}];
peaks = Pick[data, PeakDetect[data[[;; , 2]], .01, .0005], 1];
troughs = Pick[data, PeakDetect[-data[[;; , 2]], .01, .0005], 1];
ListPlot[{data, peaks, troughs},
PlotStyle -> {Automatic, Directive[Red, PointSize[0.02]],
Directive[Green, PointSize[0.02]]}]

• It would be nice to have a method to find local minima and maxima in one go. For large data, this doubles the time, somewhat unnecessarily. – István Zachar Apr 27 '16 at 11:38
• @IstvánZachar yes you are right. I will think about . It approaches 2 years since the answer. MMa has changed, I have changed but not in a desirable direction. I would very much value a better answer than mine. If you post one "comment me" in. – ubpdqn Apr 27 '16 at 11:41

Not an answer, more of a extended comment. (Since the question requires the use of PeakDetect.)

Some (more than half actually) of the local extrema are missed. This becomes obvious using Log plots (modifying the code of ubpdqn):

data = Table[{x, (Sin[10 x] + 2) Exp[-x^2]}, {x, -4, 4, .01}];
peaks = Pick[data, PeakDetect[data[[;; , 2]], .01, .0005], 1];
troughs = Pick[data, PeakDetect[-data[[;; , 2]], .01, .0005], 1];
opts = {PlotStyle -> {Automatic, Directive[Red, PointSize[0.02]],
Directive[Green, PointSize[0.02]]}, PlotTheme -> "Detailed",
ImageSize -> Medium};
Grid[{{ListPlot[{data, peaks, troughs}, opts],
ListLogPlot[{data, peaks, troughs}, opts]}}]


I tried few times to get better results by tweaking the PeakDetect parameters without success.

Using Quantile regression fitting to find the local extrema gives better results:

Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/Applications/QuantileRegressionForLocalExtrema.m"]

Block[{data = data, qfuncs, showFunc},
{qfuncs, extrema} = QRFindExtrema[data, 40, 2, 12, {0.5}];
showFunc[listPlotFunc_] :=
listPlotFunc[Join[{data}, extrema],
PlotStyle -> {{}, {PointSize[Medium], Green}, {PointSize[Medium],
Red}}, PlotTheme -> "Detailed", PlotRange -> All,
ImageSize -> Medium];
Grid[{{showFunc[ListPlot], showFunc[ListLogPlot]}}]
]


Here is a related discussion: "Finding very weak peaks".

data = Table[{x, -(Sin[10 x] + 2) Exp[-x^2]}, {x, -4, 4, .01}];
peaks = Pick[data, PeakDetect[data[[;; , 2]], .01, .0005], 1];
ListPlot[{data, peaks}, PlotStyle -> {Automatic, Directive[Red, PointSize[0.02]]}];
Rotate[%, 180 Degree]


Or as Pickett mentioned below, just add - to data as in

data = Table[{x, (Sin[10 x] + 2) Exp[-x^2]}, {x, -4, 4, .01}];
peaks = Pick[data, PeakDetect[-data[[;; , 2]], .01, .0005], 1];
ListPlot[{data, peaks}, PlotStyle -> {Automatic, Directive[Red, PointSize[0.02]]}]

• It's easier to just add - in front of data[[;;,2]]. This way you don't have to rotate the graph. – C. E. Jul 14 '14 at 1:12
• @Nasser, it would better if you ListPlot[{-data,-peaks},....] – Algohi Jul 14 '14 at 1:13
• @Pickett, sure that is better so no rotation is needed. Thanks. – Nasser Jul 14 '14 at 1:13