Пример #1
0
        /// <summary>
        /// Computes the isotope distribution of the tracer
        /// </summary>
        private void ComputeMasses()
        {
            var res = Workspace.GetAminoAcidFormulas();

            if (!AminoAcidSymbol.HasValue)
            {
                // If the tracer is a single element, then its mass is just the normal mass
                // of the element plus the mass shift.
                TraceeMasses = res.GetMassDistribution(Molecule.Parse(TraceeSymbol), 0);
                double tracerMass = TraceeMasses.MostAbundanceMass + DeltaMass;
                TracerMasses = MassDistribution.NewInstance(new Dictionary <double, double> {
                    { tracerMass, 1.0 }
                }, 0, 0);
                return;
            }
            // If the tracer is an amino acid, get the masses of the amino acid, and
            // add in atoms with the correct mass shift.
            var heavyMasses = new Dictionary <double, double>();

            heavyMasses.Add(0, 1 - AtomPercentEnrichment / 100);
            heavyMasses.Add(DeltaMass / AtomCount, AtomPercentEnrichment / 100);
            const string tempName          = "Temp";
            var          isotopeAbundances = res.IsotopeAbundances.SetAbundances(
                tempName, MassDistribution.NewInstance(heavyMasses, 0, 0));

            res = res.SetIsotopeAbundances(isotopeAbundances);
            var formula       = Molecule.Parse(res.Formulas[AminoAcidSymbol.Value]);
            var tracerFormula = Molecule.Parse(formula + tempName + AtomCount);

            TraceeMasses = res.GetMassDistribution(formula, 0);
            TracerMasses = res.GetMassDistribution(tracerFormula, 0);
        }
Пример #2
0
        public MassDistribution GetPrecursorMassDistribution()
        {
            if (_precursorMassDistribution == null)
            {
                var fragmentedMoleculeSettings = FragmentedMolecule.Settings.FromSrmSettings(Settings);
                _precursorMassDistribution = fragmentedMoleculeSettings
                                             .GetMassDistribution(GetPrecursorFormula().Molecule, 0, 0);
            }

            return(_precursorMassDistribution);
        }
Пример #3
0
        /// <summary>
        /// Constructor for an IsotopeDistInfo using TransitionFullScanSettings
        /// </summary>
        public static IsotopeDistInfo MakeIsotopeDistInfo(MassDistribution mzDistribution, TypedMass monoisotopicMass, Adduct adduct, TransitionFullScan fullScan)
        {
            // Centering resolution must be inversely proportional to charge state
            // High charge states can bring major peaks close enough together to
            // cause them to be combined and centered in isotope distribution valleys
            double massResolution = TransitionFullScan.ISOTOPE_PEAK_CENTERING_RES /
                                    (1 + Math.Abs(adduct.AdductCharge / 15.0));

            return(new IsotopeDistInfo(mzDistribution, monoisotopicMass, adduct,
                                       fullScan.GetPrecursorFilterWindow,
                                       massResolution,
                                       TransitionFullScan.MIN_ISOTOPE_PEAK_ABUNDANCE));
        }
Пример #4
0
            public MassDistribution GetMassDistribution(Molecule molecule, double massShift, int charge)
            {
                var emptyMassDistribution = new MassDistribution(MassResolution, MinAbundance);
                var massDistribution      = emptyMassDistribution;

                foreach (var entry in molecule)
                {
                    massDistribution = massDistribution.Add(emptyMassDistribution.Add(IsotopeAbundances[entry.Key]).Multiply(entry.Value));
                }
                if (charge != 0 || massShift != 0)
                {
                    massDistribution = massDistribution.OffsetAndDivide(massShift - charge * BioMassCalc.MassElectron,
                                                                        Math.Max(1, Math.Abs(charge)));
                }
                return(massDistribution);
            }
