void AbsoluteQuantitation::optimizeCalibrationCurves(
    std::map<String, std::vector<AbsoluteQuantitationStandards::featureConcentration>> & components_concentrations)
  {

    for (auto& quant_method : quant_methods_)
    {
      // DEBUGGING
      // std::cout << "optimizing calibration curves for " << quant_method.first << "." << std::endl;

      if (components_concentrations.count(quant_method.first)>0 && optimization_method_ == "iterative")
      { 
        // optimize the calibraiton curve for the component
        Param optimized_params;
        optimizeCalibrationCurveIterative(
          components_concentrations[quant_method.first],
          quant_method.second.getFeatureName(),
          quant_method.second.getTransformationModel(),
          quant_method.second.getTransformationModelParams(),
          optimized_params);

        // calculate the R2 and bias
        std::vector<double> biases;
        double correlation_coefficient = 0.0;
        calculateBiasAndR(
          components_concentrations[quant_method.first],
          quant_method.second.getFeatureName(),
          quant_method.second.getTransformationModel(),
          optimized_params,
          biases,
          correlation_coefficient);

        // record the updated information
        quant_method.second.setCorrelationCoefficient(correlation_coefficient);
        quant_method.second.setLLOQ(components_concentrations[quant_method.first][0].actual_concentration); //due to ascending sort
        quant_method.second.setULOQ(components_concentrations[quant_method.first][components_concentrations[quant_method.first].size()-1].actual_concentration); //due to ascending sort
        quant_method.second.setTransformationModelParams(optimized_params);
        quant_method.second.setNPoints(components_concentrations[quant_method.first].size());
      }
      else if (optimization_method_ != "iterative")
      {
        throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
          "Unsupported calibration curve optimization method '" + optimization_method_ + "'.");
      }
      else
      {
        LOG_INFO << "Warning: Standards not found for component " << quant_method.first << ".";
      }
    }
  } 
  void AbsoluteQuantitation::optimizeCalibrationCurves(
    std::map<String, std::vector<AbsoluteQuantitationStandards::featureConcentration>> & components_concentrations)
  {
    std::map<String, std::vector<AbsoluteQuantitationStandards::featureConcentration>>& cc = components_concentrations;
    for (std::pair<const String, AbsoluteQuantitationMethod>& quant_method : quant_methods_)
    {
      const String& component_name = quant_method.first;
      AbsoluteQuantitationMethod& component_aqm = quant_method.second;
      if (cc.count(component_name) && optimization_method_ == "iterative")
      {
        // optimize the calibration curve for the component
        Param optimized_params;
        bool optimal_calibration_found = optimizeCalibrationCurveIterative(
          cc[component_name],
          component_aqm.getFeatureName(),
          component_aqm.getTransformationModel(),
          component_aqm.getTransformationModelParams(),
          optimized_params);

        // order component concentrations and update the lloq and uloq
        std::vector<AbsoluteQuantitationStandards::featureConcentration>::const_iterator it;
        it = std::min_element(cc[component_name].begin(), cc[component_name].end(), [](
            const AbsoluteQuantitationStandards::featureConcentration& lhs,
            const AbsoluteQuantitationStandards::featureConcentration& rhs
          )
          {
            return lhs.actual_concentration < rhs.actual_concentration;
          }
        );
        component_aqm.setLLOQ(it->actual_concentration);
        it = std::max_element(cc[component_name].begin(), cc[component_name].end(), [](
            const AbsoluteQuantitationStandards::featureConcentration& lhs,
            const AbsoluteQuantitationStandards::featureConcentration& rhs
          )
          {
            return lhs.actual_concentration < rhs.actual_concentration;
          }
        );
        component_aqm.setULOQ(it->actual_concentration);

        if (optimal_calibration_found)
        {
          // calculate the R2 and bias
          std::vector<double> biases;
          double correlation_coefficient = 0.0;
          calculateBiasAndR(
            cc[component_name],
            component_aqm.getFeatureName(),
            component_aqm.getTransformationModel(),
            optimized_params,
            biases,
            correlation_coefficient);

          // record the updated information
          component_aqm.setCorrelationCoefficient(correlation_coefficient);
          component_aqm.setTransformationModelParams(optimized_params);
          component_aqm.setNPoints(cc[component_name].size());
        }
        else 
        {
          component_aqm.setCorrelationCoefficient(0.0);
          component_aqm.setNPoints(0);
          component_aqm.setLLOQ(0.0);
          component_aqm.setULOQ(0.0);
        }
      }
      else if (optimization_method_ != "iterative")
      {
        throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION,
          "Unsupported calibration curve optimization method '" + optimization_method_ + "'.");
      }
      else
      {
        LOG_DEBUG << "Warning: Standards not found for component " << component_name << ".";
      }
    }
  }