Feature ICPLLabeler::mergeFeatures_(Feature& feature_to_merge, const AASequence& labeled_feature_sequence, Map<String, Feature>& feature_index) const
  {
    // merge with feature from first map (if it exists)
    if (feature_index.count(labeled_feature_sequence.toString()) != 0)
    {
      // we only merge abundance and use feature from first map
      Feature new_f = feature_index[labeled_feature_sequence.toString()];

      new_f.setMetaValue(getChannelIntensityName(1), new_f.getIntensity());
      new_f.setMetaValue(getChannelIntensityName(2), feature_to_merge.getIntensity());
      new_f.setIntensity(new_f.getIntensity() + feature_to_merge.getIntensity());

      mergeProteinAccessions_(new_f, feature_to_merge);

      // remove feature from index
      feature_index.erase(labeled_feature_sequence.toString());

      return new_f;
    }
    else
    {
      // simply add feature from second channel, since we have no corresponding feature in the first channel
      return feature_to_merge;
    }
  }
Feature SILACLabeler::mergeFeatures_(Feature& labeled_feature, const String& unmodified_feature_sequence, Map<String, Feature>& feature_index, Int index_channel_id, Int labeled_channel_id) const
{
    // merge with feature from first map
    Feature merged_feature = feature_index[unmodified_feature_sequence];

    merged_feature.setMetaValue(getChannelIntensityName(index_channel_id), merged_feature.getIntensity());
    merged_feature.setMetaValue(getChannelIntensityName(labeled_channel_id), labeled_feature.getIntensity());

    merged_feature.setIntensity(merged_feature.getIntensity() + labeled_feature.getIntensity());

    mergeProteinAccessions_(merged_feature, labeled_feature);

    feature_index.erase(unmodified_feature_sequence);

    return merged_feature;
}
Feature SILACLabeler::mergeAllChannelFeatures_(Feature& heavy_channel_feature, const String& unmodified_feature_sequence, Map<String, Feature>& light_channel_feature_index, Map<String, Feature>& medium_channel_feature_index) const
{
    // merge with feature from first map
    Feature merged_feature = light_channel_feature_index[unmodified_feature_sequence];

    merged_feature.setMetaValue(getChannelIntensityName(1), merged_feature.getIntensity());
    merged_feature.setMetaValue(getChannelIntensityName(1), medium_channel_feature_index[unmodified_feature_sequence].getIntensity());
    merged_feature.setMetaValue(getChannelIntensityName(3), heavy_channel_feature.getIntensity());

    merged_feature.setIntensity(merged_feature.getIntensity() + heavy_channel_feature.getIntensity() + medium_channel_feature_index[unmodified_feature_sequence].getIntensity());

    mergeProteinAccessions_(merged_feature, medium_channel_feature_index[unmodified_feature_sequence]);
    mergeProteinAccessions_(merged_feature, heavy_channel_feature);

    light_channel_feature_index.erase(unmodified_feature_sequence);
    medium_channel_feature_index.erase(unmodified_feature_sequence);

    return merged_feature;
}
  double AbsoluteQuantitation::calculateRatio(const Feature & component_1, const Feature & component_2, const String & feature_name)
  {
    double ratio = 0.0;
    // member feature_name access
    if (feature_name == "intensity")
    {
      if (component_1.metaValueExists("native_id") && component_2.metaValueExists("native_id"))
      {
        const double feature_1 = component_1.getIntensity();
        const double feature_2 = component_2.getIntensity();
        ratio = feature_1 / feature_2;
      }
      else if (component_1.metaValueExists("native_id"))
      {
        LOG_DEBUG << "Warning: no IS found for component " << component_1.getMetaValue("native_id") << ".";
        const double feature_1 = component_1.getIntensity();
        ratio = feature_1;
      }
    }
    // metaValue feature_name access
    else
    {
      if (component_1.metaValueExists(feature_name) && component_2.metaValueExists(feature_name))
      {
        const double feature_1 = component_1.getMetaValue(feature_name);
        const double feature_2 = component_2.getMetaValue(feature_name);
        ratio = feature_1/feature_2;
      }
      else if (component_1.metaValueExists(feature_name))
      {
        LOG_DEBUG << "Warning: no IS found for component " << component_1.getMetaValue("native_id") << ".";
        const double feature_1 = component_1.getMetaValue(feature_name);
        ratio = feature_1;
      }
      else
      {
        LOG_DEBUG << "Feature metaValue " << feature_name << " not found for components " << component_1.getMetaValue("native_id") << " and " << component_2.getMetaValue("native_id") << ".";
      }
    }

    return ratio;
  }
	p.setIntensity(123.456f);
	p.setPosition(pos);
  p.setOverallQuality( (QualityType)0.9);
  p.setQuality( 0, (QualityType)0.1);
  p.setQuality( 1, (QualityType)0.2);
	p.setMetaValue("cluster_id",4712);
  p.setConvexHulls(hulls);

	Feature::PositionType pos2;
	Feature::IntensityType i2;

	Feature copy_of_p;
	copy_of_p.getConvexHull(); //this pre-calculates the overall convex hull in order to check that the recalculation flag is copied correctly
	copy_of_p = p;

	i2 = copy_of_p.getIntensity();
	pos2 = copy_of_p.getPosition();

  Feature::QualityType q2;

	TEST_REAL_SIMILAR(i2, 123.456)
	TEST_REAL_SIMILAR(pos2[0], 21.21)
	TEST_REAL_SIMILAR(pos2[1], 22.22)
	q2 = copy_of_p.getOverallQuality();
	TEST_REAL_SIMILAR(q2, 0.9)
	q2 = copy_of_p.getQuality(0);
	TEST_REAL_SIMILAR(q2, 0.1)
	q2 = copy_of_p.getQuality(1);
	TEST_REAL_SIMILAR(q2, 0.2)
	TEST_EQUAL(copy_of_p.getConvexHull().getHullPoints().size(),p.getConvexHull().getHullPoints().size())
	TEST_EQUAL(copy_of_p.getConvexHulls().size(),p.getConvexHulls().size())