Beispiel #1
0
        // Unit test of annotations handler class
        private static void TestSpectrumPeakAnnotations()
        {
            var noNote      = SpectrumPeakAnnotation.Create(new CustomIon(null, Adduct.FromChargeNoMass(-2), 100, 101, "noNote"), null);
            var noName      = SpectrumPeakAnnotation.Create(new CustomIon(null, Adduct.FromChargeNoMass(-2), 100, 101, null), "noted");
            var fullIon     = new CustomIon("C12H5O3", Adduct.FromStringAssumeChargeOnly("M-H2O+"), null, null, "full");
            var full        = SpectrumPeakAnnotation.Create(fullIon, "noted");
            var fullToo     = SpectrumPeakAnnotation.Create(fullIon, "noted");
            var nameOnlyTab = SpectrumPeakAnnotation.Create(new CustomIon(null, Adduct.FromChargeNoMass(-2), 100, 101, "test\ttabs"), "noted"); // Check tab escape
            var fullIonTabs = new CustomIon("C12H5", Adduct.FromChargeNoMass(-2), null, null, "full\ttabs");
            var tabbedFull  = SpectrumPeakAnnotation.Create(fullIonTabs, "noted\ttabs");                                                        // Check tab escape

            Assume.AreEqual(full, fullToo);
            Assume.AreNotEqual(full, tabbedFull);
            var tests = new List <List <SpectrumPeakAnnotation> >
            {
                new List <SpectrumPeakAnnotation> {
                    noNote, noName, full
                },
                new List <SpectrumPeakAnnotation> {
                    fullToo, nameOnlyTab, tabbedFull
                }
            };
            var cached    = SpectrumPeakAnnotation.ToCacheFormat(tests);
            var roundtrip = SpectrumPeakAnnotation.FromCacheFormat(cached);
            int i         = 0;

            foreach (var annotsPerPeak in tests)
            {
                Assume.IsTrue(CollectionUtil.EqualsDeep(annotsPerPeak, roundtrip[i++]));
            }
        }
Beispiel #2
0
        protected override void DoTest()
        {
            TestSmallMolecules = false;  // Don't need the magic test node

            var testFilesDir = TestFilesDir;

            // Verify our use of explict RT where multiple nodes and multiple chromatograms all have same Q1>Q3
            // This data set has three chromatograms with Q1=150 Q3=150 (one in negative ion mode), and
            // three transition nodes with that Q1>Q3 but different RTs (one with neg charge)
            // Expected alignment:
            // function 65/ index 242 : RT 6.95 glutamate
            // function 66/ index 243 : RT 7.95 glutamine (peak found at 8.1)
            // function 197/ index 117 (neg ion mode): RT 6.4 alpha_ketogluterate
            DoSubTest(testFilesDir, "glutes.sky", new[] { 6.95, 8.1, 6.4 }, new[] { "090215_033" }, null,
                      new[] { Adduct.M_PLUS_H, Adduct.M_PLUS_H, Adduct.M_MINUS_H });

            // Verify our handling of two Q1>Q3 transitions with no RT overlap - formerly we just ignored one or the other though both are needed
            // As in https://skyline.gs.washington.edu/labkey/announcements/home/support/thread.view?entityId=924e3c51-7c00-1033-9ff1-da202582a252&_anchor=24723
            DoSubTest(testFilesDir, "lysine.sky", new[] { 13.8, 13.8, 13.8, 13.8 }, new[] { "ESvKprosp_20151120_035", "ESvKprosp_20151120_036" }, .5,
                      new[] { Adduct.M_PLUS_H, Adduct.FromStringAssumeChargeOnly("[M6C132N15+H]") });

            // Verify our use of explict RT in peak picking where the correct peak isn't the largest
            // As in https://skyline.gs.washington.edu/labkey/announcements/home/support/thread.view?entityId=273ccc30-8258-1033-9ff1-da202582a252&_anchor=24774
            DoSubTest(testFilesDir, "test_b.sky", new[] { 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1 }, new[] { "120315_120", "120315_121", "120315_125", "120315_126" }, null,
                      new[] { Adduct.M_PLUS_H, Adduct.M_PLUS_H });
        }