Пример #5
0
        /// <summary>
        /// Synchronizes a single <see cref="MassDistribution"/> object with corresponding
        /// masses from a <see cref="BioMassCalc"/>.
        /// </summary>
        private static MassDistribution SynchDist(MassDistribution massDist,
                                                  double monoMassCalc, double secondMassCalc, double thirdMassCalc)
        {
            var massDistOrdered = massDist.MassesSortedByAbundance();

            if (EqualDistMasses(massDistOrdered, monoMassCalc, secondMassCalc, thirdMassCalc))
            {
                return(massDist);
            }
            var dictFixDist = new Dictionary <double, double>(massDist);

            ReplaceMass(dictFixDist, massDistOrdered, 0, monoMassCalc);
            ReplaceMass(dictFixDist, massDistOrdered, 1, secondMassCalc);
            ReplaceMass(dictFixDist, massDistOrdered, 2, thirdMassCalc);
            return(MassDistribution.NewInstance(dictFixDist, 0, 0));
        }
Пример #6
0
        private List <MzRange> GetMasses()
        {
            var massesAndFrequency      = new Dictionary <double, double>();
            var tracerFormulaEnumerator = new TracerFormulaEnumerator(Sequence, _tracerDefs.Values);

            while (tracerFormulaEnumerator.MoveNext())
            {
                MassDistribution massDistribution = _aminoAcidFormulas.GetMassDistribution(
                    MoleculeFromTracerFormula(tracerFormulaEnumerator.Current), 0);
                massDistribution = massDistribution.OffsetAndDivide(_aminoAcidFormulas.GetMassShift(Sequence), 1);
                foreach (var entry in massDistribution)
                {
                    if (entry.Value < MinAbundance)
                    {
                        continue;
                    }
                    double currentAbundance;
                    massesAndFrequency.TryGetValue(entry.Key, out currentAbundance);
                    if (currentAbundance >= entry.Value)
                    {
                        continue;
                    }
                    massesAndFrequency[entry.Key] = entry.Value;
                }
            }
            var allMasses = new List <double>(massesAndFrequency.Keys);

            allMasses.Sort();
            var result = new List <MzRange>();

            foreach (var mass in allMasses)
            {
                if (result.Count == 0)
                {
                    result.Add(new MzRange(mass));
                    continue;
                }
                var lastMass = result[result.Count - 1];
                if (lastMass.Distance(mass) > MassResolution)
                {
                    result.Add(new MzRange(mass));
                    continue;
                }
                result[result.Count - 1] = lastMass.Union(mass);
            }
            return(result);
        }
