View Source NxSignal.PeakFinding (NxSignal v0.2.0)

Peak finding algorithms.

Link to this section Summary

Functions

Finds a relative extrema along the selected :axis.

Finds a relative maximum along the selected :axis.

Finds a relative minimum along the selected :axis.

Link to this section Functions

Link to this function

argrelextrema(data, comparator_fn, opts \\ [])

View Source

Finds a relative extrema along the selected :axis.

A relative extremum is defined by the given comparator_fn function of arity 2 function that returns a boolean tensor.

This is the function upon which &argrelmax/2 and &argrelmin/2 are implemented.

Returns a map in the following format:

%{
  indices: #Nx.Tensor<...>,
  valid_indices: #Nx.Tensor<...>
}
  • :indices - the {n, rank} tensor of indices. Contains -1 as a placeholder for invalid indices.

  • :valid_indices - the number of valid indices that lead the tensor.

options

Options

  • :axis - the axis along which to do comparisons. Defaults to 0.
  • :order - the number of neighbor samples considered for the comparison in each direction. Defaults to 1.

examples

Examples

First, do read the examples on argrelmax/2 keeping in mind that it is equivalent to argrelextrema(&1, &Nx.greater/2, &2), as well as argrelmin/2 which is equivalent to argrelextrema(&1, &Nx.less/2, &2).

Having that in mind, we will expand on those concepts by using a custom function. For instance, we can change the definition of a relative maximum to one where a number is a relative maximum if it is greater than or equal to the double of its neighbors, as follows:

iex> comparator = fn x, y -> Nx.greater_equal(x, Nx.multiply(y, 2)) end
iex> x = Nx.tensor([0, 1, 3, 2, 0, 1, 0, 0, 0, 2, 1])
iex> result = NxSignal.PeakFinding.argrelextrema(x, comparator)
iex> result.valid_indices
#Nx.Tensor<
  u64
  3
>
iex> result.indices[0..2]
#Nx.Tensor<
  s64[3][1]
  [
    [5],
    [7],
    [9]
  ]
>

Same applies for finding local minima. In the next example, we find all local minima (i.e. &Nx.less/2) that are different to the global minimum.

iex> x = Nx.tensor([0, 1, 0, 2, 1, 3, 0, 1])
iex> global_minimum = Nx.reduce_min(x)
iex> comparator = fn x, y ->
...> x_not_global = Nx.not_equal(x, global_minimum)
...> y_not_global = Nx.not_equal(y, global_minimum)
...> both_not_global = Nx.logical_and(x_not_global, y_not_global)
...> Nx.logical_and(Nx.less(x, y), both_not_global)
...> end
iex> result = NxSignal.PeakFinding.argrelextrema(x, comparator)
iex> result.valid_indices
#Nx.Tensor<
  u64
  1
>
iex> result.indices[0..0]
#Nx.Tensor<
  s64[1][1]
  [
    [4]
  ]
>
Link to this function

argrelmax(data, opts \\ [])

View Source

Finds a relative maximum along the selected :axis.

A relative maximum is defined by the element being greater than its neighbors along the axis :axis.

Returns a map in the following format:

%{
  indices: #Nx.Tensor<...>,
  valid_indices: #Nx.Tensor<...>
}
  • :indices - the {n, rank} tensor of indices. Contains -1 as a placeholder for invalid indices.

  • :valid_indices - the number of valid indices that lead the tensor.

options

Options

  • :axis - the axis along which to do comparisons. Defaults to 0.
  • :order - the number of neighbor samples considered for the comparison in each direction. Defaults to 1.

examples

Examples

iex> x = Nx.tensor([2, 1, 2, 3, 2, 0, 1, 0])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmax(x)
iex> valid_indices
#Nx.Tensor<
  u64
  2
>
iex> indices
#Nx.Tensor<
  s64[8][1]
  [
    [3],
    [6],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1]
  ]
