X
14158

Finding multiple local max/min values for 2D plots with IDL

As is, IDL does not have a built in function to find multiple local maximums or minimums for 2D plots. Luckily, there is a simple algorithm that can be applied to a data set to determine if a point is a maximum or minimum. The algorithm works by checking the point to the left and to the right for the i-th point and seeing if the i-th point has a larger value than it's neighbors. If the i-th point is larger than it's neighbors, then the index gets added to a list and returned as an array at the end of the algorithm.

The algorithm also has a keyword included, /MINIMA, for finding the local minimum values. The default is to find the local maximums. In order to find the local minimums, the y-values are just multiplied by -1, which will make the local minimums into local maximums, and then the same algorithm is performed.

It should be noted that this program may not work well for data sets with lots of noise. This is because the code will extract each and every maximum or minimum that satisfy the above conditions. It is up to the user to find a proper filter or data processing method to pre-process their data.

To run the program, save the code below as local_max_finder.pro and then compile and run from the IDL Workbench. It should be noted that the program makes use of a main level program after the function definition so that you don't have to have two .pro files.

function local_max_finder, datax, datay, $
    ;keyword for minimum /minima
    minima = minima
    ;set compile options
    compile_opt idl2
    
    ;initialize list
    max_points = list()
    
    data_x = datax
    data_y = datay
    ;check for keyword, flip the sign of the y values
    if keyword_set(minima) then data_y = -datay

    ;iterate through elements
    for i=1, n_elements(data_y)-2 do begin
        ;previous point less than i-th point and next point less than i-th point
        if ( (data_y[i-1] lt data_y[i]) AND (data_y[i] gt data_y[i+1])) then max_points.add, i
    endfor
    
    ;return an array of the indices where the extrema occur
    return, max_points.toarray()
    
end


;main level program
compile_opt idl2
ireset, /no_prompt

;make some test data
xvals = findgen(2000)
yvals = 2*sin( xvals*(2*!PI/500) ) + sin( xvals*(2*!PI/1000) )
;plot the test data
p = plot(xvals, yvals,$
    xtitle = 'X position', ytitle = 'Amplitude',$
    yminor = 3, xminor = 3, title = 'Neat Local Max/Min example')
    

;find the local max index
local_maxmin_index = local_max_finder(xvals, yvals)

;extract the x/y pairings of the local max/min
x_extrema = xvals[local_maxmin_index]
y_extrema = yvals[local_maxmin_index]

;overplot the max/min on the existing plot
p2 = scatterplot(x_extrema, y_extrema, /current, /overplot, $
    symbol = 'o', sym_color = 'r', sym_thick = 2)


;find the local min index with /minima keyword
local_maxmin_index = local_max_finder(xvals, yvals, /minima)

;extract the x/y pairings of the local max/min
x_extrema = xvals[local_maxmin_index]
y_extrema = yvals[local_maxmin_index]

;overplot the min on the existing plot
p3 = scatterplot(x_extrema, y_extrema, /current, /overplot, $
    symbol = 'o', sym_color = 'b', sym_thick = 2)

end



Reviewed by ZN 7/2015