Пример #7
0
        public IsotopeDistInfo(MassDistribution massDistribution,
                               TypedMass monoisotopicMass,
                               Adduct adduct,
                               Func <double, double> calcFilterWindow,
                               double massResolution,
                               double minimumAbundance)
        {
            _monoisotopicMass = monoisotopicMass;
            _adduct           = adduct.Unlabeled; // Don't reapply explicit isotope labels

            // Get peak center of mass values for the given resolution
            var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList();
            // Find the monoisotopic m/z and make sure it is exactly the expected number
            double monoMz        = _adduct.MzFromNeutralMass(_monoisotopicMass);
            double monoMzDist    = monoMz;
            int    monoMassIndex = 0;

            for (int i = 0; i < q1FilterValues.Count; i++)
            {
                double peakCenterMz = q1FilterValues[i];
                double filterWindow = calcFilterWindow(peakCenterMz);
                double startMz      = peakCenterMz - filterWindow / 2;
                double endMz        = startMz + filterWindow;
                if (startMz < monoMz && monoMz < endMz)
                {
                    monoMzDist        = q1FilterValues[i];
                    q1FilterValues[i] = monoMz;
                    monoMassIndex     = i;
                    break;
                }
            }
            // Insert a M-1 peak, even if it is not expected in the isotope mass distribution
            if (monoMassIndex == 0 && q1FilterValues.Count > 1)
            {
                // Use the delta from the original distribution monoMz to the next peak
                q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]);
                monoMassIndex++;
            }

            if (!q1FilterValues.Any())
            {
                // This should never happen, but just in case it does happen, we safely exit the constructor
                ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f));
                MonoMassIndex = BaseMassIndex = 0;
                return;
            }

            var signedQ1FilterValues = q1FilterValues.Select(q => new SignedMz(q, adduct.AdductCharge < 0)).ToList();

            // Use the filtering algorithm that will be used on real data to determine the
            // expected proportions of the mass distribution that will end up filtered into
            // peaks
            // CONSIDER: Mass accuracy information is not calculated here
            var key    = new PrecursorTextId(signedQ1FilterValues[monoMassIndex], null, null, ChromExtractor.summed);
            var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, false, false);

            filter.AddQ1FilterValues(signedQ1FilterValues, calcFilterWindow);

            var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum
                                                                       {
                                                                           Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray(), NegativeCharge = (adduct.AdductCharge < 0)
                                                                       } });

            int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance);

            if (startIndex == -1)
            {
                // This can happen if the amino acid modifications are messed up,
                // and the peptide mass is negative or something.
                ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f));
                MonoMassIndex = BaseMassIndex = 0;
                return;
            }
            // Always include the M-1 peak, even if it is expected to have zero intensity
            if (startIndex > monoMassIndex - 1)
            {
                startIndex = monoMassIndex - 1;
            }
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            int endIndex              = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1;
            int countPeaks            = endIndex - startIndex;
            var listProportionIndices = new List <KeyValuePair <float, int> >(countPeaks);

            for (int i = 0; i < countPeaks; i++)
            {
                listProportionIndices.Add(new KeyValuePair <float, int>(
                                              expectedSpectrum.Intensities[i + startIndex], i));
            }
            // Sort proportions descending.
            listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key));

            // Set proportions and ranks back in the original locations
            var expectedProportionRanks = new KeyValuePair <float, int> [countPeaks];

            for (int i = 0; i < countPeaks; i++)
            {
                expectedProportionRanks[listProportionIndices[i].Value] =
                    new KeyValuePair <float, int>(listProportionIndices[i].Key, i + 1);
            }

            MonoMassIndex = monoMassIndex - startIndex;

            // Find the base peak and fill in the masses and proportions
            var expectedPeaks = new List <MzRankProportion>();

            for (int i = 0; i < countPeaks; i++)
            {
                float expectedProportion = expectedProportionRanks[i].Key;
                int   rank = expectedProportionRanks[i].Value;
                expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion));
                if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key)
                {
                    BaseMassIndex = i;
                }
            }
            ExpectedPeaks = expectedPeaks;
        }
