From 1a734095e98807a6f6ae043c732d702c02bcc3c0 Mon Sep 17 00:00:00 2001 From: "DESKTOP-382ETUR\\Hiroshi Tsugawa" Date: Fri, 25 Sep 2026 19:34:42 +0900 Subject: [PATCH] Fix alignment-light matrix quant access --- .../MsdialCoreTestApp.csproj | 4 + .../MsdialCoreTestApp/Process/LcmsProcess.cs | 23 ++++- .../Process/LcmsProcessTests.cs | 89 +++++++++++++++++++ .../AlignmentLightQuantValueAccessorTests.cs | 35 ++++++++ 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 tests/MSDIAL5/MsdialCoreTestAppTests/Process/LcmsProcessTests.cs create mode 100644 tests/MSDIAL5/MsdialCoreTests/Export/AlignmentLightQuantValueAccessorTests.cs diff --git a/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj b/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj index 49f05dc99..1fed44ff2 100644 --- a/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj +++ b/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj @@ -25,6 +25,10 @@ + + + + diff --git a/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs b/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs index 701ccdc27..392f8a666 100644 --- a/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs +++ b/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs @@ -262,10 +262,9 @@ IQuantValueAccessor CreateQuantAccessor(string exportType) => alignmentLightPeak foreach (var (_, exportType, suffix) in requestedMatrices.Where(item => item.Requested)) { var matrixFile = Path.Combine(matrixFolder, alignmentFile.FileName + suffix); using (var matrixStream = File.Open(matrixFile, FileMode.Create, FileAccess.Write)) { - new AlignmentCSVExporter().Export( + ExportAlignmentMatrix( matrixStream, result.AlignmentSpotProperties, align_decResults, files, - new MulticlassFileMetaAccessor(0), align_accessor, - new LegacyQuantValueAccessor(exportType, storage.Parameter), matrixStats); + align_accessor, exportType, storage.Parameter, alignmentLightPeakStore, matrixStats); } Console.WriteLine($"{exportType} matrix: {matrixFile}"); } @@ -373,6 +372,24 @@ private static void CollectAlignmentLightExportGarbage(bool isAlignmentLightMode GC.Collect(2, GCCollectionMode.Forced, blocking: true, compacting: true); } + internal static void ExportAlignmentMatrix( + Stream stream, + IReadOnlyList spots, + IReadOnlyList msdecResults, + IReadOnlyList files, + IMetadataAccessor metadataAccessor, + string exportType, + ParameterBase parameter, + AlignmentLightPeakStore? alignmentLightPeakStore, + IReadOnlyList stats) { + IQuantValueAccessor quantAccessor = alignmentLightPeakStore is null + ? new LegacyQuantValueAccessor(exportType, parameter) + : new AlignmentLightQuantValueAccessor(exportType, parameter, alignmentLightPeakStore); + new AlignmentCSVExporter().Export( + stream, spots, msdecResults, files, + new MulticlassFileMetaAccessor(0), metadataAccessor, quantAccessor, stats); + } + private static IEnumerable LoadRepresentativeDeconvolutions(IMsdialDataStorage storage, IReadOnlyList? spots) { var files = storage.AnalysisFiles; diff --git a/tests/MSDIAL5/MsdialCoreTestAppTests/Process/LcmsProcessTests.cs b/tests/MSDIAL5/MsdialCoreTestAppTests/Process/LcmsProcessTests.cs new file mode 100644 index 000000000..3e01a19a3 --- /dev/null +++ b/tests/MSDIAL5/MsdialCoreTestAppTests/Process/LcmsProcessTests.cs @@ -0,0 +1,89 @@ +using CompMs.App.MsdialConsole.Process; +using CompMs.Common.Interfaces; +using CompMs.MsdialCore.DataObj; +using CompMs.MsdialCore.Export; +using CompMs.MsdialCore.MSDec; +using CompMs.MsdialCore.Parameter; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; + +namespace MsdialCoreTestAppTests.Process; + +[TestClass] +public sealed class LcmsProcessTests +{ + [TestMethod] + public void LightModeHeightMatrixContainsAValueForEveryAnalysisFile() + { + var scratch = Path.Combine(Path.GetTempPath(), $"msdial-light-matrix-{Guid.NewGuid():N}"); + Directory.CreateDirectory(scratch); + try { + var files = new[] { + new AnalysisFileBean { + AnalysisFileId = 0, + AnalysisFileName = "sample-a", + AnalysisFileClass = "sample", + AnalysisFileAnalyticalOrder = 1, + AnalysisBatch = 1, + }, + new AnalysisFileBean { + AnalysisFileId = 1, + AnalysisFileName = "sample-b", + AnalysisFileClass = "sample", + AnalysisFileAnalyticalOrder = 2, + AnalysisBatch = 1, + }, + }; + using var store = AlignmentLightPeakStore.CreateTemp(); + store.Initialize(1, files); + store.WriteSpotPeaks(0, [ + new AlignmentChromPeakFeature { FileID = 0, FileName = "sample-a", PeakHeightTop = 125d }, + new AlignmentChromPeakFeature { FileID = 1, FileName = "sample-b", PeakHeightTop = 250d }, + ]); + var spot = new AlignmentSpotProperty { MasterAlignmentID = 0 }; + var output = Path.Combine(scratch, "height.txt"); + var parameter = new ParameterBase { + FileID_ClassName = new Dictionary { + [0] = "sample", + [1] = "sample", + }, + }; + + using (var stream = File.Create(output)) { + LcmsProcess.ExportAlignmentMatrix( + stream, + [spot], + [new MSDecResult()], + files, + new MinimalMetadataAccessor(), + "Height", + parameter, + store, + [StatsValue.Average]); + } + + var text = File.ReadAllText(output); + StringAssert.Contains(text, "sample-a\tsample-b"); + StringAssert.Contains(text, "125\t250"); + } + finally { + Directory.Delete(scratch, recursive: true); + } + } + + private sealed class MinimalMetadataAccessor : IMetadataAccessor + { + public IReadOnlyDictionary GetContent(AlignmentSpotProperty spot, IMSScanProperty msdec) { + return new ReadOnlyDictionary(new Dictionary { + ["ID"] = spot.MasterAlignmentID.ToString(), + }); + } + + public string[] GetHeaders() { + return ["ID"]; + } + } +} diff --git a/tests/MSDIAL5/MsdialCoreTests/Export/AlignmentLightQuantValueAccessorTests.cs b/tests/MSDIAL5/MsdialCoreTests/Export/AlignmentLightQuantValueAccessorTests.cs new file mode 100644 index 000000000..5690129aa --- /dev/null +++ b/tests/MSDIAL5/MsdialCoreTests/Export/AlignmentLightQuantValueAccessorTests.cs @@ -0,0 +1,35 @@ +using CompMs.MsdialCore.DataObj; +using CompMs.MsdialCore.Export; +using CompMs.MsdialCore.Parameter; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CompMs.MsdialCoreTests.Export; + +[TestClass] +public class AlignmentLightQuantValueAccessorTests +{ + [TestMethod] + public void GetQuantValuesUsesFileBackedRowsWhenSpotDoesNotHoldPeakProperties() + { + var files = new[] { + new AnalysisFileBean { AnalysisFileId = 0, AnalysisFileName = "sample-a" }, + new AnalysisFileBean { AnalysisFileId = 1, AnalysisFileName = "sample-b" }, + }; + using var store = AlignmentLightPeakStore.CreateTemp(); + store.Initialize(1, files); + store.WriteSpotPeak(0, new AlignmentChromPeakFeature { + FileID = 1, + FileName = "sample-b", + PeakHeightTop = 1234d, + }); + var spot = new AlignmentSpotProperty { MasterAlignmentID = 0 }; + var accessor = new AlignmentLightQuantValueAccessor("Height", new ParameterBase(), store); + + var headers = accessor.GetQuantHeaders(files); + var values = accessor.GetQuantValues(spot); + + CollectionAssert.AreEqual(new[] { "sample-a", "sample-b" }, headers); + Assert.AreEqual("0", values["sample-a"]); + Assert.AreEqual("1234", values["sample-b"]); + } +}