Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 39 additions & 2 deletions pwiz_tools/Skyline/Controls/Databinding/CandidatePeakForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private void SequenceTreeOnAfterSelect(object sender, TreeViewEventArgs args)
QueueUpdateRowSource();
}

private void QueueUpdateRowSource()
public void QueueUpdateRowSource()
{
_updatePending = true;
BeginInvoke(new Action(UpdateRowSource));
Expand Down Expand Up @@ -328,7 +328,7 @@ private Selector GetSelector()
}

var chromatogramSet = document.Settings.MeasuredResults.Chromatograms[replicateIndex];
var chromFileInfoId = chromatogramSet.MSDataFileInfos.First().FileId;
var chromFileInfoId = GetChromFileInfoId(peptideDocNode, replicateIndex, chromatogramSet);
foreach (var comparableGroup in peptideDocNode.GetComparableGroups())
{
var transitionGroups = ImmutableList.ValueOf(comparableGroup.Select(tg => tg.TransitionGroup));
Expand All @@ -342,6 +342,43 @@ private Selector GetSelector()
return null;
}

private ChromFileInfoId GetChromFileInfoId(PeptideDocNode peptideDocNode, int replicateIndex, ChromatogramSet chromatogramSet)
{
if (chromatogramSet.MSDataFileInfos.Count == 1)
{
return chromatogramSet.MSDataFileInfos[0].FileId;
}

IList<ReferenceValue<ChromFileInfoId>> candidateFileIds = Array.Empty<ReferenceValue<ChromFileInfoId>>();
if (peptideDocNode.Results != null)
{
candidateFileIds = peptideDocNode.GetSafeChromInfo(replicateIndex)
.Select(info => ReferenceValue.Of(info.FileId)).ToList();
}

if (candidateFileIds.Count == 0)
{
candidateFileIds = chromatogramSet.MSDataFileInfos.Select(file => ReferenceValue.Of(file.FileId))
.ToList();
}

if (candidateFileIds.Count == 1)
{
return candidateFileIds[0];
}

var graphChrom = SkylineWindow.GetGraphChrom(chromatogramSet.Name);
if (true == graphChrom?.Visible)
{
var graphChromFileId = graphChrom.GetChromFileInfoId();
if (graphChromFileId != null && candidateFileIds.Contains(graphChromFileId))
{
return graphChromFileId;
}
}
return candidateFileIds.FirstOrDefault();
}