Beispiel #3
0
        public override void ReadXml(XmlReader reader)
        {
            // Read tag attributes
            base.ReadXml(reader);
            Fragment = reader.GetAttribute(ATTR.cut);
            if (IsFragment)
            {
                Restrict          = reader.GetAttribute(ATTR.no_cut);
                Terminus          = reader.GetAttribute(ATTR.sense, ToSeqTerminus);
                MinFragmentLength = reader.GetNullableIntAttribute(ATTR.min_length) ??
                                    DEFAULT_MIN_FRAGMENT_LENGTH;
            }
            else
            {
                var charges = TextUtil.ParseInts(reader.GetAttribute(ATTR.charges)); // Old version?
                if (charges.Length > 1)
                {
                    throw new InvalidDataException(Resources.MeasuredIon_ReadXml_Multiple_charge_states_for_custom_ions_are_no_longer_supported_);
                }
                var    parsedIon = CustomIon.Deserialize(reader);
                Adduct adduct;
                if (charges.Any())  // Old style - fix it up a little for our revised ideas about custom ion ionization
                {
                    adduct = Adduct.FromChargeNoMass(charges[0]);
                    if (string.IsNullOrEmpty(parsedIon.NeutralFormula)) // Adjust the user-supplied masses
                    {
                        SettingsCustomIon = new SettingsCustomIon(parsedIon.NeutralFormula, adduct,
                                                                  Math.Round(parsedIon.MonoisotopicMass + charges[0] * BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.H), SequenceMassCalc.MassPrecision), // Assume user provided neutral mass.  Round new value easiest XML roundtripping.
                                                                  Math.Round(parsedIon.AverageMass + charges[0] * BioMassCalc.AVERAGE.GetMass(BioMassCalc.H), SequenceMassCalc.MassPrecision),           // Assume user provided neutral mass.  Round new value easiest XML roundtripping.
                                                                  parsedIon.Name);
                    }
                    else // Adjust the formula to include ion atoms
                    {
                        if (charges[0] > 1) // XML deserializer will have added an H already
                        {
                            var adductProtonated = Adduct.FromChargeProtonated(charges[0] - 1);
                            var formula          = adductProtonated.ApplyToFormula(parsedIon.NeutralFormula);
                            parsedIon = new CustomIon(formula, adduct, parsedIon.MonoisotopicMass, parsedIon.AverageMass, Name);
                        }
                    }
                }
                else
                {
                    adduct = Adduct.FromStringAssumeChargeOnly(reader.GetAttribute(ATTR.charge)); // Ionization mass is already in formula
                }
                if (SettingsCustomIon == null)
                {
                    SettingsCustomIon = new SettingsCustomIon(parsedIon.NeutralFormula, adduct,
                                                              parsedIon.MonoisotopicMass,
                                                              parsedIon.AverageMass,
                                                              parsedIon.Name);
                }
                IsOptional = reader.GetBoolAttribute(ATTR.optional);
            }
            // Consume tag
            reader.Read();

            Validate();
        }
Beispiel #4
0
        public new static CustomIon FromTSV(string val)
        {
            var lastTab = val.LastIndexOf(TextUtil.SEPARATOR_TSV_STR, StringComparison.Ordinal);
            var adduct  = Adduct.FromStringAssumeChargeOnly(val.Substring(lastTab + 1));
            var mol     = CustomMolecule.FromTSV(val.Substring(0, lastTab));

            if (adduct.IsEmpty && mol.IsEmpty)
            {
                return(EMPTY);
            }
            return(new CustomIon(mol, adduct));
        }
Beispiel #5
0
        private static void VerifySharedDocLibraryAnnotations(string shareDocPath)
        {
            RunUI(() => SkylineWindow.OpenSharedFile(shareDocPath));
            var doc = WaitForDocumentLoaded();

            AssertEx.IsDocumentState(doc, null, 1, 4, 4, 4); // int revision, int groups, int peptides, int tranGroups, int transitions
            SpectrumPeaksInfo spectrum;
            IsotopeLabelType  label;

            // ReSharper disable PossibleNullReferenceException
            doc.Settings.TryLoadSpectrum(doc.Molecules.FirstOrDefault().Target, Adduct.FromStringAssumeChargeOnly("M+NH4"),
                                         null, out label, out spectrum);
            Assume.IsTrue(spectrum.Annotations.Count() == 1);
            var spectrumPeakAnnotations = (spectrum.Annotations.FirstOrDefault() ?? new SpectrumPeakAnnotation[0]).ToArray();

            Assume.IsTrue(spectrumPeakAnnotations.Length == 1);
            Assume.IsTrue(spectrumPeakAnnotations.FirstOrDefault().Ion.Name == "GP");
            // ReSharper restore PossibleNullReferenceException
        }
