void GaussTraceFitter::fit(FeatureFinderAlgorithmPickedHelperStructs::MassTraces& traces)
  {
    LOG_DEBUG << "Traces length: " << traces.size() << "\n";
    setInitialParameters_(traces);

    Eigen::VectorXd x_init(NUM_PARAMS_);
    x_init(0) = height_;
    x_init(1) = x0_;
    x_init(2) = sigma_;

    TraceFitter::ModelData data;
    data.traces_ptr = &traces;
    data.weighted = this->weighted_;
    GaussTraceFunctor functor(NUM_PARAMS_, &data);

    TraceFitter::optimize_(x_init, functor);
  }
  void EGHTraceFitter::setInitialParameters_(FeatureFinderAlgorithmPickedHelperStructs::MassTraces& traces)
  {
    LOG_DEBUG << "EGHTraceFitter->setInitialParameters(...)" << std::endl;
    LOG_DEBUG << "Number of traces: " << traces.size() << std::endl;

    // aggregate data; some peaks (where intensity is zero) can be missing!
    // mapping: RT -> total intensity over all mass traces
    std::list<std::pair<double, double> > total_intensities;
    traces.computeIntensityProfile(total_intensities);

    // compute moving average for smoothing:
    const Size N = total_intensities.size();
    const Size LEN = 2;   // window size: 2 * LEN + 1
    std::vector<double> totals(N + 2 * LEN);   // pad with zeros at ends
    Int index = LEN;
    // LOG_DEBUG << "Summed intensities:\n";
    for (std::list<std::pair<double, double> >::iterator it =
           total_intensities.begin(); it != total_intensities.end(); ++it)
    {
      totals[index++] = it->second;
      // LOG_DEBUG << it->second << std::endl;
    }

    std::vector<double> smoothed(N);
    Size max_index = 0;   // index of max. smoothed intensity
    // LOG_DEBUG << "Smoothed intensities:\n";
    double sum = std::accumulate(&totals[LEN], &totals[2 * LEN], 0.0);
    for (Size i = 0; i < N; ++i)
    {
      sum += totals[i + 2 * LEN];
      smoothed[i] = sum / (2 * LEN + 1);
      sum -= totals[i];
      if (smoothed[i] > smoothed[max_index]) max_index = i;
      // LOG_DEBUG << smoothed[i] << std::endl;
    }
    LOG_DEBUG << "Maximum at index " << max_index << std::endl;
    height_ = smoothed[max_index] - traces.baseline;
    LOG_DEBUG << "height: " << height_ << std::endl;
    std::list<std::pair<double, double> >::iterator it = total_intensities.begin();
    std::advance(it, max_index);
    apex_rt_ = it->first;
    LOG_DEBUG << "apex_rt: " << apex_rt_ << std::endl;
    region_rt_span_ = (total_intensities.rbegin()->first -
                       total_intensities.begin()->first);
    LOG_DEBUG << "region_rt_span: " << region_rt_span_ << std::endl;

    // find RT values where intensity is at half-maximum:
    index = static_cast<Int>(max_index);
    while ((index > 0) && (smoothed[index] > height_ * 0.5))
      --index;
    double left_height = smoothed[index];
    it = total_intensities.begin();
    std::advance(it, index);
    double left_rt = it->first;
    LOG_DEBUG << "Left half-maximum at index " << index << ", RT " << left_rt
              << std::endl;
    index = static_cast<Int>(max_index);
    while ((index < Int(N - 1)) && (smoothed[index] > height_ * 0.5))
      ++index;
    double right_height = smoothed[index];
    it = total_intensities.end();
    std::advance(it, index - Int(N));
    double right_rt = it->first;
    LOG_DEBUG << "Right half-maximum at index " << index << ", RT "
              << right_rt << std::endl;

    double A = apex_rt_ - left_rt;
    double B = right_rt - apex_rt_;
    //LOG_DEBUG << "A: " << A << std::endl;
    //LOG_DEBUG << "B: " << B << std::endl;

    // compute estimates for tau / sigma based on A and B:
    double alpha = (left_height + right_height) * 0.5 / height_;   // ~0.5
    double log_alpha = log(alpha);

    tau_ = -1 / log_alpha * (B - A);
    //EGH function fails when tau==0
    if (tau_ == 0) tau_ = std::numeric_limits<double>::epsilon();

    LOG_DEBUG << "tau: " << tau_ << std::endl;
    sigma_ = sqrt(-0.5 / log_alpha * B * A);
    LOG_DEBUG << "sigma: " << sigma_ << std::endl;
  }
  void GaussTraceFitter::setInitialParameters_(FeatureFinderAlgorithmPickedHelperStructs::MassTraces& traces)
  {
    LOG_DEBUG << "GaussTraceFitter->setInitialParameters(...)" << std::endl;
    LOG_DEBUG << "Number of traces: " << traces.size() << std::endl;

    // aggregate data; some peaks (where intensity is zero) can be missing!
    // mapping: RT -> total intensity over all mass traces
    std::list<std::pair<double, double> > total_intensities;
    traces.computeIntensityProfile(total_intensities);

    const Size N = total_intensities.size();
    const Size LEN = 2; // window size: 2 * LEN + 1

    std::vector<double> totals(N + 2 * LEN); // pad with zeros at ends
    Int index = LEN;
    // LOG_DEBUG << "Summed intensities:\n";
    for (std::list<std::pair<double, double> >::iterator it =
           total_intensities.begin(); it != total_intensities.end(); ++it)
    {
      totals[index++] = it->second;
      // LOG_DEBUG << it->second << std::endl;
    }

    std::vector<double> smoothed(N);
    Size max_index = 0; // index of max. smoothed intensity
    if (N <= LEN + 1) // not enough distinct x values for smoothing
    {
      // throw Exception::UnableToFit(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "UnableToFit-MovingAverage", "Too few time points for smoothing with window size " + String(2 * LEN + 1));
      for (Size i = 0; i < N; ++i)
      {
        smoothed[i] = totals[i + LEN];
        if (smoothed[i] > smoothed[max_index]) max_index = i;
      }
    }
    else // compute moving average for smoothing
    {
      // LOG_DEBUG << "Smoothed intensities:\n";
      double sum = std::accumulate(&totals[LEN], &totals[2 * LEN], 0.0);
      for (Size i = 0; i < N; ++i)
      {
        sum += totals[i + 2 * LEN];
        smoothed[i] = sum / (2 * LEN + 1);
        sum -= totals[i];
        if (smoothed[i] > smoothed[max_index]) max_index = i;
        // LOG_DEBUG << smoothed[i] << std::endl;
      }
    }
    LOG_DEBUG << "Maximum at index " << max_index << std::endl;
    height_ = smoothed[max_index] - traces.baseline;
    LOG_DEBUG << "height: " << height_ << std::endl;
    std::list<std::pair<double, double> >::iterator it = total_intensities.begin();
    std::advance(it, max_index);
    x0_ = it->first;
    LOG_DEBUG << "x0: " << x0_ << std::endl;
    region_rt_span_ = (total_intensities.rbegin()->first -
                       total_intensities.begin()->first);
    LOG_DEBUG << "region_rt_span: " << region_rt_span_ << std::endl;

    // find RT values where intensity is at half-maximum:
    index = static_cast<Int>(max_index);
    while ((index > 0) && (smoothed[index] > height_ * 0.5))
      --index;
    double left_height = smoothed[index];
    it = total_intensities.begin();
    std::advance(it, index);
    double left_rt = it->first;
    LOG_DEBUG << "Left half-maximum at index " << index << ", RT " << left_rt
              << std::endl;
    index = static_cast<Int>(max_index);
    while ((index < Int(N - 1)) && (smoothed[index] > height_ * 0.5))
      ++index;
    double right_height = smoothed[index];
    it = total_intensities.end();
    std::advance(it, index - Int(N));
    double right_rt = it->first;
    LOG_DEBUG << "Right half-maximum at index " << index << ", RT "
              << right_rt << std::endl;

    double delta_x = right_rt - left_rt;
    double alpha = (left_height + right_height) * 0.5 / height_; // ~0.5
    if (alpha >= 1) sigma_ = 1.0; // degenerate case, all values are the same
    else sigma_ = delta_x * 0.5 / sqrt(-2.0 * log(alpha));
    LOG_DEBUG << "sigma: " << sigma_ << std::endl;
  }