protected override void DoTest() { // IsPauseForScreenShots = true; // For a quick demo when you need it string skyFile = TestFilesDir.GetTestPath("test_measured_drift_times_perf.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, 38, 398); RunUI(() => { SkylineWindow.SaveDocument(TestFilesDir.GetTestPath("local.sky")); // Avoid "document changed since last edit" message document = SkylineWindow.DocumentUI; }); List <ValidatingIonMobilityPrecursor> curatedDTs = null; var measuredDTs = new List <List <ValidatingIonMobilityPrecursor> >(); var precursors = new LibKeyIndex(document.MoleculePrecursorPairs.Select( p => p.NodePep.ModifiedTarget.GetLibKey(p.NodeGroup.PrecursorAdduct).LibraryKey)); PauseForScreenShot(@"Legacy ion mobility values loaded, placed in .imsdb database file"); // For a quick demo when you need it for (var pass = 0; pass < 2; pass++) { // Verify ability to extract predictions from raw data var transitionSettingsDlg = ShowDialog <TransitionSettingsUI>( () => SkylineWindow.ShowTransitionSettingsUI(TransitionSettingsUI.TABS.IonMobility)); PauseForScreenShot("new Transition Settings tab"); // For a quick demo when you need it // Simulate user picking Edit Current from the Ion Mobility Library combo control var ionMobilityLibraryDlg = ShowDialog <EditIonMobilityLibraryDlg>(transitionSettingsDlg.IonMobilityControl.EditIonMobilityLibrary); PauseForScreenShot("next, we'll update values with 'Use Results' button"); // For a quick demo when you need it RunUI(() => { if (curatedDTs == null) { curatedDTs = ionMobilityLibraryDlg.LibraryMobilitiesFlat.ToList(); } ionMobilityLibraryDlg.SetOffsetHighEnergySpectraCheckbox(true); ionMobilityLibraryDlg.GetIonMobilitiesFromResults(); }); PauseForScreenShot("values updated");// For a quick demo when you need it RunUI(() => { measuredDTs.Add(ionMobilityLibraryDlg.LibraryMobilitiesFlat.ToList()); ionMobilityLibraryDlg.OkDialog(); }); WaitForClosedForm(ionMobilityLibraryDlg); RunUI(() => { transitionSettingsDlg.OkDialog(); }); WaitForClosedForm(transitionSettingsDlg); document = SkylineWindow.Document; var count = 0; for (var n = 0; n < curatedDTs.Count; n++) { var cdt = curatedDTs[n]; var key = cdt.Precursor; var indexM = measuredDTs[pass].FindIndex(m => m.Precursor.Equals(key)); var measured = measuredDTs[pass][indexM]; var measuredDT = measured.IonMobility; var measuredHEO = measured.HighEnergyIonMobilityOffset; if (precursors.ItemsMatching(key, true).Any()) { count++; AssertEx.AreNotEqual(cdt.IonMobility, measuredDT, "measured drift time should differ somewhat for " + measured.Precursor); } AssertEx.AreEqual(cdt.IonMobility, measuredDT, 1.0, "measured drift time differs too much for " + key); AssertEx.AreEqual(cdt.HighEnergyIonMobilityOffset, measuredHEO, 2.0, "measured drift time high energy offset differs too much for " + key); } AssertEx.AreEqual(document.MoleculeTransitionGroupCount, count, "did not find drift times for all precursors"); // Expect to find a value for each precursor if (pass == 1) { break; } // Verify that we select based on strongest results by removing the training set and relying on the other noisier set RunDlg <ManageResultsDlg>(SkylineWindow.ManageResults, dlg => { var chromatograms = document.Settings.MeasuredResults.Chromatograms; var chromTraining = chromatograms[0]; var chroms = new[] { chromTraining }; dlg.SelectedChromatograms = chroms; // Passing this chromatograms[0] results in the other set being deleted - compiler problem? dlg.RemoveReplicates(); dlg.OkDialog(); }); document = WaitForDocumentChange(document); AssertEx.AreEqual(1, document.Settings.MeasuredResults.Chromatograms.Count); } // Results should be slightly different without the training set of chromatograms to contain a potentially stronger peak var ccount = 0; var noChange = new List <LibKey>(); for (var n = 0; n < measuredDTs[0].Count; n++) { var validatingIonMobilityPeptide0 = measuredDTs[0][n]; var validatingIonMobilityPeptide1 = measuredDTs[1][n]; var key = measuredDTs[0][n].Precursor; if (precursors.ItemsMatching(key, true).Any()) { ccount++; if (validatingIonMobilityPeptide0.HighEnergyIonMobilityOffset == validatingIonMobilityPeptide1.HighEnergyIonMobilityOffset) { noChange.Add(key); } } AssertEx.AreEqual(validatingIonMobilityPeptide0.IonMobility, validatingIonMobilityPeptide1.IonMobility, 1.0, "averaged measured drift time differs for " + key); AssertEx.AreEqual(validatingIonMobilityPeptide0.HighEnergyIonMobilityOffset, validatingIonMobilityPeptide1.HighEnergyIonMobilityOffset, 2.0, "averaged measured drift time high energy offset differs for " + key); AssertEx.AreEqual(validatingIonMobilityPeptide0.CollisionalCrossSectionSqA, validatingIonMobilityPeptide1.CollisionalCrossSectionSqA, 1.0, "averaged measured CCS differs for " + key); } AssertEx.AreEqual(document.MoleculeTransitionGroupCount, ccount, "did not find drift times for all precursors"); // Expect to find a value for each precursor AssertEx.IsTrue(noChange.Count < ccount / 2, "expected most values to shift a little without the nice clean training data"); // And finally verify ability to reimport with altered drift filter (would formerly fail on an erroneous Assume) // Simulate user picking Edit Current from the Ion Mobility Library combo control, and messing with all the measured drift time values var transitionSettingsDlg2 = ShowDialog <TransitionSettingsUI>( () => SkylineWindow.ShowTransitionSettingsUI(TransitionSettingsUI.TABS.Prediction)); var editIonMobilityLibraryDlg = ShowDialog <EditIonMobilityLibraryDlg>(transitionSettingsDlg2.IonMobilityControl.EditIonMobilityLibrary); RunUI(() => { var revised = new List <ValidatingIonMobilityPrecursor>(); foreach (var item in editIonMobilityLibraryDlg.LibraryMobilitiesFlat) { var im = item.IonMobility; var heo = item.HighEnergyIonMobilityOffset; revised.Add(new ValidatingIonMobilityPrecursor(item.Precursor, IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(im * 1.02, item.IonMobilityUnits), item.CollisionalCrossSectionSqA * 1.02, heo * 1.02))); } editIonMobilityLibraryDlg.LibraryMobilitiesFlat = revised; editIonMobilityLibraryDlg.OkDialog(); }); WaitForClosedForm(editIonMobilityLibraryDlg); RunUI(() => { transitionSettingsDlg2.OkDialog(); }); WaitForClosedForm(transitionSettingsDlg2); var docChangedDriftTimePredictor = WaitForDocumentChange(document); // Reimport data for a replicate - without the fix this will throw RunDlg <ManageResultsDlg>(SkylineWindow.ManageResults, dlg => { var chromatograms = docChangedDriftTimePredictor.Settings.MeasuredResults.Chromatograms; dlg.SelectedChromatograms = new[] { chromatograms[0] }; dlg.ReimportResults(); dlg.OkDialog(); }); WaitForDocumentChangeLoaded(docChangedDriftTimePredictor, WAIT_TIME * 2); }
private void EvaluateBestIonMobilityValue(int msLevel, LibKey libKey, float tolerance, List <TransitionFullScanInfo> transitions) { IonMobilityValue ionMobilityValue = IonMobilityValue.EMPTY; double maxIntensity = 0; // Avoid picking MS2 ion mobility values wildly different from MS1 valuess IonMobilityValue ms1IonMobilityBest; if ((msLevel == 2) && _ms1IonMobilities.ContainsKey(libKey)) { ms1IonMobilityBest = _ms1IonMobilities[libKey].OrderByDescending(p => p.Intensity) .FirstOrDefault() .IonMobility.IonMobility; } else { ms1IonMobilityBest = IonMobilityValue.EMPTY; } const int maxHighEnergyDriftOffsetMsec = 2; // CONSIDER(bspratt): user definable? or dynamically set by looking at scan to scan drift delta? Or resolving power? foreach (var scan in _msDataFileScanHelper.MsDataSpectra.Where(scan => scan != null)) { if (!scan.IonMobility.HasValue || !scan.Mzs.Any()) { continue; } if (ms1IonMobilityBest.HasValue && (scan.IonMobility.Mobility < ms1IonMobilityBest.Mobility - maxHighEnergyDriftOffsetMsec || scan.IonMobility.Mobility > ms1IonMobilityBest.Mobility + maxHighEnergyDriftOffsetMsec)) { continue; } // Get the total intensity for all transitions of current msLevel double totalIntensity = 0; foreach (var t in transitions) { Assume.IsTrue(t.ProductMz.IsNegative == scan.NegativeCharge); // It would be strange if associated scan did not have same polarity var mzPeak = t.ProductMz; var halfwin = (t.ExtractionWidth ?? tolerance) / 2; var mzLow = mzPeak - halfwin; var mzHigh = mzPeak + halfwin; var first = Array.BinarySearch(scan.Mzs, mzLow); if (first < 0) { first = ~first; } for (var i = first; i < scan.Mzs.Length; i++) { if (scan.Mzs[i] > mzHigh) { break; } totalIntensity += scan.Intensities[i]; } } if (maxIntensity < totalIntensity) { ionMobilityValue = scan.IonMobility; maxIntensity = totalIntensity; } } if (ionMobilityValue.HasValue) { var dict = (msLevel == 1) ? _ms1IonMobilities : _ms2IonMobilities; var ccs = msLevel == 1 && _msDataFileScanHelper.ProvidesCollisionalCrossSectionConverter ? _msDataFileScanHelper.CCSFromIonMobility(ionMobilityValue, transitions.First().PrecursorMz, libKey.Charge) : null; var result = new IonMobilityIntensityPair { IonMobility = IonMobilityAndCCS.GetIonMobilityAndCCS(ionMobilityValue, ccs, 0), Intensity = maxIntensity }; List <IonMobilityIntensityPair> listPairs; if (!dict.TryGetValue(libKey, out listPairs)) { listPairs = new List <IonMobilityIntensityPair>(); dict.Add(libKey, listPairs); } listPairs.Add(result); } }
/// <summary> /// Looks through the result and finds ion mobility values. /// Note that this method only returns new values that were found in results. /// The returned dictionary should be merged with the existing values in /// order to preserve those existing values. /// </summary> public Dictionary <LibKey, IonMobilityAndCCS> FindIonMobilityPeaks() { // Overwrite any existing measurements with newly derived ones var measured = new Dictionary <LibKey, IonMobilityAndCCS>(); if (_document.Settings.MeasuredResults == null) { return(measured); } var filepaths = _document.Settings.MeasuredResults.MSDataFilePaths.ToArray(); _totalSteps = filepaths.Length * _document.MoleculeTransitionGroupCount; if (_totalSteps == 0) { return(measured); } using (_msDataFileScanHelper = new MsDataFileScanHelper(SetScans, HandleLoadScanException)) { // // Avoid opening and re-opening raw files - make these the outer loop // _ms1IonMobilities = new Dictionary <LibKey, List <IonMobilityIntensityPair> >(); _ms2IonMobilities = new Dictionary <LibKey, List <IonMobilityIntensityPair> >(); var twopercent = (int)Math.Ceiling(_totalSteps * 0.02); _totalSteps += twopercent; _currentStep = twopercent; if (_progressMonitor != null) { _progressStatus = new ProgressStatus(filepaths.First().GetFileName()); _progressStatus = _progressStatus.UpdatePercentCompleteProgress(_progressMonitor, _currentStep, _totalSteps); // Make that inital lag seem less dismal to the user } foreach (var fp in filepaths) { if (!ProcessFile(fp)) { return(null); // User cancelled } } // Find ion mobilitiess based on MS1 data foreach (var dt in _ms1IonMobilities) { // Choose the ion mobility which gave the largest signal // CONSIDER: average IM and CCS values that fall "near" the IM of largest signal? var ms1IonMobility = dt.Value.OrderByDescending(p => p.Intensity).First().IonMobility; // Check for MS2 data to use for high energy offset List <IonMobilityIntensityPair> listDt; var ms2IonMobility = _ms2IonMobilities.TryGetValue(dt.Key, out listDt) ? listDt.OrderByDescending(p => p.Intensity).First().IonMobility : ms1IonMobility; var value = IonMobilityAndCCS.GetIonMobilityAndCCS(ms1IonMobility.IonMobility, ms1IonMobility.CollisionalCrossSectionSqA, ms2IonMobility.IonMobility.Mobility.Value - ms1IonMobility.IonMobility.Mobility.Value); if (!measured.ContainsKey(dt.Key)) { measured.Add(dt.Key, value); } else { measured[dt.Key] = value; } } // Check for data for which we have only MS2 to go on foreach (var im in _ms2IonMobilities) { if (!_ms1IonMobilities.ContainsKey(im.Key)) { // Only MS2 ion mobility values found, use that var driftTimeIntensityPair = im.Value.OrderByDescending(p => p.Intensity).First(); var value = driftTimeIntensityPair.IonMobility; // Note collisional cross section if (_msDataFileScanHelper.ProvidesCollisionalCrossSectionConverter) { var ccs = _msDataFileScanHelper.CCSFromIonMobility(value.IonMobility, im.Key.PrecursorMz.Value, im.Key.Charge); if (ccs.HasValue) { value = IonMobilityAndCCS.GetIonMobilityAndCCS(value.IonMobility, ccs, value.HighEnergyIonMobilityValueOffset); } } if (!measured.ContainsKey(im.Key)) { measured.Add(im.Key, value); } else { measured[im.Key] = value; } } } } return(measured); }
public Dictionary <LibKey, IonMobilityAndCCS> GetTableMeasuredIonMobility(bool useHighEnergyOffsets, eIonMobilityUnits units) { var e = new CancelEventArgs(); var dict = new Dictionary <LibKey, IonMobilityAndCCS>(); foreach (DataGridViewRow row in _gridMeasuredDriftTimePeptides.Rows) { if (row.IsNewRow) { continue; } string seq; if (!ValidateSequence(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_SEQUENCE], out seq)) { return(null); } // OK, we have a non-empty "sequence" string, but is that actually a peptide or a molecule? // See if there's anything in the document whose text representation matches what's in the list var target = _targetResolver.ResolveTarget(seq); if (target == null || target.IsEmpty) { return(null); } Adduct charge; if (!ValidateCharge(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_CHARGE], target.IsProteomic, out charge)) { return(null); } double mobility; if (!ValidateDriftTime(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_ION_MOBILITY], out mobility)) { return(null); } double?ccs; if (!ValidateCCS(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_CCS], out ccs)) { return(null); } double highEnergyOffset = 0; // Set default value in case user does not provide one if (useHighEnergyOffsets && !ValidateHighEnergyDriftTimeOffset(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_HIGH_ENERGY_OFFSET], out highEnergyOffset)) { return(null); } var ionMobility = IonMobilityValue.GetIonMobilityValue(mobility, units); try { dict.Add(new LibKey(target, charge), IonMobilityAndCCS.GetIonMobilityAndCCS(ionMobility, ccs, highEnergyOffset)); } // ReSharper disable once EmptyGeneralCatchClause catch { // just take the first seen } } return(dict); }
private void PerformTestMeasuredDriftValues(bool asSmallMolecules) { if (asSmallMolecules) { if (!RunSmallMoleculeTestVersions) { Console.Write(MSG_SKIPPING_SMALLMOLECULE_TEST_VERSION); return; } TestSmallMolecules = false; // No need to add the magic small molecule test node } var testFilesDir = new TestFilesDir(TestContext, @"Test\Results\BlibDriftTimeTest.zip"); // Re-used from BlibDriftTimeTest // Open document with some peptides but no results var docPath = testFilesDir.GetTestPath("BlibDriftTimeTest.sky"); // This was a malformed document, which caused problems after a fix to not recalculate // document library settings on open. To avoid rewriting this test for the document // which now contains 2 precursors, the first precursor is removed immediately. SrmDocument docOriginal = ResultsUtil.DeserializeDocument(docPath); var pathFirstPeptide = docOriginal.GetPathTo((int)SrmDocument.Level.Molecules, 0); var nodeFirstPeptide = (DocNodeParent)docOriginal.FindNode(pathFirstPeptide); docOriginal = (SrmDocument)docOriginal.RemoveChild(pathFirstPeptide, nodeFirstPeptide.Children[0]); if (asSmallMolecules) { var refine = new RefinementSettings(); docOriginal = refine.ConvertToSmallMolecules(docOriginal, testFilesDir.FullPath); } using (var docContainer = new ResultsTestDocumentContainer(docOriginal, docPath)) { var doc = docContainer.Document; // Import an mz5 file that contains drift info const string replicateName = "ID12692_01_UCA168_3727_040714"; var chromSets = new[] { new ChromatogramSet(replicateName, new[] { new MsDataFilePath(testFilesDir.GetTestPath("ID12692_01_UCA168_3727_040714.mz5")), }), }; var docResults = doc.ChangeMeasuredResults(new MeasuredResults(chromSets)); Assert.IsTrue(docContainer.SetDocument(docResults, docOriginal, true)); docContainer.AssertComplete(); var document = docContainer.Document; document = document.ChangeSettings(document.Settings.ChangePeptidePrediction(prediction => new PeptidePrediction(null, IonMobilityPredictor.EMPTY))); // Verify ability to extract predictions from raw data var newPred = document.Settings.PeptideSettings.Prediction.IonMobilityPredictor.ChangeMeasuredIonMobilityValuesFromResults( document, docContainer.DocumentFilePath); var result = newPred.MeasuredMobilityIons; Assert.AreEqual(TestSmallMolecules ? 2 : 1, result.Count); const double expectedDT = 4.0019; var expectedOffset = .4829; Assert.AreEqual(expectedDT, result.Values.First().IonMobility.Mobility.Value, .001); Assert.AreEqual(expectedOffset, result.Values.First().HighEnergyIonMobilityValueOffset, .001); // Check ability to update, and to preserve unchanged var revised = new Dictionary <LibKey, IonMobilityAndCCS>(); var libKey = result.Keys.First(); revised.Add(libKey, IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(4, MsDataFileImpl.eIonMobilityUnits.drift_time_msec), null, 0.234)); // N.B. CCS handling would require actual raw data in this test, it's covered in a perf test var libKey2 = new LibKey("DEADEELS", asSmallMolecules ? Adduct.NonProteomicProtonatedFromCharge(2) : Adduct.DOUBLY_PROTONATED); revised.Add(libKey2, IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(5, MsDataFileImpl.eIonMobilityUnits.drift_time_msec), null, 0.123)); document = document.ChangeSettings( document.Settings.ChangePeptidePrediction(prediction => new PeptidePrediction(null, new IonMobilityPredictor("test", revised, null, null, IonMobilityWindowWidthCalculator.IonMobilityPeakWidthType.resolving_power, 40, 0, 0)))); newPred = document.Settings.PeptideSettings.Prediction.ChangeDriftTimePredictor( document.Settings.PeptideSettings.Prediction.IonMobilityPredictor.ChangeMeasuredIonMobilityValuesFromResults( document, docContainer.DocumentFilePath)).IonMobilityPredictor; result = newPred.MeasuredMobilityIons; Assert.AreEqual(TestSmallMolecules ? 3 : 2, result.Count); Assert.AreEqual(expectedDT, result[libKey].IonMobility.Mobility.Value, .001); Assert.AreEqual(expectedOffset, result[libKey].HighEnergyIonMobilityValueOffset, .001); Assert.AreEqual(5, result[libKey2].IonMobility.Mobility.Value, .001); Assert.AreEqual(0.123, result[libKey2].HighEnergyIonMobilityValueOffset, .001); } }
private void ProcessTransitionGroup(IDictionary <LibKey, SpectrumMzInfo> spectra, PeptideGroupDocNode nodePepGroup, PeptideDocNode nodePep, TransitionGroupDocNode nodeTranGroup, int replicateIndex) { LibKey key; if (nodePep.IsProteomic) { var sequence = Document.Settings.GetPrecursorCalc(nodeTranGroup.TransitionGroup.LabelType, nodePep.ExplicitMods) .GetModifiedSequence(nodePep.Peptide.Target, SequenceModFormatType.lib_precision, false); key = new LibKey(sequence, nodeTranGroup.PrecursorAdduct.AdductCharge); } else { // For small molecules, the "modification" is expressed in the adduct key = new LibKey(nodeTranGroup.CustomMolecule.GetSmallMoleculeLibraryAttributes(), nodeTranGroup.PrecursorAdduct); } var mi = new List <SpectrumPeaksInfo.MI>(); var rt = 0.0; var im = IonMobilityAndCCS.EMPTY; var imGroup = TransitionGroupIonMobilityInfo.EMPTY; // CCS may be available only at group level var groupChromInfos = nodeTranGroup.GetSafeChromInfo(replicateIndex); if (!groupChromInfos.IsEmpty) { var chromInfo = groupChromInfos.First(info => info.OptimizationStep == 0); imGroup = chromInfo.IonMobilityInfo; } var maxApex = float.MinValue; var maxApexMs1 = float.MinValue; string chromFileName = null; double?mobilityMs1 = null; // Track MS1 ion mobility in order to derive high energy ion mobility offset value foreach (var nodeTran in nodeTranGroup.Transitions) { var chromInfos = nodeTran.GetSafeChromInfo(replicateIndex); if (chromInfos.IsEmpty) { continue; } var chromInfo = chromInfos.First(info => info.OptimizationStep == 0); if (chromInfo.Area == 0) { continue; } if (nodeTran.IsMs1) { // Track MS1 ion mobility in order to derive high energy ion mobility offset value if (chromInfo.Height > maxApexMs1) { maxApexMs1 = chromInfo.Height; mobilityMs1 = chromInfo.IonMobility.IonMobility.Mobility; } continue; } if (chromFileName == null) { var chromFileInfo = Document.Settings.MeasuredResults.Chromatograms[replicateIndex].MSDataFileInfos.FirstOrDefault(file => ReferenceEquals(file.Id, chromInfo.FileId)); if (chromFileInfo != null) { chromFileName = chromFileInfo.FilePath.GetFileName(); } } List <SpectrumPeakAnnotation> annotations = null; if (nodeTran.Transition.IsNonReporterCustomIon()) // CONSIDER(bspratt) include annotation for all non-peptide-fragment transitions? { var smallMoleculeLibraryAttributes = nodeTran.Transition.CustomIon.GetSmallMoleculeLibraryAttributes(); var ion = new CustomIon(smallMoleculeLibraryAttributes, nodeTran.Transition.Adduct, nodeTran.GetMoleculeMass()); annotations = new List <SpectrumPeakAnnotation> { SpectrumPeakAnnotation.Create(ion, nodeTran.Annotations.Note) }; } mi.Add(new SpectrumPeaksInfo.MI { Mz = nodeTran.Mz, Intensity = chromInfo.Area, Quantitative = nodeTran.ExplicitQuantitative, Annotations = annotations }); if (chromInfo.Height > maxApex) { maxApex = chromInfo.Height; rt = chromInfo.RetentionTime; var mobility = chromInfo.IonMobility.IonMobility; var mobilityHighEnergyOffset = 0.0; if (mobilityMs1.HasValue && mobility.HasValue && mobility.Mobility != mobilityMs1) { // Note any difference in MS1 and MS2 ion mobilities - the "high energy ion mobility offset" mobilityHighEnergyOffset = mobility.Mobility.Value - mobilityMs1.Value; mobility = mobility.ChangeIonMobility(mobilityMs1); } im = IonMobilityAndCCS.GetIonMobilityAndCCS(mobility, chromInfo.IonMobility.CollisionalCrossSectionSqA ?? imGroup.CollisionalCrossSection, mobilityHighEnergyOffset); } } if (chromFileName == null) { return; } SpectrumMzInfo spectrumMzInfo; if (!spectra.TryGetValue(key, out spectrumMzInfo)) { spectrumMzInfo = new SpectrumMzInfo { SourceFile = DocumentFilePath, Key = key, PrecursorMz = nodeTranGroup.PrecursorMz, SpectrumPeaks = new SpectrumPeaksInfo(mi.ToArray()), RetentionTimes = new List <SpectrumMzInfo.IonMobilityAndRT>(), IonMobility = im, Protein = nodePepGroup.Name, RetentionTime = rt }; spectra[key] = spectrumMzInfo; } var isBest = replicateIndex == nodePep.BestResult; if (isBest) { spectrumMzInfo.IonMobility = im; spectrumMzInfo.RetentionTime = rt; } spectrumMzInfo.RetentionTimes.Add(new SpectrumMzInfo.IonMobilityAndRT(chromFileName, im, rt, isBest)); }
public void TestLibIonMobilityInfo() { const string caffeineFormula = "C8H10N4O2"; const string caffeineInChiKey = "RYYVLZVUVIJVGH-UHFFFAOYSA-N"; const string caffeineHMDB = "HMDB01847"; const double HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC = -.01; var dbIon1 = new DbIonMobilityPeptide(new Target("JKLMN"), Adduct.SINGLY_PROTONATED, 1.2, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) { Id = 12345 }; for (var loop = 0; loop < 2; loop++) { var dbIon2 = new DbIonMobilityPeptide(dbIon1); DbIonMobilityPeptide dbIon3 = null; Assert.AreEqual(dbIon1.GetHashCode(), dbIon2.GetHashCode()); Assert.IsFalse(dbIon1.Equals(null)); Assert.IsTrue(dbIon1.Equals(dbIon2 as object)); // ReSharper disable once ExpressionIsAlwaysNull Assert.IsFalse(dbIon1.Equals(dbIon3 as object)); Assert.IsTrue(dbIon1.Equals(dbIon1)); Assert.IsTrue(dbIon1.Equals(dbIon1 as object)); Assert.IsTrue(dbIon1.Equals(dbIon2)); dbIon1.CollisionalCrossSection = 1.3; Assert.AreNotEqual(dbIon1.CollisionalCrossSection, dbIon2.CollisionalCrossSection); if (loop == 1) { dbIon1.ModifiedTarget = new Target("foo"); Assert.AreNotEqual(dbIon1.Target, dbIon2.Target); Assert.AreNotEqual(dbIon1.ModifiedTarget, dbIon2.ModifiedTarget); } else { Assert.AreEqual(dbIon1.ModifiedTarget, dbIon2.ModifiedTarget); Assert.AreEqual(dbIon1.ModifiedTarget.Molecule, dbIon2.ModifiedTarget.Molecule); } dbIon1 = new DbIonMobilityPeptide( SmallMoleculeLibraryAttributes.Create("caffeine", caffeineFormula, caffeineInChiKey, caffeineHMDB), Adduct.FromStringAssumeProtonated("M+Na"), 1.2, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) { Id = 12345 }; } var dictCCS1 = new Dictionary <LibKey, IonMobilityAndCCS[]>(); var ccs1 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 1, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 2, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Collisional cross sections var ccs2 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 3, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 4, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Collisional cross sections const string seq1 = "JKLM"; const string seq2 = "KLMN"; dictCCS1.Add(new LibKey(seq1, 1), ccs1.ToArray()); dictCCS1.Add(new LibKey(seq2, 1), ccs2.ToArray()); var lib = new List <LibraryIonMobilityInfo> { new LibraryIonMobilityInfo("test", dictCCS1) }; var peptideTimes = CollisionalCrossSectionGridViewDriver.ConvertDriftTimesToCollisionalCrossSections(null, lib, 1, null); var validatingIonMobilityPeptides = peptideTimes as ValidatingIonMobilityPeptide[] ?? peptideTimes.ToArray(); Assert.AreEqual(2, validatingIonMobilityPeptides.Length); Assert.AreEqual(1.5, validatingIonMobilityPeptides[0].CollisionalCrossSection); Assert.AreEqual(3.5, validatingIonMobilityPeptides[1].CollisionalCrossSection); Assert.AreEqual(HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC, validatingIonMobilityPeptides[1].HighEnergyDriftTimeOffsetMsec); // Test serialization of molecule with '$' in it, which we use as a tab replacement against XML parser variability var molser = new CustomMolecule(SmallMoleculeLibraryAttributes.Create("caffeine$", caffeineFormula, caffeineInChiKey, caffeineHMDB)); var text = molser.ToSerializableString(); Assert.AreEqual(molser, CustomMolecule.FromSerializableString(text)); var dictCCS2 = new Dictionary <LibKey, IonMobilityAndCCS[]>(); var ccs3 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(4, eIonMobilityUnits.drift_time_msec), null, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(5, eIonMobilityUnits.drift_time_msec), null, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Drift times const string seq3 = "KLMNJ"; dictCCS2.Add(new LibKey(seq3, Adduct.SINGLY_PROTONATED), ccs3.ToArray()); lib.Add(new LibraryIonMobilityInfo("test2", dictCCS2)); List <LibraryIonMobilityInfo> lib1 = lib; AssertEx.ThrowsException <Exception>(() => CollisionalCrossSectionGridViewDriver.ConvertDriftTimesToCollisionalCrossSections(null, lib1, 2, null), String.Format( Resources.CollisionalCrossSectionGridViewDriver_ProcessIonMobilityValues_Cannot_import_measured_ion_mobility_for_sequence__0___no_collisional_cross_section_conversion_parameters_were_provided_for_charge_state__1__, seq3, 1)); var regressions = new Dictionary <int, RegressionLine> { { 1, new RegressionLine(2, 1) } }; lib = new List <LibraryIonMobilityInfo> { new LibraryIonMobilityInfo("test", dictCCS2) }; peptideTimes = CollisionalCrossSectionGridViewDriver.ConvertDriftTimesToCollisionalCrossSections(null, lib, 1, regressions); validatingIonMobilityPeptides = peptideTimes as ValidatingIonMobilityPeptide[] ?? peptideTimes.ToArray(); Assert.AreEqual(1, validatingIonMobilityPeptides.Length); Assert.AreEqual(1.75, validatingIonMobilityPeptides[0].CollisionalCrossSection); }
public void TestLibIonMobilityInfo() { const string caffeineFormula = "C8H10N4O2"; const string caffeineInChiKey = "RYYVLZVUVIJVGH-UHFFFAOYSA-N"; const string caffeineHMDB = "HMDB01847"; const double HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC = -.01; var dbMolecule = new DbMolecule(new Target("JKLMN")) { Id = 123456 }; var dbPrecursorIon = new DbPrecursorIon(dbMolecule, Adduct.SINGLY_PROTONATED) { Id = 1234567 }; var dbIonMobilityValue = new DbPrecursorAndIonMobility(dbPrecursorIon, 1.2, 2.3, eIonMobilityUnits.drift_time_msec, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) { Id = 12345 }; DbPrecursorAndIonMobility dbPrecursorAndIonMobilityValue2 = new DbPrecursorAndIonMobility(dbIonMobilityValue); for (var loop = 0; loop < 2; loop++) { Assert.AreEqual(dbIonMobilityValue.GetHashCode(), dbPrecursorAndIonMobilityValue2.GetHashCode()); Assert.IsFalse(dbIonMobilityValue.Equals(null)); Assert.IsTrue(dbIonMobilityValue.Equals(dbPrecursorAndIonMobilityValue2 as object)); Assert.IsTrue(dbIonMobilityValue.Equals(dbIonMobilityValue)); Assert.IsTrue(dbIonMobilityValue.Equals(dbIonMobilityValue as object)); Assert.IsTrue(dbPrecursorAndIonMobilityValue2.Equals(dbIonMobilityValue)); dbIonMobilityValue.CollisionalCrossSectionSqA = 1.3; Assert.AreNotEqual(dbIonMobilityValue.CollisionalCrossSectionSqA, dbPrecursorAndIonMobilityValue2.CollisionalCrossSectionSqA); if (loop == 1) { dbIonMobilityValue.DbPrecursorIon = new DbPrecursorIon(new Target("foo"), Adduct.SINGLY_PROTONATED) { Id = 1234567 }; Assert.AreNotEqual(dbIonMobilityValue.DbPrecursorIon.GetTarget(), dbMolecule); } else { Assert.AreEqual(dbIonMobilityValue.DbPrecursorIon.DbMolecule, dbMolecule); } dbIonMobilityValue = new DbPrecursorAndIonMobility( new DbPrecursorIon( SmallMoleculeLibraryAttributes.Create("caffeine", caffeineFormula, caffeineInChiKey, caffeineHMDB), Adduct.FromStringAssumeProtonated("M+Na")) { Id = 23456 }, 1.2, 2.3, eIonMobilityUnits.drift_time_msec, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) { Id = 12345 }; dbPrecursorAndIonMobilityValue2 = new DbPrecursorAndIonMobility(dbIonMobilityValue); } var dictCCS1 = new Dictionary <LibKey, IonMobilityAndCCS[]>(); var im = IonMobilityValue.GetIonMobilityValue(12, eIonMobilityUnits.drift_time_msec); var ccs1 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 1, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 2, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Collisional cross sections var ccs2 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(im, 3, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.EMPTY, 4, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Collisional cross sections const string seq1 = "JKLM"; const string seq2 = "KLMN"; dictCCS1.Add(new LibKey(seq1, 1), ccs1.ToArray()); dictCCS1.Add(new LibKey(seq2, 1), ccs2.ToArray()); var lib = new List <LibraryIonMobilityInfo> { new LibraryIonMobilityInfo("test", false, dictCCS1) }; var peptideTimes = CollisionalCrossSectionGridViewDriver.CollectIonMobilitiesAndCollisionalCrossSections(null, lib, 1); var validatingIonMobilityPeptides = peptideTimes as ValidatingIonMobilityPrecursor[] ?? peptideTimes.ToArray(); Assert.AreEqual(2, validatingIonMobilityPeptides.Length); Assert.AreEqual(1.5, validatingIonMobilityPeptides[0].CollisionalCrossSectionSqA); Assert.AreEqual(3.5, validatingIonMobilityPeptides[1].CollisionalCrossSectionSqA); Assert.AreEqual(HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC, validatingIonMobilityPeptides[1].HighEnergyIonMobilityOffset); // This time with multiple CCS conformers supported lib = new List <LibraryIonMobilityInfo> { new LibraryIonMobilityInfo("test", true, dictCCS1) }; peptideTimes = CollisionalCrossSectionGridViewDriver.CollectIonMobilitiesAndCollisionalCrossSections(null, lib, 1); validatingIonMobilityPeptides = peptideTimes as ValidatingIonMobilityPrecursor[] ?? peptideTimes.ToArray(); Assert.AreEqual(4, validatingIonMobilityPeptides.Length); Assert.AreEqual(1, validatingIonMobilityPeptides[0].CollisionalCrossSectionSqA); Assert.AreEqual(2, validatingIonMobilityPeptides[1].CollisionalCrossSectionSqA); Assert.AreEqual(3, validatingIonMobilityPeptides[2].CollisionalCrossSectionSqA); Assert.AreEqual(4, validatingIonMobilityPeptides[3].CollisionalCrossSectionSqA); Assert.AreEqual(HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC, validatingIonMobilityPeptides[1].HighEnergyIonMobilityOffset); // Test serialization of molecule with '$' in it, which we use as a tab replacement against XML parser variability var molser = CustomMolecule.FromSmallMoleculeLibraryAttributes(SmallMoleculeLibraryAttributes.Create("caffeine$", caffeineFormula, caffeineInChiKey, caffeineHMDB)); var text = molser.ToSerializableString(); Assert.AreEqual(molser, CustomMolecule.FromSerializableString(text)); // Test handling of SmallMoleculeLibraryAttributes for mass-only descriptions var molserB = CustomMolecule.FromSmallMoleculeLibraryAttributes(SmallMoleculeLibraryAttributes.Create("caffeine$", null, new TypedMass(123.4, MassType.Monoisotopic), new TypedMass(123.45, MassType.Average), caffeineInChiKey, caffeineHMDB)); var textB = molserB.ToSerializableString(); Assert.AreEqual(molserB, CustomMolecule.FromSerializableString(textB)); var dictCCS2 = new Dictionary <LibKey, IonMobilityAndCCS[]>(); var ccs3 = new List <IonMobilityAndCCS> { IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(4, eIonMobilityUnits.drift_time_msec), 1.75, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC), IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(5, eIonMobilityUnits.drift_time_msec), null, HIGH_ENERGY_DRIFT_TIME_OFFSET_MSEC) }; // Drift times const string seq3 = "KLMNJ"; dictCCS2.Add(new LibKey(seq3, Adduct.SINGLY_PROTONATED), ccs3.ToArray()); lib = new List <LibraryIonMobilityInfo> { new LibraryIonMobilityInfo("test", false, dictCCS2) }; peptideTimes = CollisionalCrossSectionGridViewDriver.CollectIonMobilitiesAndCollisionalCrossSections(null, lib, 1); validatingIonMobilityPeptides = peptideTimes as ValidatingIonMobilityPrecursor[] ?? peptideTimes.ToArray(); Assert.AreEqual(1, validatingIonMobilityPeptides.Length); Assert.AreEqual(1.75, validatingIonMobilityPeptides[0].CollisionalCrossSectionSqA); }
public virtual IonMobilityAndCCS GetIonMobilityAndCCS() { return(IonMobilityAndCCS.GetIonMobilityAndCCS(IonMobilityValue.GetIonMobilityValue(IonMobilityNullable, IonMobilityUnits), CollisionalCrossSectionNullable, HighEnergyIonMobilityOffset)); }
public Dictionary <LibKey, IonMobilityAndCCS> GetTableMeasuredIonMobility(bool useHighEnergyOffsets, eIonMobilityUnits units) { var e = new CancelEventArgs(); var dict = new Dictionary <LibKey, IonMobilityAndCCS>(); foreach (DataGridViewRow row in _gridMeasuredDriftTimePeptides.Rows) { if (row.IsNewRow) { continue; } string seq; if (!ValidateSequence(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_SEQUENCE], out seq)) { return(null); } // OK, we have a non-empty "sequence" string, but is that actually a peptide or a molecule? // See if there's anything in the document whose text representation matches what's in the list var target = Program.MainWindow.Document.Molecules.Select(m => m.Target).FirstOrDefault(t => seq.Equals(t.ToString())); if (target == null || target.IsEmpty) { // Does seq evaluate as a peptide? target = !seq.All(c => char.IsUpper(c) || char.IsDigit(c) || @"[+-,.]()".Contains(c)) ? new Target(CustomMolecule.FromSerializableString(seq)) : Target.FromSerializableString(seq); } Adduct charge; if (!ValidateCharge(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_CHARGE], target.IsProteomic, out charge)) { return(null); } double mobility; if (!ValidateDriftTime(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_ION_MOBILITY], out mobility)) { return(null); } double?ccs; if (!ValidateCCS(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_CCS], out ccs)) { return(null); } double highEnergyOffset = 0; // Set default value in case user does not provide one if (useHighEnergyOffsets && !ValidateHighEnergyDriftTimeOffset(e, row.Cells[EditDriftTimePredictorDlg.COLUMN_HIGH_ENERGY_OFFSET], out highEnergyOffset)) { return(null); } var ionMobility = IonMobilityValue.GetIonMobilityValue(mobility, units); try { dict.Add(new LibKey(target, charge), IonMobilityAndCCS.GetIonMobilityAndCCS(ionMobility, ccs, highEnergyOffset)); } // ReSharper disable once EmptyGeneralCatchClause catch { // just take the first seen } } return(dict); }