// TODO what about charge 2 isotopes, etc. if tolerance is low enough, we can check for them too void PeakList::calculateIsotopicLevels(mass_t tolerance, vector<float>& isotopicLevels) const { const mass_t isotopicTolerance = (tolerance<0.2 ? tolerance : 0.2); const int lastPeakIndex = numPeaks_-1; isotopicLevels.clear(); isotopicLevels.resize(numPeaks_,0); int i; for (i=0; i<lastPeakIndex; i++) { if (isotopicLevels[i]>0) continue; // look for +1 peak int idx1 = findPeakWithMaxIntensity(peaks_[i].mass + MASS_PROTON, isotopicTolerance); if (idx1<0) continue; const float oneOverIntensity = 1.0 / peaks_[i].intensity; float ratio1 = peaks_[idx1].intensity * oneOverIntensity; // ignore strong +1 if ( ratio1 > 3.0) continue; // examine ratios vector<float> expectedPeakRatios, observedPeakRatios, relativeRatios; vector<int> isotopicIndexs; observedPeakRatios.resize(6); observedPeakRatios[0]=1.0; observedPeakRatios[1]= ratio1; isotopicIndexs.resize(6); isotopicIndexs[0]=i; isotopicIndexs[1]=idx1; // peak index at +1 position // find additional peaks int j; for (j=2; j<=5; j++) { int idx = findPeakWithMaxIntensity(peaks_[i].mass + j*MASS_ISO, isotopicTolerance); if (idx<0) break; observedPeakRatios[j] = peaks_[idx].mass * oneOverIntensity; isotopicIndexs[j]=idx; } const int lastIsotopicPosition = j-1; // get expected iso ratios calc_expected_iso_ratios(peaks_[i].mass,expectedPeakRatios,j); // calc ratios between observed and expected relativeRatios.clear(); relativeRatios.resize(6,0); relativeRatios[0]=1.0; for (j=1; j<=lastIsotopicPosition; j++) if (expectedPeakRatios[j]>0) relativeRatios[j]=observedPeakRatios[j] / expectedPeakRatios[j]; float levelDiscount=1.0; // as we move farther from the monoisotopic peak, the rates down for (j=1; j<= lastIsotopicPosition; j++) { float isotopicLevel; if (relativeRatios[j]>= 0.75 && relativeRatios[j]<=1.333) { isotopicLevel=2.0; } else if (relativeRatios[j] >= 0.5 && relativeRatios[j] <=2.0) { isotopicLevel=1.3333; } else if (relativeRatios[j] >= 0.3333 && relativeRatios[j] <=3.0) { isotopicLevel=0.6666; } else if (relativeRatios[j] >= 0.25 && relativeRatios[j] <= 4.0) { isotopicLevel=0.3333; } else break; isotopicLevels[isotopicIndexs[j]] = isotopicLevels[isotopicIndexs[j-1]] + levelDiscount * isotopicLevel; levelDiscount *= 0.5; } } }
/************************************************************** Sets the iso_level for each peak. Iso level 0 means that there is no evidence that this peaks is an isotopic peak. The higher the level, the more this looks like an isotopic peak ***************************************************************/ void Spectrum::calc_isotope_levels() { int i; const mass_t iso_tolerance = (config_->getTolerance()<0.2) ? config_->getTolerance() : 0.2; const int last_peak_idx = numPeaks_-1; isotopicLevels_.clear(); isotopicLevels_.resize(numPeaks_,0); for (i=0; i<last_peak_idx; i++) { if (isotopicLevels_[i]>0) continue; // look for +1 peak int idx1 = findPeakWithMaxIntensity(peaks_[i].mass + MASS_PROTON, iso_tolerance); if (idx1<0) continue; float one_over_intensity = 1.0 / peaks_[i].intensity; float ratio1 = peaks_[idx1].intensity * one_over_intensity; // ignore strong +1 if ( ratio1 > 3) continue; // examine ratios vector<float> expected_ratios, observed_ratios, relative_ratios; vector<int> iso_idxs; observed_ratios.resize(6); observed_ratios[0]=1.0; observed_ratios[1]= ratio1; iso_idxs.resize(6); iso_idxs[0]=i; iso_idxs[1]=idx1; // find additional peaks int j; for (j=2; j<=5; j++) { int idx = findPeakWithMaxIntensity(peaks_[i].mass + j, iso_tolerance); if (idx<0) break; observed_ratios[j] = peaks_[idx].mass * one_over_intensity; iso_idxs[j]=idx; } int last_iso = j-1; // get expected iso ratios calc_expected_iso_ratios(peaks_[i].mass,expected_ratios,j); // calc ratios between observed and expected relative_ratios.resize(j); relative_ratios[0]=1; for (j=1; j<=last_iso; j++) relative_ratios[j]=observed_ratios[j] / expected_ratios[j]; float level_mul=1.0; for (j=1; j<= last_iso; j++) { float iso_level; if (relative_ratios[j]>= 0.75 && relative_ratios[j]<=1.333) { iso_level=2.0; } else if (relative_ratios[j] >= 0.5 && relative_ratios[j] <=2) { iso_level=1.3333; } else if (relative_ratios[j] >= 0.3333 && relative_ratios[j] <=3) { iso_level=0.6666; } else if (relative_ratios[j] >= 0.25 && relative_ratios[j] <= 4) { iso_level=0.3333; } else break; // if (relative_ratios[j] / relative_ratios[j-1] > 3) // break; isotopicLevels_[iso_idxs[j]] = isotopicLevels_[iso_idxs[j-1]] + level_mul * iso_level; // peaks[iso_idxs[j]].IsotopicLevel = peaks[iso_idxs[j-1]].IsotopicLevel + // level_mul * iso_level; level_mul *= 0.5; } } vector<rank_pair> mono_pairs, iso_pairs; for (i=0; i<numPeaks_; i++) { rank_pair p; p.idx=i; p.inten = peaks_[i].intensity; if (isotopicLevels_[i] <= 0) { mono_pairs.push_back(p); } else iso_pairs.push_back(p); } sort(mono_pairs.begin(),mono_pairs.end()); sort(iso_pairs.begin(),iso_pairs.end()); /* ranked_mono_peaks.resize(numPeaks_); for (i=0; i<mono_pairs.size(); i++) ranked_mono_peaks[i]=mono_pairs[i].idx; for (i=0; i<iso_pairs.size(); i++) ranked_mono_peaks[mono_pairs.size()+i]=iso_pairs[i].idx; */ }