AMPD Function

public pure function AMPD(data, extend) result(location)

Automatic multiscale-based peak detection (AMPD)
峰值查找算法

Arguments

Type IntentOptional Attributes Name
real(kind=sk_real_kind), intent(in) :: data(:)

Input data
数据

logical, intent(in), optional :: extend

Extend data width to get two end peaks
是否增强数据宽度以获取两端最大峰值

Return Value integer, allocatable, (:)

Peak position
峰值位置


Contents

Source Code


Source Code

    pure function AMPD(data, extend) result(location)
        real(sk_real_kind), intent(in) :: data(:)                 !! Input data <br>
                                                        !! 数据
        logical, intent(in), optional :: extend         !! Extend data width to get two end peaks <br>
                                                        !! 是否增强数据宽度以获取两端最大峰值
        integer, allocatable :: location(:)             !! Peak position <br>
                                                        !! 峰值位置
        integer :: L, N, k, i, row_sum, min_index, extend_size
        integer, allocatable :: arr_row_sum(:)
        integer, allocatable :: p_data(:)
        logical :: extend_
        real(sk_real_kind), allocatable :: data_(:)

        if (present(extend)) then
            extend_ = extend
        else
            extend_ = .false.
        end if

        ! 确定最佳窗体宽度
        N = size(data)
        L = N/2 + 1
        allocate (arr_row_sum(L))
        do k = 1, L
            row_sum = 0
            do i = k, N - k
                if (i - k == 0 .or. i + k == N + 1) cycle
                if (data(i) > data(i - k) .and. data(i) > data(i + k)) row_sum = row_sum - 1
            end do
            arr_row_sum(k) = row_sum
        end do
        min_index = minloc(arr_row_sum, dim=1) ! 通过最小值确定最佳窗体宽度,显著提升峰值特征,方便查找峰值

        ! 查找峰值
        if (extend_) then
            extend_size = min_index + 1
        else
            extend_size = 0
        end if
        N = N + extend_size*2
        allocate (p_data(N), source=0)
        if (extend_) then
            allocate (data_(N))
            associate (min => minval(data, dim=1))
                data_(:extend_size) = min
                data_(extend_size + 1:N - extend_size) = data(:)
                data_(N - extend_size + 1:) = min
            end associate
        else
            allocate (data_(N), source=data)
        end if
        do k = 1, min_index + 1
            do i = k, N - k
                if (i - k == 0 .or. i + k == N + 1) cycle
                if (data_(i) > data_(i - k) .and. data_(i) > data_(i + k)) p_data(i) = p_data(i) + 1
            end do
        end do

        allocate (location(0))
        do i = 1, N
            if (p_data(i) == min_index) location = [location, i]
        end do
        if (extend_) location = location - extend_size

    end function AMPD