private class Selector
{
public Selector(SrmDocument document, IdentityPath peptideIdentityPath,
Expand Down
11 changes: 8 additions & 3 deletions pwiz_tools/Skyline/Controls/Graphs/GraphChromatogram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using pwiz.CommonMsData;
using pwiz.MSGraph;
using pwiz.ProteowizardWrapper;
using pwiz.Skyline.Controls.Databinding;
using pwiz.Skyline.Controls.SeqNode;
using pwiz.Skyline.Menus;
using pwiz.Skyline.Model;
Expand Down Expand Up @@ -794,13 +795,17 @@ private void comboFiles_SelectedIndexChanged(object sender, EventArgs e)
if (_dontSyncSelectedFile)
return;

var panes = FormUtil.OpenForms.OfType<GraphSummary>().SelectMany(g => g.GraphPanes).OfType<SummaryReplicateGraphPane>();

foreach (var pane in panes)
var openForms = FormUtil.OpenForms;
foreach (var pane in openForms.OfType<GraphSummary>().SelectMany(g => g.GraphPanes).OfType<SummaryReplicateGraphPane>())
{
var item = comboFiles.SelectedItem.ToString();
pane.SetSelectedFile(item);
}

foreach (var candidatePeakForm in FormUtil.OpenForms.OfType<CandidatePeakForm>())
{
candidatePeakForm.QueueUpdateRowSource();
}
}

private void GraphChromatogram_VisibleChanged(object sender, EventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,5 +240,10 @@ private SrmDocument ChoosePeak(SrmDocument document, TransitionGroupDocNode prec
return document.ChangePeak(identityPath, resultFile.Replicate.Name,
resultFile.ChromFileInfo.FilePath, null, retentionTime, UserSet.TRUE);
}

public PrecursorResult GetPrecursorResult()
{
return _precursorResult;
}
}
}
43 changes: 29 additions & 14 deletions pwiz_tools/Skyline/Model/Results/ChromatogramCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1545,9 +1545,7 @@ public ChromatogramCache OptimizeToPath(string cachePathOpt,
var listKeepTransitions = new BlockedArrayList<ChromTransition>(
ChromTransition.SizeOf, ChromTransition.DEFAULT_BLOCK_SIZE);
ChromatogramGroupIds keepGroupIds = new ChromatogramGroupIds();
var dictKeepTextIdIndices = new Dictionary<ChromatogramGroupId, int>();

// TODO: Make these first 3 temporary files that delete on close
using (var fsPeaks = new FileSaver(cachePathOpt + PEAKS_EXT, true))
using (var fsScans = new FileSaver(cachePathOpt + SCANS_EXT, true))
using (var fsScores = new FileSaver(cachePathOpt + SCORES_EXT, true))
Expand Down Expand Up @@ -1634,18 +1632,7 @@ public ChromatogramCache OptimizeToPath(string cachePathOpt,
{
TransferPeaks(cacheFormat, firstPeakToTransfer, numPeaksToTransfer, fsPeaks.FileStream);
}

if (_rawData.ChromCacheFiles[fileIndex].SizeScanIds == 0)
listKeepCachedFiles.Add(_rawData.ChromCacheFiles[fileIndex]);
else
{
// Write all scan ids for the last file to the scan ids output stream
inStream.Seek(_rawData.LocationScanIds + _rawData.ChromCacheFiles[fileIndex].LocationScanIds, SeekOrigin.Begin);
int lenReadIds = _rawData.ChromCacheFiles[fileIndex].SizeScanIds;
long locationScanIds = fsScans.Stream.Position;
inStream.TransferBytes(fsScans.Stream, lenReadIds, buffer);
listKeepCachedFiles.Add(_rawData.ChromCacheFiles[fileIndex].RelocateScanIds(locationScanIds));
}
listKeepCachedFiles.Add(RelocateScanIds(_rawData.ChromCacheFiles[fileIndex], inStream, fsScans, buffer));

if (listKeepResultFileDatas != null)
{
Expand All @@ -1664,6 +1651,20 @@ public ChromatogramCache OptimizeToPath(string cachePathOpt,
progress.SetProgressCheckCancel(i, listEntries.Length);
} while (i < listEntries.Length);

if (keepFilePaths.Count > listKeepCachedFiles.Count)
{
// If there were any file paths that we were supposed to keep, but which did not have any chromatograms, they need
// to be added to the cache file so that Skyline does not treat them as missing
var chromCacheFiles = _rawData.ChromCacheFiles.ToDictionary(file => file.FilePath);
foreach (var filePath in keepFilePaths.Except(listKeepCachedFiles.Select(file => file.FilePath)))
{
if (chromCacheFiles.TryGetValue(filePath, out var chromCachedFile))
{
listKeepCachedFiles.Add(RelocateScanIds(chromCachedFile, inStream, fsScans, buffer));
}
}
}

// CONSIDER: We should be able to figure out the order from the original order
// without needing this second sort
listKeepEntries.Sort();
Expand Down Expand Up @@ -1696,6 +1697,20 @@ public ChromatogramCache OptimizeToPath(string cachePathOpt,
}
}

private ChromCachedFile RelocateScanIds(ChromCachedFile chromCachedFile, Stream inStream, FileSaver fsScans, byte[] buffer)
{
if (chromCachedFile.SizeScanIds == 0)
{
return chromCachedFile;
}
// Write all scan ids for the last file to the scan ids output stream
inStream.Seek(_rawData.LocationScanIds + chromCachedFile.LocationScanIds, SeekOrigin.Begin);
int lenReadIds = chromCachedFile.SizeScanIds;
long locationScanIds = fsScans.Stream.Position;
inStream.TransferBytes(fsScans.Stream, lenReadIds, buffer);
return chromCachedFile.RelocateScanIds(locationScanIds);
}

public void TransferPeaks(CacheFormat targetFormat, int firstPeakIndex, int peakCount, Stream writeStream)
{
_rawData.TransferPeaks(ReadStream.Stream, targetFormat, firstPeakIndex, peakCount, writeStream);
Expand Down
67 changes: 67 additions & 0 deletions pwiz_tools/Skyline/TestFunctional/MinimizeWithEmptyFilesTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Original author: Nicholas Shulman <nicksh .at. u.washington.edu>,
* MacCoss Lab, Department of Genome Sciences, UW
*
* Copyright 2025 University of Washington - Seattle, WA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using pwiz.Skyline.FileUI;
using pwiz.SkylineTestUtil;

namespace pwiz.SkylineTestFunctional
{
/// <summary>
/// Tests minimizing the chromatograms in a document where some of the files do not have any chromatograms in the .skyd file.
/// Those files with no chromatograms need to still have file entries in the .skyd file because otherwise Skyline
/// will try to extract chromatograms from the .raw files.
/// </summary>
[TestClass]
public class MinimizeWithEmptyFilesTest : AbstractFunctionalTest
{
[TestMethod]
public void TestMinimizeWithEmptyFiles()
{
TestFilesZip = @"TestFunctional\MultiInjectCandidatePeakTest.zip";
RunFunctionalTest();
}

protected override void DoTest()
{
RunUI(() => SkylineWindow.OpenFile(TestFilesDir.GetTestPath("MultiInjectCandidatePeakTest.sky")));
WaitForDocumentLoaded();
RunDlg<ManageResultsDlg>(SkylineWindow.ManageResults, manageResultsDlg =>
{
manageResultsDlg.SelectedChromatograms = new[]
{ SkylineWindow.Document.MeasuredResults.Chromatograms.Last() };
manageResultsDlg.RemoveReplicates();
manageResultsDlg.OkDialog();
});
RunUI(()=>SkylineWindow.SaveDocument());
RunLongDlg<ManageResultsDlg>(SkylineWindow.ManageResults, manageResultsDlg =>
{
RunDlg<MinimizeResultsDlg>(manageResultsDlg.MinimizeResults, minimizeResultsDlg =>
{
minimizeResultsDlg.Minimize(false);
});
}, manageResultsDlg => { });
var cachedFiles = SkylineWindow.Document.MeasuredResults.CachedFilePaths.ToHashSet();
foreach (var filePath in SkylineWindow.Document.MeasuredResults.MSDataFilePaths)
{
Assert.IsTrue(cachedFiles.Contains(filePath), "File {0} is not in .skyd file", filePath);
}
}
}
}
138 changes: 138 additions & 0 deletions pwiz_tools/Skyline/TestFunctional/MultiInjectCandidatePeakTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Original author: Nicholas Shulman <nicksh .at. u.washington.edu>,
* MacCoss Lab, Department of Genome Sciences, UW
*
* Copyright 2025 University of Washington - Seattle, WA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using pwiz.Common.Collections;
using pwiz.Common.DataBinding;
using pwiz.Skyline.Controls.Databinding;
using pwiz.Skyline.Model;
using pwiz.Skyline.Model.Databinding.Entities;
using pwiz.Skyline.Model.Results;
using pwiz.SkylineTestUtil;

namespace pwiz.SkylineTestFunctional
{
/// <summary>
/// Verifies that when a replicate has multiple injections, the Candidate Peaks window shows
/// the peaks for an appropriate file.
/// </summary>
[TestClass]
public class MultiInjectCandidatePeakTest : AbstractFunctionalTest
{
[TestMethod]
public void TestMultiInjectCandidatePeak()
{
TestFilesZip = @"TestFunctional\MultiInjectCandidatePeakTest.zip";
RunFunctionalTest();
}

protected override void DoTest()
{
RunUI(()=>
{
SkylineWindow.OpenFile(TestFilesDir.GetTestPath("MultiInjectCandidatePeakTest.sky"));
SkylineWindow.ShowCandidatePeaks();
SkylineWindow.SelectedResultsIndex = 0;
SkylineWindow.SelectedPath = SkylineWindow.Document.GetPathTo((int)SrmDocument.Level.Molecules, 0);
});

var firstGraphChrom = SkylineWindow.GetGraphChrom(SkylineWindow.Document.MeasuredResults.Chromatograms[0].Name);
Assert.IsTrue(firstGraphChrom.Visible);
var candidatePeakForm = FindOpenForm<CandidatePeakForm>();
Assert.IsNotNull(candidatePeakForm);
// Verify that the file shown in the candidate peaks window is the same as the file chosen in the chromatogram graph
foreach (var moleculeGroup in SkylineWindow.Document.MoleculeGroups)
{
foreach (var molecule in moleculeGroup.Molecules)
{
var moleculeIdentityPath = new IdentityPath(moleculeGroup.PeptideGroup, molecule.Peptide);
RunUI(() => SkylineWindow.SelectedPath = moleculeIdentityPath);
WaitForGraphs();
var candidatePeaks = GetCandidatePeaks(candidatePeakForm).ToList();
Assert.AreEqual(moleculeIdentityPath, candidatePeaks.Select(peak=>peak.GetPrecursorResult().Precursor.Peptide.IdentityPath).Distinct().Single());
int fileCount = firstGraphChrom.Files.Count;
if (fileCount == 1)
{
Assert.AreSame(UniqueFileId(candidatePeaks), CallUI(firstGraphChrom.GetChromFileInfoId));
}
else
{
for (int i = 0; i < fileCount; i++)
{
RunUI(() => firstGraphChrom.SelectedFileIndex = i);

candidatePeaks = GetCandidatePeaks(candidatePeakForm).ToList();
WaitForGraphs();
var candidatePeakFileId = UniqueFileId(candidatePeaks);
var graphFileId = CallUI(firstGraphChrom.GetChromFileInfoId);
Assert.AreSame(candidatePeakFileId, graphFileId);
}
}
}
}
// Close all the chromatogram windows
RunUI(() =>
{
foreach (var graphChrom in SkylineWindow.GraphChromatograms.ToList())
{
graphChrom.Close();
}

SkylineWindow.SelectedResultsIndex = 0;
firstGraphChrom.Close();
Assert.AreEqual(0, SkylineWindow.SelectedResultsIndex);
foreach (var graphChrom in SkylineWindow.GraphChromatograms)
{
Assert.IsFalse(graphChrom.Visible);
}
});
foreach (var moleculeGroup in SkylineWindow.Document.MoleculeGroups)
{
foreach (var molecule in moleculeGroup.Molecules)
{
var moleculeIdentityPath = new IdentityPath(moleculeGroup.PeptideGroup, molecule.Peptide);
RunUI(() => SkylineWindow.SelectedPath = moleculeIdentityPath);
WaitForGraphs();
var candidatePeaks = GetCandidatePeaks(candidatePeakForm).ToList();
Assert.AreEqual(moleculeIdentityPath, candidatePeaks.Select(peak => peak.GetPrecursorResult().Precursor.Peptide.IdentityPath).Distinct().Single());
Assert.IsNotNull(UniqueFileId(candidatePeaks));
foreach (var candidatePeak in candidatePeaks)
{
Assert.AreEqual(candidatePeak.GetPrecursorResult().Precursor.Peptide.IdentityPath, moleculeIdentityPath);
}
}
}
}

private IEnumerable<CandidatePeakGroup> GetCandidatePeaks(CandidatePeakForm candidatePeakForm)
{
WaitForConditionUI(() => candidatePeakForm.IsComplete);
return CallUI(()=>candidatePeakForm.DataboundGridControl.BindingListSource.OfType<RowItem>()
.Select(rowItem => (CandidatePeakGroup)rowItem.Value));
}

private ChromFileInfoId UniqueFileId(IEnumerable<CandidatePeakGroup> peaks)
{
return peaks.Select(peak => ReferenceValue.Of(peak.GetPrecursorResult().GetResultFile().ChromFileInfoId))
.Distinct()
.SingleOrDefault().Value;
}
}
}
Binary file not shown.
2 changes: 2 additions & 0 deletions pwiz_tools/Skyline/TestFunctional/TestFunctional.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,13 @@
<Compile Include="LogScaleAxisTest.cs" />
<Compile Include="MedianNormalizationTest.cs" />
<Compile Include="MessageBoxHelperTest.cs" />
<Compile Include="MinimizeWithEmptyFilesTest.cs" />
<Compile Include="MinimizeIrtTest.cs" />
<Compile Include="EADZIonsTest.cs" />
<Compile Include="MissingOptStepsTest.cs" />
<Compile Include="MixedSrmPrmTest.cs" />
<Compile Include="Ms1SpectrumFilterTest.cs" />
<Compile Include="MultiInjectCandidatePeakTest.cs" />
<Compile Include="MultiInjectionReplicatesTest.cs" />
<Compile Include="MultiInjectReplicatePivotTest.cs" />
<Compile Include="MultiInjectRescoreTest.cs" />
Expand Down