Пример #8
0
        public IsotopeDistInfo(MassDistribution massDistribution,
                               double monoisotopicMass,
                               bool isMassH, // Is monoisotopicMass M+H, or just M as in small molecule use?
                               int charge,
                               Func <double, double> calcFilterWindow,
                               double massResolution,
                               double minimumAbundance)
        {
            _monoisotopicMass = monoisotopicMass;
            _charge           = charge;
            _isMassH          = isMassH;

            // Get peak center of mass values for the given resolution
            var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList();
            // Find the monoisotopic m/z and make sure it is exactly the expected number
            double monoMz        = isMassH ? SequenceMassCalc.GetMZ(_monoisotopicMass, _charge) : BioMassCalc.CalculateIonMz(_monoisotopicMass, _charge);
            double monoMzDist    = monoMz;
            int    monoMassIndex = 0;

            for (int i = 0; i < q1FilterValues.Count; i++)
            {
                double peakCenterMz = q1FilterValues[i];
                double filterWindow = calcFilterWindow(peakCenterMz);
                double startMz      = peakCenterMz - filterWindow / 2;
                double endMz        = startMz + filterWindow;
                if (startMz < monoMz && monoMz < endMz)
                {
                    monoMzDist        = q1FilterValues[i];
                    q1FilterValues[i] = monoMz;
                    monoMassIndex     = i;
                    break;
                }
            }
            // Insert a M-1 peak, even if it is not expected in the isotope mass distribution
            if (monoMassIndex == 0 && q1FilterValues.Count > 1)
            {
                // Use the delta from the original distribution monoMz to the next peak
                q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]);
                monoMassIndex++;
            }

            if (!q1FilterValues.Any())  // As is small molecule docs with mz values only, no formulas
            {
                return;
            }

            // Use the filtering algorithm that will be used on real data to determine the
            // expected proportions of the mass distribution that will end up filtered into
            // peaks
            // CONSIDER: Mass accuracy information is not calculated here
            var key    = new PrecursorTextId(q1FilterValues[monoMassIndex], null, ChromExtractor.summed);
            var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, null, null, 0, false, false);

            filter.AddQ1FilterValues(q1FilterValues, calcFilterWindow);

            var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum
                                                                       {
                                                                           Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray()
                                                                       } });

            int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance);

            if (startIndex == -1)
            {
                throw new InvalidOperationException(
                          string.Format(Resources.IsotopeDistInfo_IsotopeDistInfo_Minimum_abundance__0__too_high,
                                        minimumAbundance));
            }
            // Always include the M-1 peak, even if it is expected to have zero intensity
            if (startIndex > monoMassIndex - 1)
            {
                startIndex = monoMassIndex - 1;
            }
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            int endIndex              = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1;
            int countPeaks            = endIndex - startIndex;
            var listProportionIndices = new List <KeyValuePair <float, int> >(countPeaks);

            for (int i = 0; i < countPeaks; i++)
            {
                listProportionIndices.Add(new KeyValuePair <float, int>(
                                              expectedSpectrum.Intensities[i + startIndex], i));
            }
            // Sort proportions descending.
            listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key));

            // Set proportions and ranks back in the original locations
            var expectedProportionRanks = new KeyValuePair <float, int> [countPeaks];

            for (int i = 0; i < countPeaks; i++)
            {
                expectedProportionRanks[listProportionIndices[i].Value] =
                    new KeyValuePair <float, int>(listProportionIndices[i].Key, i + 1);
            }

            // TODO: Can this be discarded?
            // MassDistribution = massDistribution;

            MonoMassIndex = monoMassIndex - startIndex;

            // Find the base peak and fill in the masses and proportions
            var expectedPeaks = new List <MzRankProportion>();

            for (int i = 0; i < countPeaks; i++)
            {
                float expectedProportion = expectedProportionRanks[i].Key;
                int   rank = expectedProportionRanks[i].Value;
                expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion));
                if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key)
                {
                    BaseMassIndex = i;
                }
            }
            ExpectedPeaks = expectedPeaks;
        }
Пример #9
0
 /// <summary>
 /// Synchronizes a single <see cref="MassDistribution"/> object with corresponding
 /// masses from a <see cref="BioMassCalc"/>.
 /// </summary>
 private static MassDistribution SynchDist(MassDistribution massDist,
     double monoMassCalc, double secondMassCalc, double thirdMassCalc)
 {
     var massDistOrdered = massDist.MassesSortedByAbundance();
     if (EqualDistMasses(massDistOrdered, monoMassCalc, secondMassCalc, thirdMassCalc))
         return massDist;
     var dictFixDist = new Dictionary<double, double>(massDist);
     ReplaceMass(dictFixDist, massDistOrdered, 0, monoMassCalc);
     ReplaceMass(dictFixDist, massDistOrdered, 1, secondMassCalc);
     ReplaceMass(dictFixDist, massDistOrdered, 2, thirdMassCalc);
     return MassDistribution.NewInstance(dictFixDist, 0, 0);
 }
Пример #10
0
// ReSharper disable once ParameterTypeCanBeEnumerable.Local
        private MassDistribution GetMzDistribution(Molecule molecule, int charge, IsotopeAbundances abundances, double unexplainedMass, bool isMassH)
        {
            // Low resolution to get back only peaks at Dalton (i.e. neutron) boundaries
            var md = new MassDistribution(_massResolution, _minimumAbundance);
            var result = md;
            foreach (var element in molecule)
            {
                result = result.Add(md.Add(abundances[element.Key]).Multiply(element.Value));
            }
            return result.OffsetAndDivide(unexplainedMass + charge* (isMassH ? BioMassCalc.MassProton : -BioMassCalc.MassElectron), charge);
        }
Пример #11
0
 public MassDistribution GetMassDistribution(Molecule molecule, int charge)
 {
     var md = new MassDistribution(MassResolution, .00001);
     var result = md;
     foreach (var element in molecule)
     {
         result = result.Add(md.Add(IsotopeAbundances[element.Key]).Multiply(element.Value));
     }
     if (charge != 0)
     {
         result = result.OffsetAndDivide(charge * ProtonMass, charge);
     }
     return result;
 }
