/// <summary> /// Given two keys that match each other (i.e. the modification masses are within the other's margin of error) /// return a key which has the lower precision of the two. /// For instance, if one key is C[+57.021464]PEPTIDER[+10] and the is C[+57.02]PEPTIDEK[10.0083], /// the result be C[+57.02]PEPTIDER[+10]. /// </summary> private PeptideLibraryKey MostGeneralPeptideKey(PeptideLibraryKey key1, PeptideLibraryKey key2) { Assume.AreEqual(key1.UnmodifiedSequence, key2.UnmodifiedSequence); var mods1 = key1.GetModifications(); var mods2 = key2.GetModifications(); Assume.AreEqual(mods1.Count, mods2.Count); var newMods = new List <KeyValuePair <int, string> >(mods1.Count); for (int i = 0; i < mods1.Count; i++) { var mod1 = mods1[i]; var mod2 = mods2[i]; Assume.AreEqual(mod1.Key, mod2.Key); if (mod1.Value == mod2.Value) { newMods.Add(mod1); continue; } MassModification massMod1 = MassModification.Parse(mod1.Value); MassModification massMod2 = MassModification.Parse(mod2.Value); if (massMod1.Precision <= massMod2.Precision) { newMods.Add(mod1); } else { newMods.Add(mod2); } } return(new PeptideLibraryKey(MakeModifiedSequence(key1.UnmodifiedSequence, newMods), key1.Charge)); }
// 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++])); } }
/// <summary> /// Modify the XML that CreateXmlReader will parse for next caller. Finds each /// occuraece of elementName and changes or adds attribute name from attributesList. /// Expects as many occurences of elementName as there are members in attributesList /// </summary> public void ModifyAttributesInElement(string elementName, string attributeName, IList <string> attributesList) { var elementOpenA = string.Format("<{0} ", elementName); // Not L10N var elementOpenB = string.Format("<{0}>", elementName); // Not L10N var elementsA = XmlText.Split(new[] { elementOpenA }, StringSplitOptions.None); var elementsB = XmlText.Split(new[] { elementOpenB }, StringSplitOptions.None); var elements = elementsA.Length > elementsB.Length ? elementsA : elementsB; var elementOpen = elementsA.Length > elementsB.Length ? elementOpenA : elementOpenB; var attr = string.Format(" {0}=", attributeName); // Not L10N Assume.AreEqual(elements.Length, attributesList.Count + 1, "Trouble in XML lookahead"); // Not L10N for (var e = 1; e < elements.Length; e++) { var element = elements[e]; var attrStart = element.IndexOf(attr, StringComparison.InvariantCulture); var tagEnd = element.IndexOf(">", StringComparison.InvariantCulture); // Not L10N if (attrStart > tagEnd) { attrStart = -1; // That attr belonged to a child element } var newAttr = string.Format(" {0}\"{1}\" ", attr, attributesList[e - 1]); // Not L10N if (attrStart == -1) { elements[e] = newAttr + elements[e]; } else { var attrEnd = element.IndexOf("\"", attrStart + attr.Length + 1, StringComparison.InvariantCulture); // Not L10N elements[e] = elements[e].Substring(0, attrStart) + newAttr + elements[e].Substring(attrEnd + 1); } } XmlText = string.Join(elementOpen, elements); }
private string FormatLinkedPeptides(Func <IEnumerable <Modification>, string> modFormatter) { List <Tuple <int, Modification> > linkedModifications = new List <Tuple <int, Modification> >(); StringBuilder peptideSequences = new StringBuilder(); StringBuilder crosslinks = new StringBuilder(); int totalPeptides = 1; foreach (var mod in GetModifications().Where(mod => null != mod.ExplicitMod.LinkedPeptide)) { totalPeptides += mod.ExplicitMod.LinkedPeptide.CountDescendents(); if (mod.LinkedPeptideSequence == null) { crosslinks.Append(FormatCrosslinkMod(modFormatter, totalPeptides, mod, 0, 0)); } else { linkedModifications.Add(Tuple.Create(0, mod)); } } int peptideIndex = 0; while (linkedModifications.Any()) { peptideIndex++; var linkedModTuple = linkedModifications[0]; linkedModifications.RemoveAt(0); var linkedModification = linkedModTuple.Item2; if (linkedModTuple.Item2.LinkedPeptideSequence != null) { foreach (var mod in linkedModTuple.Item2.LinkedPeptideSequence.GetModifications() .Where(mod => null != mod.ExplicitMod.LinkedPeptide)) { if (mod.LinkedPeptideSequence == null) { crosslinks.Append(FormatCrosslinkMod(modFormatter, totalPeptides, mod, peptideIndex, peptideIndex)); } else { linkedModifications.Add(Tuple.Create(peptideIndex, mod)); } } } peptideSequences.Append(@"-"); peptideSequences.Append(linkedModification.LinkedPeptideSequence.FormatSelf(modFormatter)); crosslinks.Append(FormatCrosslinkMod(modFormatter, totalPeptides, linkedModification, linkedModTuple.Item1, peptideIndex)); } if (crosslinks.Length == 0) { Assume.AreEqual(0, peptideSequences.Length); return(string.Empty); } return(peptideSequences + @"-" + crosslinks); }
private void CheckRefSpectra(IList <DbRefSpectra> spectra, string name, string formula, string precursorAdduct, double precursorMz, ushort numPeaks, string[] fragmentNames = null, double?ionMobility = null, double?ionMobilityHighEnergyOffset = null) { if (_convertedFromPeptides) { name = RefinementSettings.TestingConvertedFromProteomicPeptideNameDecorator + name; } for (var i = 0; i < spectra.Count; i++) { var spectrum = spectra[i]; if (spectrum.MoleculeName.Equals(name) && spectrum.ChemicalFormula.Equals(formula) && spectrum.PrecursorCharge.Equals(Adduct.FromStringAssumeProtonated(precursorAdduct).AdductCharge) && spectrum.PrecursorAdduct.Equals(precursorAdduct) && Math.Abs(spectrum.PrecursorMZ - precursorMz) < 0.001 && spectrum.NumPeaks.Equals(numPeaks)) { // Found the item - check its fragment info if provided // This demonstrates fix for "Issue 689: File > Export > Spectral Library losing information from small molecule documents", // point 3 "Ion annotations do not preserve the ion names from the document but instead always use 'ion[mass]' for the annotations // when the document gave them names." if (fragmentNames != null) { Assume.AreEqual(fragmentNames.Length, spectrum.PeakAnnotations.Count); foreach (var annotation in spectrum.PeakAnnotations) { Assume.IsTrue(fragmentNames.Contains(annotation.Name)); } } if (ionMobility.HasValue) { AssertEx.AreEqualNullable(spectrum.IonMobility, ionMobility, .00001); if (ionMobilityHighEnergyOffset.HasValue) { AssertEx.AreEqualNullable(spectrum.IonMobilityHighEnergyOffset, ionMobilityHighEnergyOffset, .00001); } } // Item is OK, remove from further searches spectra.RemoveAt(i); return; } } Assume.Fail(string.Format("{0}, {1}, precursor charge {2}, precursor m/z {3}, with {4} peaks not found", name, formula, precursorAdduct, precursorMz, numPeaks)); }
/// <summary> /// Helper function for creating input tensors. /// type should match T. /// </summary> public static TensorProto Create2dTensor <T>(DataType type, Func <TensorProto, RepeatedField <T> > getVal, ICollection <T> inputs, params long[] dimensions) { // Construct Tensor var tp = new TensorProto { Dtype = type }; // Populate with data getVal(tp).AddRange(inputs); tp.TensorShape = new TensorShapeProto(); Assume.AreEqual(dimensions.Aggregate(1L, (a, b) => a * b), (long)inputs.Count); tp.TensorShape.Dim.AddRange(dimensions.Select(d => new TensorShapeProto.Types.Dim { Size = d })); return(tp); }
private void CompareDocumentTransitions(SrmDocument docA, SrmDocument docB) { // Note that we can't just run the lists in parallel - one of these is likely a small molecule conversion of the other, // and will have its transitions sorted differently Assume.AreEqual(docA.MoleculeTransitionGroupCount, docB.MoleculeTransitionGroupCount); foreach (var transGroupDocB in docB.MoleculeTransitionGroups) { var transGroupDocA = docA.MoleculeTransitionGroups.FirstOrDefault(a => Math.Abs(a.PrecursorMz - transGroupDocB.PrecursorMz) <= 1.5E-6 && Equals(a.TransitionCount, transGroupDocB.TransitionCount) && Equals(a.TransitionGroup.PrecursorAdduct.AdductCharge, transGroupDocB.TransitionGroup.PrecursorAdduct.AdductCharge) && Equals(a.TransitionGroup.LabelType, transGroupDocB.TransitionGroup.LabelType)); Assume.IsNotNull(transGroupDocA, "failed to find matching transition group"); var docBTransitions = transGroupDocB.Transitions.ToArray(); var docBTransitionsMatched = new List <TransitionDocNode>(); // ReSharper disable once PossibleNullReferenceException foreach (var transDocA in transGroupDocA.Transitions) { var a = transDocA; var transDocB = docBTransitions.FirstOrDefault(b => a.Transition.IsPrecursor() == b.Transition.IsPrecursor() && Math.Abs(a.Mz - b.Mz) <= 1.0E-5 && ((a.Results == null) ? (b.Results == null) : (a.Results.Count == b.Results.Count))); Assume.IsNotNull(transDocB, "failed to find matching transition"); Assume.IsFalse(docBTransitionsMatched.Contains(transDocB), "transition matched twice"); docBTransitionsMatched.Add(transDocB); // ReSharper disable PossibleNullReferenceException using (var docBChromInfos = transDocB.ChromInfos.GetEnumerator()) { foreach (var infoDocA in transDocA.ChromInfos) { Assume.IsTrue(docBChromInfos.MoveNext()); var infoDocB = docBChromInfos.Current; Assume.IsTrue(infoDocA.Equals(infoDocB)); } } // ReSharper restore PossibleNullReferenceException } } }
public MoleculeAccessionNumbers(string keysTSV, string inChiKey = null) { var keys = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); // Treat "cas" and "CAS" as identical lookups if (!string.IsNullOrEmpty(keysTSV) || !string.IsNullOrEmpty(inChiKey)) { if (!string.IsNullOrEmpty(keysTSV)) { // Pick apart a string like "CAS:58-08-2\tinchi:1S/C8H10N4O2/c1-10-4-9-6-5(10)7(13)12(3)8(14)11(6)2/h4H,1-3H3\tmykey:a:b:c:d" foreach (var kvp in keysTSV.Split(TextUtil.SEPARATOR_TSV)) { var pair = kvp.Split(':'); if (pair.Length > 1) { var key = pair[0].Trim(); var value = string.Join(":", pair.Skip(1)).Trim(); // In case value contains semicolons // Not L10N if (!string.IsNullOrEmpty(value)) { keys.Add(key, value); } } } } if (!string.IsNullOrEmpty(inChiKey)) { if (keys.ContainsKey(TagInChiKey)) { Assume.AreEqual(inChiKey, keys[TagInChiKey]); } else { keys.Add(TagInChiKey, inChiKey); } } } AccessionNumbers = ImmutableSortedList <string, string> .FromValues(keys, ACCESSION_TYPE_SORTER); }
protected override void DoTest() { string skyFile = TestFilesDir.GetTestPath("tims_test.sky"); Program.ExtraRawFileSearchFolder = TestFilesDir.PersistentFilesDir; var testPath = TestFilesDir.GetTestPath("local.sky"); // Make sure that commandline loading employs 3-array IMS (should be quick if it does) TestCommandlineImport(skyFile, testPath); RunUI(() => Settings.Default.ImportResultsSimultaneousFiles = (int)MultiFileLoader.ImportResultsSimultaneousFileOptions.many); // use maximum threads for multiple file import RunUI(() => SkylineWindow.OpenFile(skyFile)); ImportResults(BSA_50fmol_TIMS_InfusionESI_10precd); var document = WaitForDocumentLoaded(240000); // mz5 part of this this can take awhile AssertEx.IsDocumentState(document, null, 1, 34, 89, 1007); RunUI(() => { // Show that we can reopen a document with 3-array data in it SkylineWindow.SaveDocument(testPath); SkylineWindow.NewDocument(); VerifySerialization(testPath, false); SkylineWindow.LoadFile(testPath); }); document = WaitForDocumentLoaded(240000); var transitions = document.MoleculeTransitions.ToArray(); // Verify ability to extract ion mobility peaks from raw data var peptideSettingsDlg = ShowDialog <PeptideSettingsUI>( () => SkylineWindow.ShowPeptideSettingsUI(PeptideSettingsUI.TABS.Prediction)); // Simulate user picking Add from the ion mobility Predictor combo control var driftTimePredictorDlg = ShowDialog <EditDriftTimePredictorDlg>(peptideSettingsDlg.AddDriftTimePredictor); RunUI(() => { driftTimePredictorDlg.SetOffsetHighEnergySpectraCheckbox(true); driftTimePredictorDlg.SetPredictorName("test_tims"); driftTimePredictorDlg.SetResolvingPower(40); driftTimePredictorDlg.GetDriftTimesFromResults(); }); // PauseTest(); // Uncomment this to inspect ion mobility finder results RunUI(() => { driftTimePredictorDlg.OkDialog(true); // Force overwrite if a named predictor already exists }); WaitForClosedForm(driftTimePredictorDlg); RunUI(() => { peptideSettingsDlg.OkDialog(); }); WaitForClosedForm(peptideSettingsDlg); var docChangedDriftTimePredictor = WaitForDocumentChange(document); // Reimport data - should shift precursors RunDlg <ManageResultsDlg>(SkylineWindow.ManageResults, dlg => { var chromatograms = docChangedDriftTimePredictor.Settings.MeasuredResults.Chromatograms; dlg.SelectedChromatograms = new[] { chromatograms[0] }; dlg.ReimportResults(); dlg.OkDialog(); }); document = WaitForDocumentChangeLoaded(docChangedDriftTimePredictor); var transitionsNew = document.MoleculeTransitions.ToArray(); var nChanges = 0; var nNonEmpty = 0; for (var i = 0; i < transitions.Length; i++) { Assert.AreEqual(transitions[i].Mz, transitionsNew[i].Mz); if (transitions[i].AveragePeakArea.HasValue) { nNonEmpty++; if (transitions[i].AveragePeakArea != transitionsNew[i].AveragePeakArea) // Using filter should alter peak area { nChanges++; } } else { Assert.AreEqual(transitions[i].AveragePeakArea, transitionsNew[i].AveragePeakArea); } } Assert.IsTrue(nChanges >= nNonEmpty * .9); // We expect nearly all peaks to change in area with IMS filter in use // And read some mz5 converted from Bruker in 2-array IMS format, then compare replicates - should be identical var mz5 = TestFilesDir.GetTestPath(bsaFmolTimsInfusionesiPrecMz5Mz5); ImportResultsFile(mz5); document = WaitForDocumentChange(document); var sb = new StringBuilder(); int trials = 0; int diffs = 0; foreach (var nodeGroup in document.MoleculeTransitionGroups) { Assert.AreEqual(2, nodeGroup.Results.Count); foreach (TransitionDocNode nodeTran in nodeGroup.Children) { Assume.AreEqual(2, nodeTran.Results.Count); if (nodeTran.Results[0].Any() || nodeTran.Results[1].Any()) { trials++; } if (Equals(nodeTran.Results[0], nodeTran.Results[1])) { continue; } var diff = Math.Abs(nodeTran.Results[0].First().Area - nodeTran.Results[1].First().Area) / Math.Min(nodeTran.Results[0].First().Area, nodeTran.Results[1].First().Area); diffs++; if (diff > 0) { sb.AppendLine(string.Format("Difference {0} in {1} - {2}", diff, nodeGroup, nodeTran.Transition)); } else { sb.AppendLine(string.Format("No area difference in {0} - {1}", nodeGroup, nodeTran.Transition)); } } } if (sb.Length > 0) { Assert.Fail(TextUtil.LineSeparate(string.Format("{0} of {1} differences found in peak areas between 2- and 3- array spectra", diffs, trials), sb.ToString())); } // Verify that the data was loaded in 3-array IMS format for .d and 2-array for .mz5 (which was converted that way on purpose) by looking at serialization RunUI(() => { SkylineWindow.SaveDocument(testPath); }); VerifySerialization(testPath, true); }
/// <summary> /// Returns true if Skyline can handle the structure of the crosslinks in this CrosslinkLibraryKey. /// </summary> public bool IsSupportedBySkyline() { var queue = new List <int>(); var remainingCrosslinks = new List <ImmutableList <int> >(); var consumedPeptides = new HashSet <int>(); foreach (var crosslink in Crosslinks) { var peptideIndexesWithLinks = ImmutableList.ValueOf(crosslink.PeptideIndexesWithLinks); if (peptideIndexesWithLinks.Count == 1) { if (crosslink.AaIndexes[peptideIndexesWithLinks[0]].Count() != 2) { return(false); } } else if (peptideIndexesWithLinks.Count == 2) { if (peptideIndexesWithLinks.Any(index => crosslink.AaIndexes[index].Count() != 1)) { return(false); } if (peptideIndexesWithLinks.Contains(0)) { Assume.AreEqual(peptideIndexesWithLinks[0], 0); queue.Add(peptideIndexesWithLinks[1]); } else { remainingCrosslinks.Add(peptideIndexesWithLinks); } } else { return(false); } } consumedPeptides.Add(0); while (queue.Count != 0) { int currentPeptideIndex = queue[0]; queue.RemoveAt(0); if (!consumedPeptides.Add(currentPeptideIndex)) { return(false); } for (int iCrosslink = remainingCrosslinks.Count - 1; iCrosslink >= 0; iCrosslink--) { var crosslinkIndexes = remainingCrosslinks[iCrosslink]; if (!crosslinkIndexes.Contains(currentPeptideIndex)) { continue; } int otherPeptideIndex = crosslinkIndexes.Except(new[] { currentPeptideIndex }).First(); queue.Add(otherPeptideIndex); remainingCrosslinks.RemoveAt(iCrosslink); } } if (consumedPeptides.Count != PeptideLibraryKeys.Count) { return(false); } return(true); }
private void DoFullScanFilterTest(RefinementSettings.ConvertToSmallMoleculesMode asSmallMolecules, out List <SrmDocument> docCheckpoints, bool centroided = false) { docCheckpoints = new List <SrmDocument>(); var testFilesDir = new TestFilesDir(TestContext, ZIP_FILE); string docPath = testFilesDir.GetTestPath("BSA_Protea_label_free_20100323_meth3_multi.sky"); var expectedPepCount = 7; var expectedTransGroupCount = 7; var expectedTransCount = 49; var doc = InitFullScanDocument(ref docPath, 2, ref expectedPepCount, ref expectedTransGroupCount, ref expectedTransCount, asSmallMolecules); if (centroided && ExtensionTestContext.CanImportThermoRaw) { const double ppm20 = 20.0; doc = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorResolution(FullScanMassAnalyzerType.centroided, ppm20, 0))); } using (var docContainer = new ResultsTestDocumentContainer(doc, docPath)) { // Import the first RAW file (or mzML for international) string rawPath = testFilesDir.GetTestPath("ah_20101011y_BSA_MS-MS_only_5-2" + ExtensionTestContext.ExtThermoRaw); var measuredResults = new MeasuredResults(new[] { new ChromatogramSet("Single", new[] { new MsDataFilePath(rawPath) }) }); SrmDocument docResults = docContainer.ChangeMeasuredResults(measuredResults, 3, 3, 21); docCheckpoints.Add(docResults); // Refilter allowing multiple precursors per spectrum SrmDocument docMulti = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan( fs => fs.ChangeAcquisitionMethod(FullScanAcquisitionMethod.DIA, new IsolationScheme("Test", 2)))); AssertEx.Serializable(docMulti, AssertEx.DocumentCloned); // Release data cache file Assume.IsTrue(docContainer.SetDocument(docMulti, docResults)); // And remove it FileEx.SafeDelete(Path.ChangeExtension(docPath, ChromatogramCache.EXT)); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, 6, 6, 38)); // Import full scan Orbi-Velos data docPath = testFilesDir.GetTestPath("BSA_Protea_label_free_20100323_meth3_long_acc_template.sky"); expectedPepCount = 3; expectedTransGroupCount = 3; expectedTransCount = 21; doc = InitFullScanDocument(ref docPath, 1, ref expectedPepCount, ref expectedTransGroupCount, ref expectedTransCount, asSmallMolecules); docCheckpoints.Add(doc); Assume.AreEqual(FullScanMassAnalyzerType.orbitrap, doc.Settings.TransitionSettings.FullScan.ProductMassAnalyzer); // Make sure saving this type of document works AssertEx.Serializable(doc, AssertEx.DocumentCloned); Assume.IsTrue(docContainer.SetDocument(doc, docContainer.Document)); rawPath = testFilesDir.GetTestPath("ah_20101029r_BSA_CID_FT_centroid_3uscan_3" + ExtensionTestContext.ExtThermoRaw); measuredResults = new MeasuredResults(new[] { new ChromatogramSet("Accurate", new[] { rawPath }) }); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, 3, 3, 21)); // Import LTQ data with MS1 and MS/MS docPath = testFilesDir.GetTestPath("BSA_Protea_label_free_20100323_meth3_test4.sky"); expectedPepCount = 3; expectedTransGroupCount = 4; expectedTransCount = 32; doc = InitFullScanDocument(ref docPath, 3, ref expectedPepCount, ref expectedTransGroupCount, ref expectedTransCount, asSmallMolecules); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.ProductMassAnalyzer); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.PrecursorMassAnalyzer); docCheckpoints.Add(doc); var docBoth = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangeAcquisitionMethod(FullScanAcquisitionMethod.Targeted, null) .ChangePrecursorResolution(FullScanMassAnalyzerType.qit, TransitionFullScan.DEFAULT_RES_QIT, null))); docCheckpoints.Add(docBoth); AssertEx.Serializable(docBoth, AssertEx.DocumentCloned); Assume.IsTrue(docContainer.SetDocument(docBoth, docContainer.Document)); string dataPath = testFilesDir.GetTestPath("klc_20100329v_Protea_Peptide_Curve_200fmol_uL_tech1.mzML"); var listResults = new List <ChromatogramSet> { new ChromatogramSet("MS1 and MS/MS", new[] { dataPath }), }; measuredResults = new MeasuredResults(listResults.ToArray()); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, expectedPepCount, expectedTransGroupCount, expectedTransCount - 6)); // The mzML was filtered for the m/z range 410 to 910. foreach (var nodeTran in docContainer.Document.MoleculeTransitions) { Assume.IsTrue(nodeTran.HasResults); Assume.IsNotNull(nodeTran.Results[0]); if (410 > nodeTran.Mz || nodeTran.Mz > 910) { Assume.IsTrue(nodeTran.Results[0][0].IsForcedIntegration); } else { Assume.IsFalse(nodeTran.Results[0][0].IsForcedIntegration); } } // Import LTQ data with MS1 and MS/MS using multiple files for a single replicate listResults.Add(new ChromatogramSet("Multi-file", new[] { testFilesDir.GetTestPath("both_DRV.mzML"), testFilesDir.GetTestPath("both_KVP.mzML"), })); measuredResults = new MeasuredResults(listResults.ToArray()); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, expectedPepCount - 1, expectedTransGroupCount - 1, expectedTransCount - 6)); if (asSmallMolecules == RefinementSettings.ConvertToSmallMoleculesMode.masses_only) { return; // Can't work with isotope distributions when we don't have ion formulas } int indexResults = listResults.Count - 1; var matchIdentifierDRV = "DRV"; if (asSmallMolecules != RefinementSettings.ConvertToSmallMoleculesMode.none) { matchIdentifierDRV = RefinementSettings.TestingConvertedFromProteomicPeptideNameDecorator + matchIdentifierDRV; } int index = 0; foreach (var nodeTran in docContainer.Document.MoleculeTransitions) { Assume.IsTrue(nodeTran.HasResults); Assume.AreEqual(listResults.Count, nodeTran.Results.Count); var peptide = nodeTran.Transition.Group.Peptide; if (peptide.IsCustomMolecule && index == 24) { // Conversion to small molecule loses some of the nuance of "Sequence" vs "FastaSequence", comparisons are inexact Assume.AreEqual("pep_DRVY[+80.0]IHPF", nodeTran.PrimaryCustomIonEquivalenceKey); break; } // DRV without FASTA sequence should not have data for non-precursor transitions if (!peptide.TextId.StartsWith(matchIdentifierDRV) || (!peptide.IsCustomMolecule && !peptide.Begin.HasValue)) { Assume.IsNotNull(nodeTran.Results[indexResults]); Assume.IsFalse(nodeTran.Results[indexResults][0].IsEmpty); } else if (nodeTran.Transition.IonType != IonType.precursor) { Assert.IsTrue(nodeTran.Results[indexResults].IsEmpty); } else { // Random, bogus peaks chosen in both files Assume.IsNotNull(nodeTran.Results[indexResults]); Assume.AreEqual(2, nodeTran.Results[indexResults].Count); Assume.IsFalse(nodeTran.Results[indexResults][0].IsEmpty); Assume.IsFalse(nodeTran.Results[indexResults][1].IsEmpty); } index++; } // Verify handling of bad request for vendor centroided data - out-of-range PPM docPath = testFilesDir.GetTestPath("Yeast_HI3 Peptides_test.sky"); expectedPepCount = 2; expectedTransGroupCount = 2; expectedTransCount = 2; doc = InitFullScanDocument(ref docPath, 2, ref expectedPepCount, ref expectedTransGroupCount, ref expectedTransCount, asSmallMolecules); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.ProductMassAnalyzer); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.PrecursorMassAnalyzer); var docBad = doc; AssertEx.ThrowsException <InvalidDataException>(() => docBad.ChangeSettings(docBad.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 1, IsotopeEnrichmentsList.DEFAULT) .ChangePrecursorResolution(FullScanMassAnalyzerType.centroided, 50 * 1000, 400))), string.Format(Resources.TransitionFullScan_ValidateRes_Mass_accuracy_must_be_between__0__and__1__for_centroided_data_, TransitionFullScan.MIN_CENTROID_PPM, TransitionFullScan.MAX_CENTROID_PPM)); // Verify relationship between PPM and resolving power const double ppm = 20.0; // Should yield same filter width as resolving power 50,000 in TOF var docNoCentroid = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 1, IsotopeEnrichmentsList.DEFAULT) .ChangePrecursorResolution(FullScanMassAnalyzerType.centroided, ppm, 0))); AssertEx.Serializable(docNoCentroid, AssertEx.DocumentCloned); Assume.IsTrue(docContainer.SetDocument(docNoCentroid, docContainer.Document)); const double mzTest = 400.0; var filterWidth = docNoCentroid.Settings.TransitionSettings.FullScan.GetPrecursorFilterWindow(mzTest); Assume.AreEqual(mzTest * 2.0 * ppm * 1E-6, filterWidth); // Verify relationship between normal and high-selectivity extraction var docTofNormal = docNoCentroid.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 50 * 1000, null))); AssertEx.Serializable(docTofNormal, AssertEx.DocumentCloned); var docTofSelective = docTofNormal.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 25 * 1000, null) .ChangeUseSelectiveExtraction(true))); AssertEx.Serializable(docTofSelective, AssertEx.DocumentCloned); var filterWidthTof = docTofNormal.Settings.TransitionSettings.FullScan.GetPrecursorFilterWindow(mzTest); var filterWidthSelective = docTofSelective.Settings.TransitionSettings.FullScan.GetPrecursorFilterWindow(mzTest); Assume.AreEqual(filterWidth, filterWidthTof); Assume.AreEqual(filterWidth, filterWidthSelective); // Verify handling of bad request for vendor centroided data - ask for centroiding in mzML const string fileName = "S_2_LVN.mzML"; var filePath = testFilesDir.GetTestPath(fileName); AssertEx.ThrowsException <AssertFailedException>(() => { listResults = new List <ChromatogramSet> { new ChromatogramSet("rep1", new[] { new MsDataFilePath(filePath) }), }; docContainer.ChangeMeasuredResults(new MeasuredResults(listResults.ToArray()), 1, 1, 1); }, string.Format(Resources.NoCentroidedDataException_NoCentroidedDataException_No_centroided_data_available_for_file___0_____Adjust_your_Full_Scan_settings_, filePath)); // Import FT data with only MS1 docPath = testFilesDir.GetTestPath("Yeast_HI3 Peptides_test.sky"); expectedPepCount = 2; expectedTransGroupCount = 2; expectedTransCount = 2; doc = InitFullScanDocument(ref docPath, 2, ref expectedPepCount, ref expectedTransGroupCount, ref expectedTransCount, asSmallMolecules); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.ProductMassAnalyzer); Assume.AreEqual(FullScanMassAnalyzerType.none, doc.Settings.TransitionSettings.FullScan.PrecursorMassAnalyzer); var docMs1 = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 1, IsotopeEnrichmentsList.DEFAULT) .ChangePrecursorResolution(FullScanMassAnalyzerType.tof, 50 * 1000, null))); Assume.AreEqual(filterWidth, docMs1.Settings.TransitionSettings.FullScan.GetPrecursorFilterWindow(mzTest)); docMs1 = doc.ChangeSettings(doc.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 1, IsotopeEnrichmentsList.DEFAULT) .ChangePrecursorResolution(FullScanMassAnalyzerType.ft_icr, 50 * 1000, mzTest))); AssertEx.Serializable(docMs1, AssertEx.DocumentCloned); Assume.IsTrue(docContainer.SetDocument(docMs1, docContainer.Document)); const string rep1 = "rep1"; listResults = new List <ChromatogramSet> { new ChromatogramSet(rep1, new[] { filePath }), }; measuredResults = new MeasuredResults(listResults.ToArray()); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, 1, 1, 1)); // Because of the way the mzML files were filtered, all of the LVN peaks should be present // in the first replicate, and all of the NVN peaks should be present in the other. var matchIdentifierLVN = "LVN"; if (asSmallMolecules != RefinementSettings.ConvertToSmallMoleculesMode.none) { matchIdentifierLVN = RefinementSettings.TestingConvertedFromProteomicPeptideNameDecorator + matchIdentifierLVN; } foreach (var nodeTranGroup in docContainer.Document.MoleculeTransitionGroups) { foreach (var docNode in nodeTranGroup.Children) { var nodeTran = (TransitionDocNode)docNode; Assume.IsTrue(nodeTran.HasResults); Assume.AreEqual(1, nodeTran.Results.Count); if (nodeTran.Transition.Group.Peptide.Target.ToString().StartsWith(matchIdentifierLVN)) { Assume.IsFalse(nodeTran.Results[0][0].IsEmpty); } else { Assume.IsTrue(nodeTran.Results[0][0].IsEmpty); } } } const string rep2 = "rep2"; listResults.Add(new ChromatogramSet(rep2, new[] { testFilesDir.GetTestPath("S_2_NVN.mzML") })); measuredResults = new MeasuredResults(listResults.ToArray()); docCheckpoints.Add(docContainer.ChangeMeasuredResults(measuredResults, 1, 1, 1)); // Because of the way the mzML files were filtered, all of the LVN peaks should be present // in the first replicate, and all of the NVN peaks should be present in the other. foreach (var nodeTranGroup in docContainer.Document.MoleculeTransitionGroups) { foreach (var docNode in nodeTranGroup.Children) { var nodeTran = (TransitionDocNode)docNode; Assume.IsTrue(nodeTran.HasResults); Assume.AreEqual(2, nodeTran.Results.Count); if (nodeTran.Transition.Group.Peptide.Target.ToString().StartsWith(matchIdentifierLVN)) { Assume.IsTrue(nodeTran.Results[1][0].IsEmpty); } else { Assume.IsFalse(nodeTran.Results[1][0].IsEmpty); } } } // Chromatograms should be present in the cache for a number of isotopes. var docMs1Isotopes = docContainer.Document.ChangeSettings(doc.Settings .ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 3, IsotopeEnrichmentsList.DEFAULT)) .ChangeTransitionFilter(filter => filter.ChangePeptideIonTypes(new[] { IonType.precursor }) .ChangeSmallMoleculeIonTypes(new[] { IonType.precursor }))); docCheckpoints.Add(docMs1Isotopes); AssertEx.IsDocumentState(docMs1Isotopes, null, 2, 2, 2); // Need to reset auto-manage for transitions var refineAutoSelect = new RefinementSettings { AutoPickChildrenAll = PickLevel.transitions }; docMs1Isotopes = refineAutoSelect.Refine(docMs1Isotopes); AssertEx.IsDocumentState(docMs1Isotopes, null, 2, 2, 6); AssertResult.IsDocumentResultsState(docMs1Isotopes, rep1, 1, 1, 0, 3, 0); AssertResult.IsDocumentResultsState(docMs1Isotopes, rep2, 1, 1, 0, 3, 0); docCheckpoints.Add(docMs1Isotopes); // Add M-1 transitions, and verify that they have chromatogram data also, but // empty peaks in all cases var docMs1All = docMs1Isotopes.ChangeSettings(docMs1Isotopes.Settings .ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Percent, 0, IsotopeEnrichmentsList.DEFAULT)) .ChangeTransitionIntegration(i => i.ChangeIntegrateAll(false))); // For compatibility with v2.5 and earlier docCheckpoints.Add(docMs1All); AssertEx.IsDocumentState(docMs1All, null, 2, 2, 10); AssertResult.IsDocumentResultsState(docMs1All, rep1, 1, 1, 0, 4, 0); AssertResult.IsDocumentResultsState(docMs1All, rep2, 1, 1, 0, 4, 0); var ms1AllTranstions = docMs1All.MoleculeTransitions.ToArray(); var tranM1 = ms1AllTranstions[0]; Assert.AreEqual(-1, tranM1.Transition.MassIndex); Assert.IsTrue(!tranM1.Results[0].IsEmpty && !tranM1.Results[1].IsEmpty); Assert.IsTrue(tranM1.Results[0][0].IsEmpty && tranM1.Results[1][0].IsForcedIntegration); tranM1 = ms1AllTranstions[5]; Assert.AreEqual(-1, tranM1.Transition.MassIndex); Assert.IsTrue(!tranM1.Results[0].IsEmpty && !tranM1.Results[1].IsEmpty); Assert.IsTrue(tranM1.Results[0][0].IsForcedIntegration && tranM1.Results[1][0].IsEmpty); } }
public void DoFullScanSettingsTest(RefinementSettings.ConvertToSmallMoleculesMode asSmallMolecules, out List <SrmDocument> docCheckPoints) { docCheckPoints = new List <SrmDocument>(); var doc0 = ResultsUtil.DeserializeDocument("MultiLabel.sky", GetType()); var refine = new RefinementSettings(); var docSM = refine.ConvertToSmallMolecules(doc0, ".", asSmallMolecules); docCheckPoints.Add(docSM); Assert.IsFalse(docSM.MoleculeTransitionGroups.Any(nodeGroup => nodeGroup.IsotopeDist != null)); AssertEx.Serializable(docSM, AssertEx.Cloned); double c13Delta = BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.C13) - BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.C); double n15Delta = BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.N15) - BioMassCalc.MONOISOTOPIC.GetMass(BioMassCalc.N); // Verify isotope distributions calculated when MS1 filtering enabled var enrichments = IsotopeEnrichmentsList.DEFAULT; var docIsotopes = docSM.ChangeSettings(docSM.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Count, 3, enrichments))); docCheckPoints.Add(docIsotopes); Assert.AreEqual(FullScanMassAnalyzerType.tof, docIsotopes.Settings.TransitionSettings.FullScan.PrecursorMassAnalyzer); Assert.IsFalse(docIsotopes.MoleculeTransitionGroups.Any(nodeGroup => nodeGroup.IsotopeDist == null)); foreach (var nodeGroup in docIsotopes.MoleculeTransitionGroups) { Assert.AreEqual(3, nodeGroup.Children.Count); var isotopePeaks = nodeGroup.IsotopeDist; Assert.IsNotNull(isotopePeaks); Assert.IsTrue(nodeGroup.HasIsotopeDist); // The peaks should always includ at least M-1 Assume.IsTrue(isotopePeaks.MassIndexToPeakIndex(0) > 0); // Within 2.5% of 100% of the entire isotope distribution Assert.AreEqual(1.0, isotopePeaks.ExpectedProportions.Sum(), 0.025); // Precursor mass and m/z values are expected to match exactly (well, within XML roundtrip accuracy anyway) Assert.AreEqual(nodeGroup.PrecursorMz, nodeGroup.IsotopeDist.GetMZI(0), SequenceMassCalc.MassTolerance); Assert.AreEqual(nodeGroup.PrecursorMz, nodeGroup.TransitionGroup.IsCustomIon ? BioMassCalc.CalculateIonMz(nodeGroup.IsotopeDist.GetMassI(0), nodeGroup.TransitionGroup.PrecursorAdduct.Unlabeled) : SequenceMassCalc.GetMZ(nodeGroup.IsotopeDist.GetMassI(0), nodeGroup.TransitionGroup.PrecursorAdduct), SequenceMassCalc.MassTolerance); // Check isotope distribution masses for (int i = 1; i < isotopePeaks.CountPeaks; i++) { int massIndex = isotopePeaks.PeakIndexToMassIndex(i); Assert.IsTrue(isotopePeaks.GetMZI(massIndex - 1) < isotopePeaks.GetMZI(massIndex)); double massDelta = GetMassDelta(isotopePeaks, massIndex); if (nodeGroup.TransitionGroup.LabelType.IsLight) { // All positive should be close to 13C - C, and 0 should be the same as the next delta double expectedDelta = (massIndex > 0 ? c13Delta : GetMassDelta(isotopePeaks, massIndex + 1)); Assert.AreEqual(expectedDelta, massDelta, 0.001); } else if (nodeGroup.TransitionGroup.LabelType.Name.Contains("15N")) { // All positive should be close to 13C, and all negative 15N double expectedDelta = (massIndex > 0 ? c13Delta : n15Delta); Assert.AreEqual(expectedDelta, massDelta, 0.0015); } else if (massIndex == 0) { double expectedDelta = (isotopePeaks.GetProportionI(massIndex - 1) == 0 ? GetMassDelta(isotopePeaks, massIndex + 1) : 1.0017); Assert.AreEqual(expectedDelta, massDelta, 0.001); } else { Assert.AreEqual(c13Delta, massDelta, 0.001); } } } AssertEx.Serializable(docIsotopes, AssertEx.Cloned); // Narrow the resolution, and verify that predicted proportion of the isotope // distribution captured is reduced for all precursors var docIsotopesFt = docIsotopes.ChangeSettings(docIsotopes.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorResolution(FullScanMassAnalyzerType.ft_icr, 500 * 1000, 400))); docCheckPoints.Add(docIsotopesFt); var tranGroupsOld = docIsotopes.MoleculeTransitionGroups.ToArray(); var tranGroupsNew = docIsotopesFt.MoleculeTransitionGroups.ToArray(); Assume.AreEqual(tranGroupsOld.Length, tranGroupsNew.Length); for (int i = 0; i < tranGroupsOld.Length; i++) { Assert.AreNotSame(tranGroupsOld[i], tranGroupsNew[i]); Assert.AreNotSame(tranGroupsOld[i].IsotopeDist, tranGroupsNew[i].IsotopeDist); Assert.IsTrue(tranGroupsOld[i].IsotopeDist.ExpectedProportions.Sum() > tranGroupsNew[i].IsotopeDist.ExpectedProportions.Sum()); } // Use Min % of base peak and verify variation in transitions used const float minPercent1 = 10; var docIsotopesP1 = docIsotopes.ChangeSettings(docIsotopes.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Percent, minPercent1, enrichments))); docCheckPoints.Add(docIsotopesP1); tranGroupsNew = docIsotopesP1.MoleculeTransitionGroups.ToArray(); int maxTran = 0; for (int i = 0; i < tranGroupsOld.Length; i++) { // Isotope distributions should not have changed var isotopePeaks = tranGroupsNew[i].IsotopeDist; Assert.AreSame(tranGroupsOld[i].IsotopeDist, isotopePeaks); // Expected transitions should be present maxTran = Math.Max(maxTran, tranGroupsNew[i].Children.Count); foreach (TransitionDocNode nodeTran in tranGroupsNew[i].Children) { int massIndex = nodeTran.Transition.MassIndex; Assume.IsTrue(minPercent1 <= isotopePeaks.GetProportionI(massIndex) * 100.0 / isotopePeaks.BaseMassPercent); } } Assume.AreEqual(5, maxTran); AssertEx.Serializable(docIsotopesP1, AssertEx.Cloned); // Express any failure in terms of XML diffs // Use 10%, and check that 15N modifications all have M-1 const float minPercent2 = 5; var docIsotopesP2 = docIsotopesP1.ChangeSettings(docIsotopesP1.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Percent, minPercent2, enrichments))); docCheckPoints.Add(docIsotopesP2); foreach (var nodeGroup in docIsotopesP2.MoleculeTransitionGroups) { var firstChild = (TransitionDocNode)nodeGroup.Children[0]; if (nodeGroup.TransitionGroup.LabelType.Name.EndsWith("15N")) { Assume.AreEqual(-1, firstChild.Transition.MassIndex); } else { Assume.AreNotEqual(-1, firstChild.Transition.MassIndex); } } AssertEx.Serializable(docIsotopesP2, AssertEx.Cloned); // Use lower enrichment of 13C, and verify that this add M-1 for 13C labeled precursors var enrichmentsLow13C = enrichments.ChangeEnrichment(new IsotopeEnrichmentItem(BioMassCalc.C13, 0.9)); var docIsotopesLow13C = docIsotopesP1.ChangeSettings(docIsotopesP1.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Percent, minPercent2, enrichmentsLow13C))); tranGroupsNew = docIsotopesLow13C.MoleculeTransitionGroups.ToArray(); for (int i = 0; i < tranGroupsOld.Length; i++) { var nodeGroup = tranGroupsNew[i]; if (!Equals(nodeGroup.TransitionGroup.LabelType.Name, "heavy")) { Assert.AreSame(tranGroupsOld[i].IsotopeDist, nodeGroup.IsotopeDist); } else { var firstChild = (TransitionDocNode)nodeGroup.Children[0]; Assert.IsTrue(firstChild.Transition.MassIndex < 0); } } AssertEx.Serializable(docIsotopesLow13C, AssertEx.Cloned); // Express any failure as XML diffs // Use 0%, and check that everything has M-1 and lower var enrichmentsLow = enrichmentsLow13C.ChangeEnrichment(new IsotopeEnrichmentItem(BioMassCalc.N15, 0.97)); var docIsotopesLowP0 = docIsotopesP1.ChangeSettings(docIsotopesP1.Settings.ChangeTransitionFullScan(fs => fs.ChangePrecursorIsotopes(FullScanPrecursorIsotopes.Percent, 0, enrichmentsLow))); docCheckPoints.Add(docIsotopesLowP0); foreach (var nodeGroup in docIsotopesLowP0.MoleculeTransitionGroups) { Assume.AreEqual(nodeGroup.IsotopeDist.CountPeaks, nodeGroup.Children.Count); var firstChild = (TransitionDocNode)nodeGroup.Children[0]; if (nodeGroup.TransitionGroup.LabelType.IsLight) { Assert.AreEqual(-1, firstChild.Transition.MassIndex); } else { Assert.IsTrue(-1 > firstChild.Transition.MassIndex); } } AssertEx.Serializable(docIsotopesLowP0, AssertEx.Cloned); // Test a document with variable and heavy modifications, which caused problems for // the original implementation var docVariable = ResultsUtil.DeserializeDocument("HeavyVariable.sky", GetType()); Assert.IsFalse(docVariable.MoleculeTransitionGroups.Any(nodeGroup => nodeGroup.IsotopeDist == null)); foreach (var nodeGroup in docVariable.MoleculeTransitionGroups) { var isotopePeaks = nodeGroup.IsotopeDist; Assert.IsNotNull(isotopePeaks); // The peaks should always includ at least M-1 Assert.IsTrue(isotopePeaks.MassIndexToPeakIndex(0) > 0); // Precursor mass and m/z values are expected to match exactly (well, within XML roundtrip tolerance anyway) var mzI = nodeGroup.IsotopeDist.GetMZI(0); Assert.AreEqual(nodeGroup.PrecursorMz, mzI, SequenceMassCalc.MassTolerance); // Check isotope distribution masses for (int i = 1; i < isotopePeaks.CountPeaks; i++) { int massIndex = isotopePeaks.PeakIndexToMassIndex(i); Assert.IsTrue(isotopePeaks.GetMZI(massIndex - 1) < isotopePeaks.GetMZI(massIndex)); double massDelta = GetMassDelta(isotopePeaks, massIndex); bool containsSulfur = nodeGroup.TransitionGroup.Peptide.IsCustomMolecule ? (nodeGroup.CustomMolecule.Formula.IndexOfAny("S".ToCharArray()) != -1) : (nodeGroup.TransitionGroup.Peptide.Sequence.IndexOfAny("CM".ToCharArray()) != -1); if (massIndex == 0) { double expectedDelta = (isotopePeaks.GetProportionI(massIndex - 1) == 0 ? GetMassDelta(isotopePeaks, massIndex + 1) : 1.0017); Assert.AreEqual(expectedDelta, massDelta, 0.001); } else if (!containsSulfur || massIndex == 1) { Assert.AreEqual(c13Delta, massDelta, 0.001); } else { Assert.AreEqual(1.00075, massDelta, 0.001); } } } docCheckPoints.Add(docVariable); }
protected override void DoTest() { // Load a document with results loaded without drift filter string skyFile = TestFilesDir.GetTestPath("tims_test.sky"); Program.ExtraRawFileSearchFolder = TestFilesDir.PersistentFilesDir; // So we don't have to reload the raw files, which have moved relative to skyd file RunUI(() => SkylineWindow.OpenFile(skyFile)); var document = WaitForDocumentLoaded(240000); // If it decides to remake chromatograms this can take awhile AssertEx.IsDocumentState(document, null, 1, 34, 89, 1007); RunUI(() => { SkylineWindow.SaveDocument(TestFilesDir.GetTestPath("local.sky")); // Avoid "document changed since last edit" message document = SkylineWindow.DocumentUI; }); var transitions = document.MoleculeTransitions.ToArray(); // Verify ability to extract predictions from raw data var peptideSettingsDlg = ShowDialog <PeptideSettingsUI>( () => SkylineWindow.ShowPeptideSettingsUI(PeptideSettingsUI.TABS.Prediction)); // Simulate user picking Add from the ion mobility Predictor combo control var driftTimePredictorDlg = ShowDialog <EditDriftTimePredictorDlg>(peptideSettingsDlg.AddDriftTimePredictor); RunUI(() => { driftTimePredictorDlg.SetOffsetHighEnergySpectraCheckbox(true); driftTimePredictorDlg.SetPredictorName("test_tims"); driftTimePredictorDlg.SetResolvingPower(40); driftTimePredictorDlg.GetDriftTimesFromResults(); driftTimePredictorDlg.OkDialog(true); // Force overwrite if a named predictor already exists }); WaitForClosedForm(driftTimePredictorDlg); RunUI(() => { peptideSettingsDlg.OkDialog(); }); WaitForClosedForm(peptideSettingsDlg); var docChangedDriftTimePredictor = WaitForDocumentChange(document); // Reimport data - should shift precursors RunDlg <ManageResultsDlg>(SkylineWindow.ManageResults, dlg => { var chromatograms = docChangedDriftTimePredictor.Settings.MeasuredResults.Chromatograms; dlg.SelectedChromatograms = new[] { chromatograms[0] }; dlg.ReimportResults(); dlg.OkDialog(); }); document = WaitForDocumentChangeLoaded(docChangedDriftTimePredictor); var transitionsNew = document.MoleculeTransitions.ToArray(); var nChanges = 0; var nNonEmpty = 0; for (var i = 0; i < transitions.Length; i++) { Assume.AreEqual(transitions[i].Mz, transitionsNew[i].Mz); if (transitions[i].AveragePeakArea.HasValue) { nNonEmpty++; if (transitions[i].AveragePeakArea != transitionsNew[i].AveragePeakArea) // Using filter should alter peak area { nChanges++; } } else { Assume.AreEqual(transitions[i].AveragePeakArea, transitionsNew[i].AveragePeakArea); } } Assume.IsTrue(nChanges >= nNonEmpty * .9); // We expect nearly all peaks to change in area with IMS filter in use // And read some mz5 converted from Bruker, then compare replicates - should be identical var mz5 = TestFilesDir.GetTestPath(bsaFmolTimsInfusionesiPrecMz5Mz5); ImportResultsFile(mz5); document = WaitForDocumentChange(document); foreach (var nodeGroup in document.MoleculeTransitionGroups) { Assume.AreEqual(2, nodeGroup.Results.Count); foreach (TransitionDocNode nodeTran in nodeGroup.Children) { Assume.AreEqual(2, nodeTran.Results.Count); Assume.AreEqual(nodeTran.Results[0], nodeTran.Results[1]); } } }
private void WatersImsMseChromatogramTest(DriftFilterType mode, IonMobilityWindowWidthCalculator.IonMobilityPeakWidthType driftPeakWidthCalcType, RefinementSettings.ConvertToSmallMoleculesMode asSmallMolecules = RefinementSettings.ConvertToSmallMoleculesMode.none) { if (asSmallMolecules != RefinementSettings.ConvertToSmallMoleculesMode.none && !RunSmallMoleculeTestVersions) { Console.Write(MSG_SKIPPING_SMALLMOLECULE_TEST_VERSION); return; } string subdir = (asSmallMolecules == RefinementSettings.ConvertToSmallMoleculesMode.none) ? null : asSmallMolecules.ToString(); var testFilesDir = new TestFilesDir(TestContext, ZIP_FILE, subdir); TestSmallMolecules = false; // Don't need that extra magic node bool withDriftTimePredictor = (mode == DriftFilterType.predictor); // Load the doc that has a drift time predictor? bool withDriftTimeFilter = (mode != DriftFilterType.none); // Perform drift time filtering? (either with predictor, or with bare times in blib file) string docPath; SrmDocument document = InitWatersImsMseDocument(testFilesDir, driftPeakWidthCalcType, withDriftTimeFilter, withDriftTimePredictor, out docPath); AssertEx.IsDocumentState(document, null, 1, 1, 1, 8); // Drift time lib load bumps the doc version, so does small mol conversion var listChromatograms = new List <ChromatogramSet>(); // A small subset of the QC_HDMSE_02_UCA168_3495_082213 data set (RT 21.5-22.5) from Will Thompson string mz5Path = "waters-mobility" + ExtensionTestContext.ExtMz5; string testModeStr = withDriftTimePredictor ? "with drift time predictor" : "without drift time info"; if (withDriftTimeFilter && !withDriftTimePredictor) { testModeStr = "with drift times from spectral library"; } listChromatograms.Add(AssertResult.FindChromatogramSet(document, new MsDataFilePath(mz5Path)) ?? new ChromatogramSet(Path.GetFileName(mz5Path).Replace('.', '_'), new[] { mz5Path })); using (var docContainer = new ResultsTestDocumentContainer(document, docPath)) { var doc = docContainer.Document; var docResults = doc.ChangeMeasuredResults(new MeasuredResults(listChromatograms)); Assume.IsTrue(docContainer.SetDocument(docResults, doc, true)); docContainer.AssertComplete(); document = docContainer.Document; } document = ConvertToSmallMolecules(document, ref docPath, new[] { mz5Path }, asSmallMolecules); using (var docContainer = new ResultsTestDocumentContainer(document, docPath)) { float tolerance = (float)document.Settings.TransitionSettings.Instrument.MzMatchTolerance; double maxHeight = 0; var results = document.Settings.MeasuredResults; Assume.AreEqual(1, document.MoleculePrecursorPairs.Count()); foreach (var pair in document.MoleculePrecursorPairs) { ChromatogramGroupInfo[] chromGroupInfo; Assume.IsTrue(results.TryLoadChromatogram(0, pair.NodePep, pair.NodeGroup, tolerance, true, out chromGroupInfo)); Assume.AreEqual(1, chromGroupInfo.Length, testModeStr); var chromGroup = chromGroupInfo[0]; int expectedPeaks; if (withDriftTimeFilter) { expectedPeaks = 3; } else if (asSmallMolecules != RefinementSettings.ConvertToSmallMoleculesMode.masses_only) { expectedPeaks = 5; } else { expectedPeaks = 6; // No libraries } Assume.AreEqual(expectedPeaks, chromGroup.NumPeaks, testModeStr); // This will be higher if we don't filter on DT foreach (var tranInfo in chromGroup.TransitionPointSets) { maxHeight = Math.Max(maxHeight, tranInfo.MaxIntensity); } } Assume.AreEqual(withDriftTimeFilter ? 5226 : 20075, maxHeight, 1, testModeStr); // Without DT filtering, this will be much greater // now drill down for specific values int nPeptides = 0; foreach (var nodePep in document.Molecules.Where(nodePep => !nodePep.Results[0].IsEmpty)) { // expecting just one peptide result in this small data set if (nodePep.Results[0].Sum(chromInfo => chromInfo.PeakCountRatio > 0 ? 1 : 0) > 0) { Assume.AreEqual(21.94865, (double)nodePep.GetMeasuredRetentionTime(0), .0001, testModeStr); Assume.AreEqual(1.0, (double)nodePep.GetPeakCountRatio(0), 0.0001, testModeStr); nPeptides++; } } Assume.AreEqual(1, nPeptides); if (withDriftTimePredictor || withDriftTimeFilter) { // Verify that the .imdb pr .blib file goes out in the share zipfile for (int complete = 0; complete <= 1; complete++) { var sharePath = testFilesDir.GetTestPath(complete == 1 ? "share_complete.zip" : "share_minimized.zip"); var share = new SrmDocumentSharing(document, docPath, sharePath, new ShareType(complete == 1, SkylineVersion.CURRENT)); // Explicitly declaring version number forces a save before zip share.Share(new SilentProgressMonitor()); var files = share.ListEntries().ToArray(); var imdbFile = withDriftTimePredictor ? "scaled.imdb" : "waters-mobility.filtered-scaled.blib"; if (asSmallMolecules != RefinementSettings.ConvertToSmallMoleculesMode.none) { var ext = "." + imdbFile.Split('.').Last(); imdbFile = imdbFile.Replace(ext, BiblioSpecLiteSpec.DotConvertedToSmallMolecules + ext); } Assume.IsTrue(files.Contains(imdbFile)); // And round trip it to make sure we haven't left out any new features in minimized imdb or blib files share.Extract(new SilentProgressMonitor()); using (var cmdline = new CommandLine()) { Assume.IsTrue(cmdline.OpenSkyFile(share.DocumentPath)); // Handles any path shifts in database files, like our .imdb file var document2 = cmdline.Document; Assume.IsNotNull(document2); Assume.IsTrue(docContainer.SetDocument(document2, docContainer.Document, true)); docContainer.AssertComplete(); document2 = docContainer.Document; var im = document2.Settings.GetIonMobilities(new MsDataFilePath(mz5Path)); var pep = document2.Molecules.First(); foreach (TransitionGroupDocNode nodeGroup in pep.Children) { double windowDT; var centerDriftTime = document2.Settings.GetIonMobility( pep, nodeGroup, null, im, null, driftTimeMax, out windowDT); Assume.AreEqual(3.86124, centerDriftTime.IonMobility.Mobility.Value, .0001, testModeStr); Assume.AreEqual(0.077224865797235934, windowDT, .0001, testModeStr); } } } } } }
protected override void DoTest() { var startPage = _showStartPage ? WaitForOpenForm <StartPage>() : null; var modeDlg = WaitForOpenForm <NoModeUIDlg>(); // Expect a dialog asking user to select a default UI mode RunUI(() => { modeDlg.SelectModeUI(SrmDocument.DOCUMENT_TYPE.small_molecules); modeDlg.ClickOk(); }); WaitForClosedForm(modeDlg); if (_showStartPage) { // ReSharper disable PossibleNullReferenceException Assert.AreEqual(SrmDocument.DOCUMENT_TYPE.small_molecules, startPage.GetModeUIHelper().GetUIToolBarButtonState()); // Verify that start page UI is updated Assert.IsFalse(startPage.GetVisibleBoxPanels().Where(c => c is ActionBoxControl).Any(c => ((ActionBoxControl)c).IsProteomicOnly)); RunUI(() => startPage.DoAction(skylineWindow => true)); // Start a new file // ReSharper restore PossibleNullReferenceException WaitForOpenForm <SkylineWindow>(); } // Verify that Skyline UI isn't showing anything proteomic Assert.AreEqual(SrmDocument.DOCUMENT_TYPE.small_molecules, SkylineWindow.GetModeUIHelper().GetUIToolBarButtonState()); Assert.IsFalse(SkylineWindow.HasProteomicMenuItems); RunUI(() => { SkylineWindow.SaveDocument(TestFilesDir.GetTestPath("blank.sky")); }); // Verify handling of start page invoked from Skyline menu with a populated document RunUI(() => SkylineWindow.OpenFile(TestFilesDir.GetTestPath("Proteomic.sky"))); Assert.IsTrue(SkylineWindow.HasProteomicMenuItems); startPage = ShowDialog <StartPage>(SkylineWindow.OpenStartPage); RunDlg <AlertDlg>(() => startPage.SetUIMode(SrmDocument.DOCUMENT_TYPE.small_molecules), alertDlg => alertDlg.ClickYes()); Assert.IsTrue(SkylineWindow.Document.MoleculeCount == 0); // Document should be empty RunUI(() => startPage.DoAction(skylineWindow => true)); // Close the start window Assert.IsFalse(SkylineWindow.HasProteomicMenuItems); if (!_showStartPage) { return; // No need to do the rest of this this twice } foreach (SrmDocument.DOCUMENT_TYPE uimode in Enum.GetValues(typeof(SrmDocument.DOCUMENT_TYPE))) { if (uimode == SrmDocument.DOCUMENT_TYPE.none) { continue; } // Loading a purely proteomic doc should change UI mode to straight up proteomic TestUIModesFileLoadAction(uimode, // Initial UI mode "Proteomic.sky", // Doc to be loaded SrmDocument.DOCUMENT_TYPE.proteomic); // Resulting UI mode // Loading a purely small mol doc should change UI mode to straight up small mol TestUIModesFileLoadAction(uimode, // Initial UI mode "SmallMol.sky", // Doc to be loaded SrmDocument.DOCUMENT_TYPE.small_molecules); // Resulting UI mode // Loading a mixed doc should change UI mode to mixed TestUIModesFileLoadAction(uimode, // Initial UI mode "Mixed.sky", // Doc to be loaded SrmDocument.DOCUMENT_TYPE.mixed); // Resulting UI mode // Loading an empty doc shouldn't have any effect on UI mode TestUIModesFileLoadAction(uimode, // Initial UI mode "blank.sky", // Doc to be loaded uimode); // Resulting UI mode // Test behavior in an empty document RunUI(() => { SkylineWindow.NewDocument(); SkylineWindow.SetUIMode(uimode); Assert.AreEqual(uimode, SkylineWindow.ModeUI); }); // Test per-ui-mode persistence of "peptide" settings tab choice var peptideSettingsDlg = ShowDialog <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI); RunUI(() => Assume.AreEqual(peptideSettingsDlg.SelectedTab, (PeptideSettingsUI.TABS)uimode)); OkDialog(peptideSettingsDlg, peptideSettingsDlg.CancelDialog); } TestPeptideToMoleculeText(); // Exercise the UI peptide->molecule translation code // Test interaction of buttons in non-empty documents TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.small_molecules, SrmDocument.DOCUMENT_TYPE.small_molecules, false); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.small_molecules, SrmDocument.DOCUMENT_TYPE.proteomic, true); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.small_molecules, SrmDocument.DOCUMENT_TYPE.mixed, false); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.proteomic, SrmDocument.DOCUMENT_TYPE.proteomic, false); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.proteomic, SrmDocument.DOCUMENT_TYPE.small_molecules, true); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.proteomic, SrmDocument.DOCUMENT_TYPE.mixed, false); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.mixed, SrmDocument.DOCUMENT_TYPE.mixed, false); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.mixed, SrmDocument.DOCUMENT_TYPE.small_molecules, true); TestUIModesClickAction(SrmDocument.DOCUMENT_TYPE.mixed, SrmDocument.DOCUMENT_TYPE.proteomic, true); // Verify operation of small-mol-only UI elements foreach (SrmDocument.DOCUMENT_TYPE uimode2 in Enum.GetValues(typeof(SrmDocument.DOCUMENT_TYPE))) { if (uimode2 == SrmDocument.DOCUMENT_TYPE.none) { continue; } RunUI(() => { SkylineWindow.NewDocument(); SkylineWindow.SetUIMode(uimode2); }); var peptideSettingsUI = ShowDialog <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI); Assert.AreEqual(uimode2 == SrmDocument.DOCUMENT_TYPE.small_molecules, peptideSettingsUI.SmallMoleculeLabelsTabEnabled); if (uimode2 == SrmDocument.DOCUMENT_TYPE.small_molecules) { // Verify operation of internal standard list edit RunUI(() => { peptideSettingsUI.SelectedTab = PeptideSettingsUI.TABS.Labels; }); } OkDialog(peptideSettingsUI, peptideSettingsUI.OkDialog); } }
public void TestAuditLogSerialization() { var datetime = AuditLogEntry.ParseSerializedTimeStamp("2019-01-01T05:02:03+04", out var tzoffset); // Accept ISO format, which may omit minutes in offset Assume.AreEqual(DateTimeKind.Utc, datetime.Kind); Assume.AreEqual(1, datetime.Hour); // Local time was 5AM, 4 hour offset to GMT. Assume.AreEqual(new TimeSpan(4, 0, 0), tzoffset); var xsd = AuditLogEntry.FormatSerializationString(datetime, tzoffset); Assume.AreEqual("2019-01-01T05:02:03+04:00", xsd); var zulu = AuditLogEntry.ParseSerializedTimeStamp("2019-01-01T01:02:03Z", out tzoffset); Assume.AreEqual(tzoffset, TimeSpan.Zero); Assume.AreEqual(datetime, zulu); AuditLogEntry.ParseSerializedTimeStamp("2019-01-01T01:02:03-04:30", out tzoffset); Assume.AreEqual(new TimeSpan(-4, -30, 0), tzoffset); datetime = AuditLogEntry.ParseSerializedTimeStamp("2018-12-31T23:02:03-04", out tzoffset); Assume.AreEqual(datetime, AuditLogEntry.ParseSerializedTimeStamp("2019-01-01T03:02:03Z", out tzoffset)); // Test backward compatibility - this file with 4.2 log should load without any problems Assume.IsTrue(AuditLogList.ReadFromXmlTextReader(new XmlTextReader(new StringReader(Test42FormatSkyl)), out var loggedSkylineDocumentHash, out var old)); Assume.AreEqual("tgnQ8fDiKLMIS236kpdJIXNR+fw=", old.RootHash.ActualHash.HashString); Assume.AreEqual("AjigWTmQeAO94/jAlwubVMp4FRg=", loggedSkylineDocumentHash); // Note that this is a base64 representation of the 4.2 hex representation "<document_hash>0238A05939907803BDE3F8C0970B9B54CA781518</document_hash> var then = DateTime.Parse("2019-03-08 00:02:03Z", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime(); // Just before DST const int entryCount = 20000; // Enough to ensure stack overflow in case of some design error per Nick var timestep = new TimeSpan(1, 0, 1); // 20000 hours should be sufficient to take us into and out of daylight savings twice AuditLogEntry headEntry = null; for (var index = 0; index++ < entryCount;) { var documentType = (SrmDocument.DOCUMENT_TYPE)(index % ((int)SrmDocument.DOCUMENT_TYPE.none + 1)); var entry = AuditLogEntry.CreateTestOnlyEntry(then, documentType, string.Empty); then += timestep; if (headEntry == null) { headEntry = entry; } else { headEntry = entry.ChangeParent(headEntry); } } Assert.IsNotNull(headEntry); Assert.AreEqual(entryCount, headEntry.Count); Assert.AreEqual(headEntry.Count, headEntry.Enumerate().Count()); var auditLogList = new AuditLogList(headEntry); var serializedAuditLog = new StringWriter(); var serializer = new XmlSerializer(typeof(AuditLogList)); serializer.Serialize(serializedAuditLog, auditLogList); var currentCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; // Logs are meant to be culture invariant var roundTrip = (AuditLogList)serializer.Deserialize(new StringReader(serializedAuditLog.ToString())); Assert.IsNotNull(roundTrip); Assert.AreEqual(auditLogList.AuditLogEntries.Count, roundTrip.AuditLogEntries.Count); var entries = auditLogList.AuditLogEntries.Enumerate().ToArray(); var roundtripEntries = roundTrip.AuditLogEntries.Enumerate().ToArray(); for (var i = 0; i < auditLogList.AuditLogEntries.Count; i++) { Assert.AreEqual(entries[i].TimeStampUTC, roundtripEntries[i].TimeStampUTC); Assert.AreEqual(entries[i].TimeZoneOffset, roundtripEntries[i].TimeZoneOffset); Assert.AreEqual(entries[i].SkylineVersion, roundtripEntries[i].SkylineVersion); Assert.AreEqual(entries[i].User, roundtripEntries[i].User); Assert.AreEqual(entries[i].DocumentType == SrmDocument.DOCUMENT_TYPE.proteomic ? SrmDocument.DOCUMENT_TYPE.none : entries[i].DocumentType, roundtripEntries[i].DocumentType); Assert.AreEqual(entries[i].Hash.ActualHash, roundtripEntries[i].Hash.ActualHash); // No Skyl hash until sserialized, so can't compare here } Thread.CurrentThread.CurrentCulture = currentCulture; // Make sure current system timezone isn't messing with us Assert.AreEqual(14, roundtripEntries[100].TimeStampUTC.Day); Assert.AreEqual(8, roundtripEntries[100].TimeStampUTC.Hour); Assert.AreEqual(27, roundtripEntries[10000].TimeStampUTC.Day); Assert.AreEqual(17, roundtripEntries[10000].TimeStampUTC.Hour); }
private void CheckDocumentGridAndColumns(string docName, string viewName, int rowCount, int colCount, // Expected row and column count for document grid SrmDocument.DOCUMENT_TYPE expectedDocumentType, string expectedProductIonFormula = null, string expectedFragmentIon = null, string expectedMolecularFormula = null, string expectedPrecursorNeutralFormula = null, string expectedPrecursorIonFormula = null) { var oldDoc = SkylineWindow.Document; OpenDocument(docName); WaitForDocumentChangeLoaded(oldDoc); Assume.AreEqual(expectedDocumentType, SkylineWindow.Document.DocumentType); WaitForClosedForm <DocumentGridForm>(); var documentGrid = ShowDialog <DocumentGridForm>(() => SkylineWindow.ShowDocumentGrid(true)); RunUI(() => documentGrid.ChooseView(viewName)); WaitForCondition(() => (documentGrid.RowCount == rowCount)); // Let it initialize int iteration = 0; WaitForCondition(() => { bool result = documentGrid.ColumnCount == colCount; if (!result && iteration++ > 9) { Assert.AreNotEqual(colCount, documentGrid.ColumnCount); // Put breakpoint on this line, if you have changed columns and need to update the numbers } return(result); }); // Let it initialize var colProductIonFormula = documentGrid.FindColumn(PropertyPath.Parse("ProductIonFormula")); var colProductNeutralFormula = documentGrid.FindColumn(PropertyPath.Parse("ProductNeutralFormula")); var colProductAdduct = documentGrid.FindColumn(PropertyPath.Parse("ProductAdduct")); var colFragmentIon = documentGrid.FindColumn(PropertyPath.Parse("FragmentIonType")); var colMoleculeFormula = documentGrid.FindColumn(PropertyPath.Parse("Precursor.Peptide.MoleculeFormula")); var colPrecursorNeutralFormula = documentGrid.FindColumn(PropertyPath.Parse("Precursor.NeutralFormula")); var colPrecursorIonFormula = documentGrid.FindColumn(PropertyPath.Parse("Precursor.IonFormula")); if (expectedProductIonFormula == null) { Assert.IsNull(colProductIonFormula); Assert.IsNull(colProductNeutralFormula); Assert.IsNull(colProductAdduct); } else { RunUI(() => { var formula = documentGrid.DataGridView.Rows[0].Cells[colProductIonFormula.Index].Value.ToString(); if (expectedProductIonFormula.Contains("[")) { var formulaNeutral = documentGrid.DataGridView.Rows[0].Cells[colProductNeutralFormula.Index].Value.ToString(); var adduct = documentGrid.DataGridView.Rows[0].Cells[colProductAdduct.Index].Value.ToString(); Assert.AreEqual(expectedProductIonFormula, formulaNeutral + adduct); } else { Assert.AreEqual(expectedProductIonFormula, formula); } if (!string.IsNullOrEmpty(expectedMolecularFormula)) { Assert.AreEqual(expectedMolecularFormula, documentGrid.DataGridView.Rows[0].Cells[colMoleculeFormula.Index].Value.ToString()); Assert.AreEqual(expectedPrecursorNeutralFormula, documentGrid.DataGridView.Rows[0].Cells[colPrecursorNeutralFormula.Index].Value.ToString()); Assert.AreEqual(expectedPrecursorIonFormula, documentGrid.DataGridView.Rows[0].Cells[colPrecursorIonFormula.Index].Value.ToString()); } }); } if (expectedFragmentIon == null) { Assert.IsNull(colFragmentIon); } else { RunUI(() => { var frag = documentGrid.DataGridView.Rows[0].Cells[colFragmentIon.Index].Value.ToString(); Assert.AreEqual(expectedFragmentIon, frag); }); } RunUI(() => documentGrid.Close()); }