///|
pub fn find_peaks(
  signal : ArrayView[Double],
  threshold? : Double = 0.0,
  min_distance? : Int = 1,
) -> Array[SignalPeak] raise SpectrumError {
  if signal.length() == 0 {
    raise EmptySignal
  }
  if threshold < 0.0 {
    raise InvalidArgument(message="threshold must be non-negative")
  }
  if min_distance <= 0 {
    raise InvalidArgument(message="min_distance must be positive")
  }
  let candidates : Array[SignalPeak] = []
  if signal.length() >= 3 {
    for i in 1..<(signal.length() - 1) {
      let value = signal[i]
      if value >= threshold && value > signal[i - 1] && value >= signal[i + 1] {
        candidates.push({ index: i, value })
      }
    }
  }
  let selected : Array[SignalPeak] = []
  let blocked = Array::make(candidates.length(), false)
  let mut remaining = candidates.length()
  while remaining > 0 {
    let mut best = -1
    for i in 0.. candidates[best].value) {
        best = i
      }
    }
    if best < 0 {
      remaining = 0
    } else {
      selected.push(candidates[best])
      for i in 0..