FunctionPeakDetection
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description Method used for peak detection, similar to MATLAB peakdet method
library(title='FunctionPeakDetection')

import RicardoSantos/ArrayGenerate/1 as ag

// @function Method for detecting peaks.
// @param sample_x float array, sample with indices.
// @param sample_y float array, sample with data.
// @param delta float, positive threshold value for detecting a peak.
// @returns tuple with found max/min peak indices.
export function (float[] sample_x, float[] sample_y, float delta) => //{
	int _size_x = array.size(sample_x)
	int _size_y = array.size(sample_y)
	//
	switch
	    (_size_x != _size_y) => runtime.error('FunctionPeakDetection -> function(): "sample_x" and "sample_y" size does not match.')
	    (delta < 0.0) => runtime.error('FunctionPeakDetection -> function(): "delta" must be positive.')
	//
	float[] _maxtab = array.new_float()
	float[] _mintab = array.new_float()
	float _mn = +1.0e308
	float _mx = -1.0e308
	float _mnpos = na
	float _mxpos = na
    bool _look_for_max = true
	for _i = 0 to _size_x-1
	    _current = array.get(sample_y, _i)
	    if _current > _mx
	        _mx := _current
	        _mxpos := array.get(sample_x, _i)
	    if _current < _mn
	        _mn := _current
	        _mnpos := array.get(sample_x, _i)
	    if _look_for_max
	        if _current < (_mx - delta)
	            array.push(_maxtab, _mxpos)
	            _mn := _current
	            _mnpos := array.get(sample_x, _i)
	            _look_for_max := false
	    else
	        if _current > (_mn + delta)
	            array.push(_mintab, _mnpos)
	            _mx := _current
	            _mxpos := array.get(sample_x, _i)
	            _look_for_max := true
	[_maxtab, _mintab]
//{ reference:
//      https://github.com/tyiannak/pyAudioAnalysis/blob/master/pyAudioAnalysis/utilities.py#L33
//{ usage:
// this is just a example, label garbage collection is not taken in account..
x = bar_index < 101 ? array.from(0.0) : ag.sequence_from_series(bar_index, 100, 0, true)
y = bar_index < 101 ? array.from(0.0) : ag.sequence_from_series(close, 100, 0, true)
delta = array.stdev(y)
[mx, mn] = function(x, y, delta)
if array.size(mx) > 0
    for _i = 0 to array.size(mx)-1
        label.new(int(array.get(mx, _i)), close[bar_index-array.get(mx, _i)], 'V')
if array.size(mn) > 0
    for _i = 0 to array.size(mn)-1
        label.new(int(array.get(mn, _i)), close[bar_index-array.get(mn, _i)], 'A', style=label.style_label_up)
plot(close)
//}}