Beispiel #6
0
        private void TestAdductOperators()
        {
            // Test some underlying formula handling for fanciful user-supplied values
            Assert.IsTrue(Molecule.AreEquivalentFormulas("C10H30Si5O5H-CH4", "C9H27O5Si5"));
            Assert.AreEqual("C7H27O5Si4", BioMassCalc.MONOISOTOPIC.FindFormulaIntersection(new[] { "C8H30Si5O5H-CH4", "C9H27O5Si4", "C9H27O5Si5Na" }));
            Assert.AreEqual("C7H27O5Si4", BioMassCalc.MONOISOTOPIC.FindFormulaIntersectionUnlabeled(new[] { "C7C'H30Si5O5H-CH4", "C9H27O5Si4", "C9H25H'2O5Si5Na" }));

            // There is a difference between a proteomic adduct and non proteomic, primarily in how they display
            Assert.AreEqual(Adduct.FromStringAssumeChargeOnly("M+H"), Adduct.M_PLUS_H);
            Assert.AreEqual(Adduct.FromStringAssumeProtonatedNonProteomic("1"), Adduct.M_PLUS_H);
            Assert.AreEqual(Adduct.FromStringAssumeChargeOnly("1"), Adduct.M_PLUS);
            Assert.AreEqual(Adduct.FromStringAssumeProtonatedNonProteomic("M+H"), Adduct.M_PLUS_H);
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("1"), Adduct.SINGLY_PROTONATED);
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+H"), Adduct.SINGLY_PROTONATED);
            Assert.AreEqual(Adduct.FromStringAssumeChargeOnly("M+H").AsFormula(), Adduct.SINGLY_PROTONATED.AsFormula()); // But the underlying chemistry is the same

            Assert.AreEqual(Adduct.FromStringAssumeProtonated("[M+S]+"), Adduct.FromStringAssumeProtonated("M+S").ChangeCharge(1));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M(-1.234)+2Na"), Adduct.FromStringAssumeProtonated("M(-1.234)+3Na").ChangeCharge(2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M1.234+2Na"), Adduct.FromStringAssumeProtonated("M1.234+3Na").ChangeCharge(2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M2Cl37-2Na"), Adduct.FromStringAssumeProtonated("M2Cl37+3Na").ChangeCharge(-2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M1.234-2Na"), Adduct.FromStringAssumeProtonated("M1.234+3Na").ChangeCharge(-2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M(-1.234)-2Na"), Adduct.FromStringAssumeProtonated("M(-1.234)+3Na").ChangeCharge(-2));

            Assert.IsFalse(Adduct.M_PLUS_H.IsProteomic);
            Assert.IsTrue(Adduct.M_PLUS_H.IsProtonated);
            Assert.IsTrue(Adduct.SINGLY_PROTONATED.IsProteomic);
            Assert.IsTrue(Adduct.SINGLY_PROTONATED.IsProtonated);
            Assert.IsFalse(Adduct.SINGLY_PROTONATED.IsEmpty);
            Assert.IsFalse(Adduct.EMPTY.IsProteomic);
            Assert.IsTrue(Adduct.EMPTY.IsEmpty);

            // Exercise the ability to work with masses and isotope labels
            Assert.IsTrue(ReferenceEquals(Adduct.SINGLY_PROTONATED, Adduct.SINGLY_PROTONATED.Unlabeled));
            var nolabel = Adduct.FromStringAssumeProtonated("M-2Na");
            var label   = Adduct.FromStringAssumeProtonated("M2Cl37-2Na");

            Assert.AreEqual(nolabel, label.Unlabeled);
            Assert.IsTrue(ReferenceEquals(nolabel, nolabel.Unlabeled));
            Assert.IsFalse(nolabel.MassFromMz(300.0, MassType.Monoisotopic).IsHeavy());
            Assert.IsFalse(label.MassFromMz(300.0, MassType.Monoisotopic).IsHeavy());
            Assert.IsTrue(label.MassFromMz(300.0, MassType.MonoisotopicHeavy).IsHeavy());
            Assert.IsTrue(label.MassFromMz(300.0, MassType.Monoisotopic).IsMonoIsotopic());
            Assert.IsFalse(nolabel.MassFromMz(300.0, MassType.Average).IsHeavy());
            Assert.IsFalse(label.MassFromMz(300.0, MassType.Average).IsHeavy());
            Assert.IsTrue(label.MassFromMz(300.0, MassType.AverageHeavy).IsHeavy());
            Assert.IsTrue(label.MassFromMz(300.0, MassType.Average).IsAverage());
            var massHeavy = label.ApplyToMass(new TypedMass(300, MassType.MonoisotopicHeavy)); // Will not have isotope effect added in mz calc, as it's already heavy
            var massLight = label.ApplyToMass(new TypedMass(300, MassType.Monoisotopic));      // Will have isotope effect added in mz calc

            Assert.AreNotEqual(massHeavy, massLight);
            Assert.AreNotEqual(label.MzFromNeutralMass(massHeavy), label.MzFromNeutralMass(massLight));

            Assert.IsTrue(Adduct.PossibleAdductDescriptionStart("["));
            Assert.IsTrue(Adduct.PossibleAdductDescriptionStart("M"));
            Assert.IsTrue(Adduct.PossibleAdductDescriptionStart("[2M+CH3COO]"));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+2CH3COO"), Adduct.FromStringAssumeProtonated("M+CH3COO").ChangeCharge(-2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M-2CH3COO"), Adduct.FromStringAssumeProtonated("M+CH3COO").ChangeCharge(2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M-2Na"), Adduct.FromStringAssumeProtonated("M+Na").ChangeCharge(-2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+Na"), Adduct.FromStringAssumeProtonated("M+Na").ChangeCharge(1));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+2Na"), Adduct.FromStringAssumeProtonated("M+Na").ChangeCharge(2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+2Na"), Adduct.FromStringAssumeProtonated("M+3Na").ChangeCharge(2));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M2Cl37+2Na"), Adduct.FromStringAssumeProtonated("M2Cl37+3Na").ChangeCharge(2));
            AssertEx.ThrowsException <InvalidOperationException>(() => Adduct.FromStringAssumeProtonated("M+2Na-H").ChangeCharge(2)); // Too complex to adjust formula

            AssertEx.ThrowsException <InvalidOperationException>(() => Adduct.FromStringAssumeProtonatedNonProteomic("[M2"));         // Seen in the wild, wasn't handled well

            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M++++").AdductCharge, Adduct.FromChargeNoMass(4).AdductCharge);
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M+4"), Adduct.FromChargeNoMass(4));
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M--").AdductCharge, Adduct.FromChargeNoMass(-2).AdductCharge);
            Assert.AreEqual(Adduct.FromStringAssumeProtonated("M-2"), Adduct.FromChargeNoMass(-2));
            Assert.IsTrue(ReferenceEquals(Adduct.FromStringAssumeChargeOnly("M-"), Adduct.FromChargeNoMass(-1)));  // Both should return Adduct.M_MINUS
            Assert.IsTrue(ReferenceEquals(Adduct.FromStringAssumeChargeOnly("M+"), Adduct.FromChargeNoMass(1)));   // Both should return Adduct.M_PLUS
            Assert.IsTrue(ReferenceEquals(Adduct.FromStringAssumeChargeOnly("[M+]"), Adduct.FromChargeNoMass(1))); // Both should return Adduct.M_PLUS
            Assert.IsTrue(ReferenceEquals(Adduct.FromStringAssumeChargeOnly("M-H"), Adduct.M_MINUS_H));
            Assert.IsTrue(ReferenceEquals(Adduct.FromStringAssumeChargeOnly("M+H"), Adduct.M_PLUS_H));

            var a    = Adduct.FromChargeProtonated(-1);
            var aa   = Adduct.FromStringAssumeProtonated("M+CH3COO");
            var b    = Adduct.FromChargeProtonated(2);
            var bb   = Adduct.FromChargeProtonated(2);
            var bbb  = Adduct.FromChargeProtonated(2);
            var bbbb = Adduct.FromChargeProtonated(2);
            var c    = Adduct.FromChargeProtonated(3);
            var cc   = Adduct.FromStringAssumeChargeOnly("M+3H");
            var ccc  = Adduct.FromStringAssumeChargeOnly("[M+3H]");

            Assert.AreEqual(a.AdductCharge, aa.AdductCharge);
            Assert.IsTrue(b == bb);
            Assert.IsTrue(b == bbb);
            Assert.IsTrue(ReferenceEquals(bbb, bbbb));
            Assert.IsTrue(c.AdductCharge == cc.AdductCharge);
            Assert.IsFalse(c == cc);
            Assert.IsTrue(c != cc);
            Assert.IsTrue(cc == ccc);
            Assert.IsTrue(a < aa);
            Assert.IsTrue(a < b);
            Assert.IsTrue(b > a);
            Assert.IsTrue(b != a);

            var sorted = new List <Adduct> {
                a, aa, b, bb, bbb, bbbb, c, cc, ccc
            };
            var unsorted = new List <Adduct> {
                bb, aa, ccc, b, c, bbb, a, bbbb, cc
            };

            Assert.IsFalse(sorted.SequenceEqual(unsorted));
            unsorted.Sort();
            Assert.IsTrue(sorted.SequenceEqual(unsorted));

            var ints = new AdductMap <int>();

            Assert.AreEqual(0, ints[a]);
            ints[a] = 7;
            Assert.AreEqual(7, ints[a]);

            var adducts = new AdductMap <Adduct>();

            Assert.AreEqual(null, adducts[a]);
            adducts[a] = b;
            Assert.AreEqual(b, adducts[a]);
            adducts[a] = c;
            Assert.AreEqual(c, adducts[a]);

            var d   = Adduct.FromStringAssumeProtonated("[2M+3H]");
            var dd  = Adduct.FromStringAssumeProtonated("[M+3H]");
            var ddd = Adduct.FromStringAssumeProtonated("[M-Na]");

            Assert.IsTrue(d.ChangeMassMultiplier(1).SameEffect(dd));
            Assert.IsTrue(dd.ChangeMassMultiplier(2).SameEffect(d));
            Assert.AreEqual(dd.ChangeIonFormula("-Na"), ddd);
            Assert.AreEqual(d.ChangeMassMultiplier(1).ChangeIonFormula("-Na"), ddd);

            CheckLabel(BioMassCalc.Cl37);
            CheckLabel(BioMassCalc.Br81);
            CheckLabel(BioMassCalc.S33);
            CheckLabel(BioMassCalc.S34);
            CheckLabel(BioMassCalc.P32);
            CheckLabel(BioMassCalc.C14);
            CheckLabel(BioMassCalc.O17);
            CheckLabel(BioMassCalc.O18);

            var tips = Adduct.Tips;

            foreach (var nickname in Adduct.DICT_ADDUCT_NICKNAMES)
            {
                Assert.IsTrue(tips.Contains(nickname.Key));
            }
            foreach (var nickname in Adduct.DICT_ADDUCT_ISOTOPE_NICKNAMES)
            {
                Assert.IsTrue(tips.Contains(nickname.Key));
            }
        }
