diff --git a/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj b/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj
index 93c4ee406..8e41446bc 100644
--- a/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj
+++ b/tests/MSDIAL5/MsdialCoreTestApp/MsdialCoreTestApp.csproj
@@ -29,6 +29,10 @@
+
+
+
+
diff --git a/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs b/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs
index 05114e09e..c527f484a 100644
--- a/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs
+++ b/tests/MSDIAL5/MsdialCoreTestApp/Process/LcmsProcess.cs
@@ -301,10 +301,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}");
}
@@ -412,6 +411,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"]);
+ }
+}