detectPeaksEmiAbs method

List<List<int>> detectPeaksEmiAbs (Float64List data, int ixstart, int ixend, double noise, bool emi_first, double threshold, bool pickNegs)

Helper for detectPeaks0(). Detects peaks in data between ixstart, ixend (ixend exclusive). noise is used for differentiating peaks from noise. emi_first == true if emission peaks to be searched first. (emission = "mountains" peaks, absorption = "valleys"). All peaks <= threshold will not be addedto the list. If pickNegs is true, find only negative peaks. Returns list indices emission peaks, list indices absorption peaks (could be empty, but not null).

Implementation

static List<List<int>> detectPeaksEmiAbs(
    Float64List data,
    int ixstart,
    int ixend,
    double noise,
    bool emi_first,
    double threshold,
    bool pickNegs) {
  void invert() {
    if (pickNegs) {
      for (int i = ixstart; i < ixend; i++) {
        data[i] = -data[i];
      }
      // user may specify e.g. 10 or -10, for negative peaks this will be allright
      threshold = threshold.abs();
    }
  }

  invert(); // if necessary

  int i;
  int curmax_ix = ixstart;
  int curmin_ix = ixstart;
  bool is_detecting_emi = emi_first;

  double curmax = data[ixstart];
  double curmin = data[ixstart];

  List<int> emi_peaks = [];
  List<int> absop_peaks = [];

  double datai;
  for (i = ixstart; i < ixend; i++) {
    datai = data[i];
    if (datai > curmax) {
      curmax_ix = i;
      curmax = datai;
    }
    if (datai < curmin) {
      curmin_ix = i;
      curmin = datai;
    }

    if (is_detecting_emi && datai < (curmax - noise)) {
      if (data[curmax_ix] > threshold) emi_peaks.add(curmax_ix);

      is_detecting_emi = false;

      i = curmax_ix - 1;

      curmin = data[curmax_ix];
      curmin_ix = curmax_ix;
    } else if ((!is_detecting_emi) && datai > (curmin + noise)) {
      if (data[curmin_ix] > threshold) absop_peaks.add(curmin_ix);

      is_detecting_emi = true;

      i = curmin_ix - 1;

      curmax = data[curmin_ix];
      curmax_ix = curmin_ix;
    }
  }

  List.from(absop_peaks).forEach((pos) {
    if (data[pos] < threshold) absop_peaks.remove(pos);
  });

  invert(); // restore inverted if necessary
  return [emi_peaks, absop_peaks];
}