void MapAlignmentAlgorithmIdentification::alignPeptideIdentifications(
    vector<vector<PeptideIdentification> > & maps,
    vector<TransformationDescription> & transformations)
  {
    checkParameters_(maps.size());
    startProgress(0, 3, "aligning peptide identifications");

    if (reference_index_)     // reference is one of the input files
    {
      SeqToList rt_data;
      getRetentionTimes_(maps[reference_index_ - 1], rt_data);
      computeMedians_(rt_data, reference_, true);
    }

    // one set of RT data for each input map, except reference:
    vector<SeqToList> rt_data(maps.size() - bool(reference_index_));
    for (Size i = 0, j = 0; i < maps.size(); ++i)
    {
      if (i == reference_index_ - 1)
        continue;                              // skip reference map, if any
      getRetentionTimes_(maps[i], rt_data[j++]);
    }
    setProgress(1);

    computeTransformations_(rt_data, transformations, true);
    setProgress(2);

    // transformPeptideIdentifications(maps, transformations);
    setProgress(3);
    endProgress();
  }
  void MapAlignmentAlgorithmIdentification::getRetentionTimes_(
    MapType & features, SeqToList & rt_data)
  {
    bool use_feature_rt = param_.getValue("use_feature_rt").toBool();
    for (typename MapType::Iterator feat_it = features.begin();
         feat_it != features.end(); ++feat_it)
    {
      if (use_feature_rt)
      {
        // find the peptide ID closest in RT to the feature centroid:
        String sequence;
        DoubleReal rt_distance = numeric_limits<DoubleReal>::max();
        bool any_good_hit = false;
        for (vector<PeptideIdentification>::iterator pep_it =
               feat_it->getPeptideIdentifications().begin(); pep_it !=
             feat_it->getPeptideIdentifications().end(); ++pep_it)
        {
          if (hasGoodHit_(*pep_it))
          {
            any_good_hit = true;
            DoubleReal current_distance =
              abs(double(pep_it->getMetaValue("RT")) - feat_it->getRT());
            if (current_distance < rt_distance)
            {
              sequence = pep_it->getHits()[0].getSequence().toString();
              rt_distance = current_distance;
            }
          }
        }

        if (any_good_hit)
          rt_data[sequence] << feat_it->getRT();

      }
      else
      {
        getRetentionTimes_(feat_it->getPeptideIdentifications(), rt_data);
      }
    }

    if (!use_feature_rt && param_.getValue("use_unassigned_peptides").toBool())
    {
      getRetentionTimes_(features.getUnassignedPeptideIdentifications(),
                         rt_data);
    }

    // remove duplicates (can occur if a peptide ID was assigned to several
    // features due to overlap or annotation tolerance):
    for (SeqToList::iterator rt_it = rt_data.begin();
         rt_it != rt_data.end(); ++rt_it)
    {
      DoubleList & rt_values = rt_it->second;
      sort(rt_values.begin(), rt_values.end());
      DoubleList::iterator it = unique(rt_values.begin(), rt_values.end());
      rt_values.resize(it - rt_values.begin());
    }
  }
  void MapAlignmentAlgorithmIdentification::setReference(Size reference_index,
                                                         const String & reference_file)
  {
    reference_.clear();
    reference_index_ = reference_index;
    // reference is one of the input files, or no reference given:
    if (reference_index_ || reference_file.empty())
      return;

    // reference is external file:
    LOG_DEBUG << "Extracting reference RT data..." << endl;
    SeqToList rt_data;
    bool sorted = true;
    FileTypes::Type filetype = FileHandler::getType(reference_file);
    if (filetype == FileTypes::MZML)
    {
      MSExperiment<> experiment;
      MzMLFile().load(reference_file, experiment);
      getRetentionTimes_(experiment, rt_data);
      sorted = false;
    }
    else if (filetype == FileTypes::FEATUREXML)
    {
      FeatureMap<> features;
      FeatureXMLFile().load(reference_file, features);
      getRetentionTimes_(features, rt_data);
    }
    else if (filetype == FileTypes::CONSENSUSXML)
    {
      ConsensusMap features;
      ConsensusXMLFile().load(reference_file, features);
      getRetentionTimes_(features, rt_data);
    }
    else if (filetype == FileTypes::IDXML)
    {
      vector<ProteinIdentification> proteins;
      vector<PeptideIdentification> peptides;
      IdXMLFile().load(reference_file, proteins, peptides);
      getRetentionTimes_(peptides, rt_data);
    }

    computeMedians_(rt_data, reference_, sorted);
    if (reference_.empty())
    {
      throw Exception::MissingInformation(
              __FILE__, __LINE__, __PRETTY_FUNCTION__,
              "Could not extract retention time information from the reference file");
    }
  }
 // lists of peptide hits in "maps" will be sorted
 void MapAlignmentAlgorithmIdentification::getRetentionTimes_(
   MSExperiment<> & experiment, SeqToList & rt_data)
 {
   for (MSExperiment<>::Iterator exp_it = experiment.begin();
        exp_it != experiment.end(); ++exp_it)
   {
     getRetentionTimes_(exp_it->getPeptideIdentifications(), rt_data);
   }
   // duplicates should not be possible -> no need to remove them
 }
 // lists of peptide hits in "maps" will be sorted
 bool MapAlignmentAlgorithmIdentification::getRetentionTimes_(
   PeakMap& experiment, SeqToList& rt_data)
 {
   for (PeakMap::Iterator exp_it = experiment.begin();
        exp_it != experiment.end(); ++exp_it)
   {
     getRetentionTimes_(exp_it->getPeptideIdentifications(), rt_data);
   }
   // duplicate annotations should not be possible -> no need to remove them
   return false;
 }