Beispiel #7
0
        public static TransitionDocNode FromTransitionProto(AnnotationScrubber scrubber, SrmSettings settings,
                                                            TransitionGroup group, ExplicitMods mods, IsotopeDistInfo isotopeDist, ExplicitTransitionValues pre422ExplicitTransitionValues,
                                                            SkylineDocumentProto.Types.Transition transitionProto)
        {
            var         stringPool  = scrubber.StringPool;
            IonType     ionType     = DataValues.FromIonType(transitionProto.FragmentType);
            MeasuredIon measuredIon = null;

            if (transitionProto.MeasuredIonName != null)
            {
                measuredIon = settings.TransitionSettings.Filter.MeasuredIons.SingleOrDefault(
                    i => i.Name.Equals(transitionProto.MeasuredIonName.Value));
                if (measuredIon == null)
                {
                    throw new InvalidDataException(string.Format(Resources.TransitionInfo_ReadXmlAttributes_The_reporter_ion__0__was_not_found_in_the_transition_filter_settings_, transitionProto.MeasuredIonName));
                }
                ionType = IonType.custom;
            }
            bool           isCustom    = Transition.IsCustom(ionType, group);
            bool           isPrecursor = Transition.IsPrecursor(ionType);
            CustomMolecule customIon   = null;

            if (isCustom)
            {
                if (measuredIon != null)
                {
                    customIon = measuredIon.SettingsCustomIon;
                }
                else if (isPrecursor)
                {
                    customIon = group.CustomMolecule;
                }
                else
                {
                    var formula      = DataValues.FromOptional(transitionProto.Formula);
                    var moleculeID   = MoleculeAccessionNumbers.FromString(DataValues.FromOptional(transitionProto.MoleculeId)); // Tab separated list of InChiKey, CAS etc
                    var monoMassH    = DataValues.FromOptional(transitionProto.MonoMassH);
                    var averageMassH = DataValues.FromOptional(transitionProto.AverageMassH);
                    var monoMass     = DataValues.FromOptional(transitionProto.MonoMass) ?? monoMassH;
                    var averageMass  = DataValues.FromOptional(transitionProto.AverageMass) ?? averageMassH;
                    customIon = new CustomMolecule(formula,
                                                   new TypedMass(monoMass.Value, monoMassH.HasValue ? MassType.MonoisotopicMassH : MassType.Monoisotopic),
                                                   new TypedMass(averageMass.Value, averageMassH.HasValue ? MassType.AverageMassH : MassType.Average),
                                                   DataValues.FromOptional(transitionProto.CustomIonName), moleculeID);
                }
            }
            Transition transition;
            var        adductString = DataValues.FromOptional(transitionProto.Adduct);
            var        adduct       = string.IsNullOrEmpty(adductString)
                ? Adduct.FromChargeProtonated(transitionProto.Charge)
                : Adduct.FromStringAssumeChargeOnly(adductString);

            if (isCustom)
            {
                transition = new Transition(group, isPrecursor ? group.PrecursorAdduct :adduct, transitionProto.MassIndex, customIon, ionType);
            }
            else if (isPrecursor)
            {
                transition = new Transition(group, ionType, group.Peptide.Length - 1, transitionProto.MassIndex,
                                            group.PrecursorAdduct, DataValues.FromOptional(transitionProto.DecoyMassShift));
            }
            else
            {
                int offset = Transition.OrdinalToOffset(ionType, transitionProto.FragmentOrdinal,
                                                        group.Peptide.Length);
                transition = new Transition(group, ionType, offset, transitionProto.MassIndex, adduct, DataValues.FromOptional(transitionProto.DecoyMassShift));
            }
            var losses          = TransitionLosses.FromLossProtos(settings, transitionProto.Losses);
            var mass            = settings.GetFragmentMass(group, mods, transition, isotopeDist);
            var isotopeDistInfo = GetIsotopeDistInfo(transition, losses, isotopeDist);

            if (group.DecoyMassShift.HasValue && transitionProto.DecoyMassShift == null)
            {
                throw new InvalidDataException(Resources.SrmDocument_ReadTransitionXml_All_transitions_of_decoy_precursors_must_have_a_decoy_mass_shift);
            }

            TransitionLibInfo libInfo = null;

            if (transitionProto.LibInfo != null)
            {
                libInfo = new TransitionLibInfo(transitionProto.LibInfo.Rank, transitionProto.LibInfo.Intensity);
            }
            var annotations = scrubber.ScrubAnnotations(Annotations.FromProtoAnnotations(transitionProto.Annotations), AnnotationDef.AnnotationTarget.transition);
            var results     = TransitionChromInfo.FromProtoTransitionResults(scrubber, settings, transitionProto.Results);
            var explicitTransitionValues = pre422ExplicitTransitionValues ?? ExplicitTransitionValues.Create(
                DataValues.FromOptional(transitionProto.ExplicitCollisionEnergy),
                DataValues.FromOptional(transitionProto.ExplicitIonMobilityHighEnergyOffset),
                DataValues.FromOptional(transitionProto.ExplicitSLens),
                DataValues.FromOptional(transitionProto.ExplicitConeVoltage),
                DataValues.FromOptional(transitionProto.ExplicitDeclusteringPotential));

            return(new TransitionDocNode(transition, annotations, losses, mass, new TransitionQuantInfo(isotopeDistInfo, libInfo, !transitionProto.NotQuantitative), explicitTransitionValues, results));
        }