Пример #12
0
        public IsotopeDistInfo(MassDistribution massDistribution,
            double monoisotopicMass,
            bool isMassH, // Is monoisotopicMass M+H, or just M as in small molecule use?
            int charge,
            Func<double, double> calcFilterWindow,
            double massResolution,
            double minimumAbundance)
        {
            _monoisotopicMass = monoisotopicMass;
            _charge = charge;
            _isMassH = isMassH;

            // Get peak center of mass values for the given resolution
            var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList();
            // Find the monoisotopic m/z and make sure it is exactly the expected number
            double monoMz = isMassH ? SequenceMassCalc.GetMZ(_monoisotopicMass, _charge) : BioMassCalc.CalculateIonMz(_monoisotopicMass, _charge);
            double monoMzDist = monoMz;
            int monoMassIndex = 0;
            for (int i = 0; i < q1FilterValues.Count; i++)
            {
                double peakCenterMz = q1FilterValues[i];
                double filterWindow = calcFilterWindow(peakCenterMz);
                double startMz = peakCenterMz - filterWindow/2;
                double endMz = startMz + filterWindow;
                if (startMz < monoMz && monoMz < endMz)
                {
                    monoMzDist = q1FilterValues[i];
                    q1FilterValues[i] = monoMz;
                    monoMassIndex = i;
                    break;
                }
            }
            // Insert a M-1 peak, even if it is not expected in the isotope mass distribution
            if (monoMassIndex == 0 && q1FilterValues.Count > 1)
            {
                // Use the delta from the original distribution monoMz to the next peak
                q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]);
                monoMassIndex++;
            }

            if (!q1FilterValues.Any())  // As is small molecule docs with mz values only, no formulas
                return;

            // Use the filtering algorithm that will be used on real data to determine the
            // expected proportions of the mass distribution that will end up filtered into
            // peaks
            // CONSIDER: Mass accuracy information is not calculated here
            var key = new PrecursorTextId(q1FilterValues[monoMassIndex], null, ChromExtractor.summed);
            var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, null, null, 0, false, false);
            filter.AddQ1FilterValues(q1FilterValues, calcFilterWindow);

            var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum
            { Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray() } });

            int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance);
            if (startIndex == -1)
            {
                throw new InvalidOperationException(
                    string.Format(Resources.IsotopeDistInfo_IsotopeDistInfo_Minimum_abundance__0__too_high,
                                  minimumAbundance));
            }
            // Always include the M-1 peak, even if it is expected to have zero intensity
            if (startIndex > monoMassIndex - 1)
                startIndex = monoMassIndex - 1;
            if (startIndex < 0)
                startIndex = 0;
            int endIndex = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1;
            int countPeaks = endIndex - startIndex;
            var listProportionIndices = new List<KeyValuePair<float, int>>(countPeaks);
            for (int i = 0; i < countPeaks; i++)
            {
                listProportionIndices.Add(new KeyValuePair<float, int>(
                    expectedSpectrum.Intensities[i + startIndex], i));
            }
            // Sort proportions descending.
            listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key));

            // Set proportions and ranks back in the original locations
            var expectedProportionRanks = new KeyValuePair<float, int>[countPeaks];
            for (int i = 0; i < countPeaks; i++)
            {
                expectedProportionRanks[listProportionIndices[i].Value] =
                    new KeyValuePair<float, int>(listProportionIndices[i].Key, i + 1);
            }

            // TODO: Can this be discarded?
            // MassDistribution = massDistribution;

            MonoMassIndex = monoMassIndex - startIndex;

            // Find the base peak and fill in the masses and proportions
            var expectedPeaks = new List<MzRankProportion>();
            for (int i = 0; i < countPeaks; i++)
            {
                float expectedProportion = expectedProportionRanks[i].Key;
                int rank = expectedProportionRanks[i].Value;
                expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion));
                if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key)
                    BaseMassIndex = i;
            }
            ExpectedPeaks = expectedPeaks;
        }