>
iex> Nx.slice_along_axis(indices, 0, Nx.to_number(valid_indices), axis: 0)
#Nx.Tensor<
  s64[2][1]
  [
    [3],
    [6]
  ]
>

For the same tensor in the previous example, we can use :order to check if the relative maxima are extrema in a wider neighborhood.

iex> x = Nx.tensor([2, 1, 2, 3, 2, 0, 1, 0])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmax(x, order: 3)
iex> valid_indices
#Nx.Tensor<
  u64
  1
>
iex> indices
#Nx.Tensor<
  s64[8][1]
  [
    [3],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1]
  ]
>
iex> Nx.slice_along_axis(indices, 0, Nx.to_number(valid_indices), axis: 0)
#Nx.Tensor<
  s64[1][1]
  [
    [3]
  ]
>

We can also apply this function to tensors with a larger rank:

iex> x = Nx.tensor([[1, 2, 1, 2], [6, 2, 0, 0], [5, 3, 4, 4]])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmax(x)
iex> valid_indices
#Nx.Tensor<
  u64
  1
>
iex> indices[0]
#Nx.Tensor<
  s64[2]
  [1, 0]
>
iex> %{indices: indices} = NxSignal.PeakFinding.argrelmax(x, axis: 1)
iex> valid_indices
#Nx.Tensor<
  u64
  1
>
iex> indices[0]
#Nx.Tensor<
  s64[2]
  [0, 1]
>
Link to this function

argrelmin(data, opts \\ [])

View Source

Finds a relative minimum along the selected :axis.

A relative minimum is defined by the element being greater than its neighbors along the axis :axis.

Returns a map in the following format:

%{
  indices: #Nx.Tensor<...>,
  valid_indices: #Nx.Tensor<...>
}
  • :indices - the {n, rank} tensor of indices. Contains -1 as a placeholder for invalid indices.

  • :valid_indices - the number of valid indices that lead the tensor.

options

Options

  • :axis - the axis along which to do comparisons. Defaults to 0.
  • :order - the number of neighbor samples considered for the comparison in each direction. Defaults to 1.

examples

Examples

iex> x = Nx.tensor([2, 1, 2, 3, 2, 0, 1, 0])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmin(x)
iex> valid_indices
#Nx.Tensor<
  u64
  2
>
iex> indices
#Nx.Tensor<
  s64[8][1]
  [
    [1],
    [5],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1]
  ]
>
iex> Nx.slice_along_axis(indices, 0, Nx.to_number(valid_indices), axis: 0)
#Nx.Tensor<
  s64[2][1]
  [
    [1],
    [5]
  ]
>

For the same tensor in the previous example, we can use :order to check if the relative maxima are extrema in a wider neighborhood.

iex> x = Nx.tensor([2, 1, 2, 3, 2, 0, 1, 0])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmin(x, order: 3)
iex> valid_indices
#Nx.Tensor<
  u64
  1
>
iex> indices
#Nx.Tensor<
  s64[8][1]
  [
    [1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1],
    [-1]
  ]
>
iex> Nx.slice_along_axis(indices, 0, Nx.to_number(valid_indices), axis: 0)
#Nx.Tensor<
  s64[1][1]
  [
    [1]
  ]
>

We can also apply this function to tensors with a larger rank:

iex> x = Nx.tensor([[1, 2, 1, 2], [6, 2, 0, 0], [5, 3, 4, 4]])
iex> %{indices: indices, valid_indices: valid_indices} = NxSignal.PeakFinding.argrelmin(x)
iex> valid_indices
#Nx.Tensor<
  u64
  2
>
iex> indices[0..1]
#Nx.Tensor<
  s64[2][2]
  [
    [1, 2],
    [1, 3]
  ]
>
iex> %{indices: indices} = NxSignal.PeakFinding.argrelmin(x, axis: 1)
iex> valid_indices
#Nx.Tensor<
  u64
  2
>
iex> indices[0..1]
#Nx.Tensor<
  s64[2][2]
  [
    [0, 2],
    [2, 1]
  ]
>