1
// --------------------------------------------------------------------------
2
// OpenMS -- Open-Source Mass Spectrometry
3
// --------------------------------------------------------------------------
4
// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5
// ETH Zurich, and Freie Universitaet Berlin 2002-2013.
7
// This software is released under a three-clause BSD license:
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of any author or any participating institution
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
// For a full list of authors, refer to the file AUTHORS.
17
// --------------------------------------------------------------------------
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22
// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
// --------------------------------------------------------------------------
31
// $Maintainer: Stephan Aiche $
32
// $Authors: Stephan Aiche, Chris Bielow $
33
// --------------------------------------------------------------------------
35
#include <OpenMS/ANALYSIS/QUANTITATION/IsobaricNormalizer.h>
40
IsobaricNormalizer::IsobaricNormalizer(const IsobaricQuantitationMethod* const quant_method) :
41
quant_meth_(quant_method)
43
reference_channel_name_ = quant_meth_->getChannelInformation()[quant_meth_->getReferenceChannel()].name;
46
IsobaricNormalizer::IsobaricNormalizer(const IsobaricNormalizer& other) :
47
quant_meth_(other.quant_meth_),
48
reference_channel_name_(other.reference_channel_name_)
52
IsobaricNormalizer& IsobaricNormalizer::operator=(const IsobaricNormalizer& rhs)
57
quant_meth_ = rhs.quant_meth_;
58
reference_channel_name_ = rhs.reference_channel_name_;
63
ConsensusFeature::HandleSetType::iterator IsobaricNormalizer::findReferenceChannel_(ConsensusFeature& cf, const ConsensusMap& consensus_map) const
65
for (ConsensusFeature::HandleSetType::iterator it_elements = cf.begin();
66
it_elements != cf.end();
69
if ((Int) consensus_map.getFileDescriptions()[it_elements->getMapIndex()].getMetaValue("channel_name") == reference_channel_name_)
78
void IsobaricNormalizer::buildVectorIndex_(const ConsensusMap& consensus_map)
82
map_to_vec_index_.clear();
85
for (ConsensusMap::FileDescriptions::const_iterator file_it = consensus_map.getFileDescriptions().begin();
86
file_it != consensus_map.getFileDescriptions().end();
89
if ((Int) file_it->second.getMetaValue("channel_name") == reference_channel_name_)
91
ref_map_id_ = file_it->first;
93
map_to_vec_index_[file_it->first] = index;
98
void IsobaricNormalizer::collectRatios_(const ConsensusFeature& cf, const Peak2D::IntensityType& ref_intensity)
100
for (ConsensusFeature::HandleSetType::const_iterator it_elements = cf.begin();
101
it_elements != cf.end();
104
if (ref_intensity == 0) //avoid nan's and inf's
106
if (it_elements->getIntensity() == 0) // 0/0 will give 'nan'
108
//so leave it out completely (there is no information to be gained)
110
else // x/0 is 'inf' but std::sort() has problems with that
112
peptide_ratios_[map_to_vec_index_[it_elements->getMapIndex()]].push_back(std::numeric_limits<Peak2D::IntensityType>::max());
115
else // everything seems fine
117
peptide_ratios_[map_to_vec_index_[it_elements->getMapIndex()]].push_back(it_elements->getIntensity() / ref_intensity);
121
peptide_intensities_[map_to_vec_index_[it_elements->getMapIndex()]].push_back(it_elements->getIntensity());
126
void IsobaricNormalizer::computeNormalizationFactors_(std::vector<Peak2D::IntensityType>& normalization_factors)
128
// ensure that the ref_(ratios|intensities) are sorted
129
std::sort(peptide_ratios_[ref_map_id_].begin(), peptide_ratios_[ref_map_id_].end());
130
std::sort(peptide_intensities_[ref_map_id_].begin(), peptide_intensities_[ref_map_id_].end());
133
Peak2D::IntensityType max_deviation_from_control = 0;
135
// find MEDIAN of ratios for each channel (store as 0th element in sorted vector)
136
for (Map<Size, Size>::const_iterator it_map = map_to_vec_index_.begin(); it_map != map_to_vec_index_.end(); ++it_map)
138
// this is solely for readability reasons, the compiler should optimize this anyway
139
const Size vec_idx = it_map->second;
141
// sort vector (partial_sort might improve performance here)
142
std::sort(peptide_ratios_[vec_idx].begin(), peptide_ratios_[vec_idx].end());
144
// save median as first element
145
normalization_factors[vec_idx] = peptide_ratios_[vec_idx][peptide_ratios_[vec_idx].size() / 2];
147
// sort control (intensities)
148
std::sort(peptide_intensities_[vec_idx].begin(), peptide_intensities_[vec_idx].end());
150
// find MEDIAN of control-method (intensities) for each channel
151
peptide_intensities_[vec_idx][0] = peptide_intensities_[vec_idx][peptide_intensities_[vec_idx].size() / 2] /
152
peptide_intensities_[ref_map_id_][peptide_intensities_[ref_map_id_].size() / 2];
154
LOG_INFO << "IsobaricNormalizer: map-id " << (it_map->first) << " has factor " << (normalization_factors[vec_idx]) << " (control: " << (peptide_intensities_[vec_idx][0]) << ")" << std::endl;
156
Peak2D::IntensityType dev = (peptide_ratios_[vec_idx][0] - peptide_intensities_[vec_idx][0]) / normalization_factors[vec_idx];
157
if (fabs(max_deviation_from_control) < fabs(dev))
159
max_deviation_from_control = dev;
163
LOG_INFO << "IsobaricNormalizer: max ratio deviation of alternative method is " << (max_deviation_from_control * 100) << "%\n";
166
void IsobaricNormalizer::normalize(ConsensusMap& consensus_map)
168
// determine reference channel as vector index
169
buildVectorIndex_(consensus_map);
171
// build mapping of map_index to ratio_array_index
172
peptide_ratios_.resize(quant_meth_->getNumberOfChannels());
173
peptide_intensities_.resize(quant_meth_->getNumberOfChannels());
175
//build up ratios for each peptide of non-reference channels
176
ConsensusFeature::HandleSetType::iterator ref_it;
178
for (ConsensusMap::Iterator cm_it = consensus_map.begin(); cm_it != consensus_map.end(); ++cm_it)
180
// find reference index (this is inefficient to do every time,
181
// but the most robust against anyone who tries to change the internals of ConsensusFeature):
182
ref_it = findReferenceChannel_(*cm_it, consensus_map);
184
// reference channel not found in this ConsensusFeature
185
if (ref_it == cm_it->end())
187
LOG_WARN << "IsobaricNormalizer::normalize() WARNING: ConsensusFeature "
188
<< (cm_it - consensus_map.begin())
189
<< " does not have a reference channel! Skipping"
194
collectRatios_(*cm_it, ref_it->getIntensity());
195
} // ! collect ratios
197
// vector to store the channel wise normalization factors
198
std::vector<Peak2D::IntensityType> normalization_factors;
199
normalization_factors.resize(quant_meth_->getNumberOfChannels());
201
// compute the normalization factors based on the medians of the compute ratios
202
computeNormalizationFactors_(normalization_factors);
205
peptide_intensities_.clear();
206
peptide_ratios_.clear();
208
// adjust intensity ratios
209
for (size_t i = 0; i < consensus_map.size(); ++i)
211
// find reference index (this is inefficient to do every time,
212
// but the most robust against anyone who tries to change the
213
// internals of ConsensusFeature):
214
ref_it = findReferenceChannel_(consensus_map[i], consensus_map);
216
// reference channel not found in this ConsensusFeature
217
if (ref_it == consensus_map[i].end())
222
// now adjust the ratios
223
ConsensusFeature cf = consensus_map[i];
224
cf.clear(); // delete its handles
225
for (ConsensusFeature::HandleSetType::iterator it_elements = consensus_map[i].begin();
226
it_elements != consensus_map[i].end();
229
FeatureHandle hd = *it_elements;
230
if (it_elements == ref_it)
234
else // divide current intensity by normalization factor (which was stored at position 0)
236
hd.setIntensity(hd.getIntensity() / normalization_factors[map_to_vec_index_[it_elements->getMapIndex()]]);
240
// replace consensusFeature with updated intensity
241
consensus_map[i] = cf;