From fc9f72954667d47f0cec1c8b5437ce4bec9a5221 Mon Sep 17 00:00:00 2001 From: Alan Race Date: Tue, 9 Apr 2019 12:32:05 +0100 Subject: [PATCH] Updated handling of RegionOfInterest in post processing techniques Previously attempting to perform PCA (or other MVA) technique on a ROI would fail. If the ROI had different pixels to those present within the data, this would also fail. Now the correct data is extracted for PCA (or other MVA) and a new (correct) ROI is generated from the combination of the original data ROI and the user selected ROI. --- src/core/DataInMemory.m | 31 ++++-------------- src/core/DataOnDisk.m | 2 +- src/core/DataRepresentation.m | 32 +++++++++++++++++-- src/core/ProjectedDataInMemory.m | 13 ++------ src/processing/postprocessing/InMemoryMAF.m | 7 ++-- src/processing/postprocessing/InMemoryNMF.m | 7 ++-- src/processing/postprocessing/InMemoryPCA.m | 9 ++++-- src/processing/postprocessing/InMemorypLSA.m | 7 ++-- .../postprocessing/KMeansClustering.m | 10 +----- .../postprocessing/MemoryEfficientPCA.m | 5 ++- 10 files changed, 65 insertions(+), 58 deletions(-) diff --git a/src/core/DataInMemory.m b/src/core/DataInMemory.m index 8f5eb46..ff24006 100644 --- a/src/core/DataInMemory.m +++ b/src/core/DataInMemory.m @@ -31,7 +31,6 @@ function setData(obj, data, regionOfInterest, isRowMajor, spectralChannels, name) obj.data = data; - obj.regionOfInterest = regionOfInterest; obj.spectralChannels = spectralChannels; obj.spectralChannelRange = [min(spectralChannels) max(spectralChannels)]; obj.name = name; @@ -41,8 +40,8 @@ function setData(obj, data, regionOfInterest, isRowMajor, spectralChannels, name % Ensure that no NaN exist in the data to avoid issues with % display and subsequent processing obj.data(isnan(obj.data)) = 0; - - obj.createPixelList(); + + obj.setRegionOfInterest(regionOfInterest); end function loadData(obj, parser, regionOfInterest, spectralChannelRange, zeroFilling) @@ -154,15 +153,6 @@ function loadData(obj, parser, regionOfInterest, spectralChannelRange, zeroFilli selectionData = pixelMask(obj.minY:obj.maxY, obj.minX:obj.maxX); if(isempty(preprocessingWorkflow) || preprocessingWorkflow.numberOfMethods == 0) - pixels = obj.regionOfInterest.getPixelList(); - - if(obj.isRowMajor) - % Sort by y column, then by x column - pixels = sortrows(pixels, [2 1]); - else - % Sort by x column, then by y column - pixels = sortrows(pixels, [1 2]); - end for imageIndex = 1:length(spectralChannelList) indicies = obj.spectralChannels >= (spectralChannelList(imageIndex)-spectralWidthList(imageIndex)) ... @@ -170,8 +160,8 @@ function loadData(obj, parser, regionOfInterest, spectralChannelRange, zeroFilli d = sum(obj.data(:, indicies), 2); - for i = 1:length(pixels) - images(pixels(i, 2), pixels(i, 1), imageIndex) = d(i); + for i = 1:length(obj.pixels) + images(obj.pixels(i, 2), obj.pixels(i, 1), imageIndex) = d(i); end end @@ -223,18 +213,9 @@ function loadData(obj, parser, regionOfInterest, spectralChannelRange, zeroFilli % image(selectionData == 1) = sum(obj.data, 2); d = sum(obj.data, 2); - pixels = obj.regionOfInterest.getPixelList(); - - if(obj.isRowMajor) - % Sort by y column, then by x column - pixels = sortrows(pixels, [2 1]); - else - % Sort by x column, then by y column - pixels = sortrows(pixels, [1 2]); - end - for i = 1:length(pixels) - image(pixels(i, 2), pixels(i, 1)) = d(i); + for i = 1:length(obj.pixels) + image(obj.pixels(i, 2), obj.pixels(i, 1)) = d(i); end image = Image(image); diff --git a/src/core/DataOnDisk.m b/src/core/DataOnDisk.m index 8c53dbd..2398c44 100644 --- a/src/core/DataOnDisk.m +++ b/src/core/DataOnDisk.m @@ -4,7 +4,7 @@ methods function obj = DataOnDisk(parser) - if(~isa(parser, 'Parser')) + if(~isa(parser, 'Parser')) exception = MException('DataOnDisk:InvalidArgument', 'Must supply an instance of the Parser class.'); throw(exception); end diff --git a/src/core/DataRepresentation.m b/src/core/DataRepresentation.m index 3d0f4db..7bebbcf 100644 --- a/src/core/DataRepresentation.m +++ b/src/core/DataRepresentation.m @@ -63,14 +63,42 @@ function createPixelList(obj) obj.height = (obj.maxY - obj.minY) + 1; if(obj.isRowMajor) - % Sort by y column, then by x column + % Sort by rows and then columns [obj.pixels, obj.pixelIndicies] = sortrows(obj.pixels, [2 1]); else - % Sort by x column, then by y column + % Sort by columns and then rows [obj.pixels, obj.pixelIndicies] = sortrows(obj.pixels, [1 2]); end end + % Returns a list of the pixel coordinates in the order that the + % data is stored in. I.e. if the data is row major, then the + % returned pixel list will also be row major. + % + % If no regionOfInterest is supplied then the base pixel list is + % returned + function pixelList = getDataOrderedPixelList(this, regionOfInterest) + if(~exist('regionOfInterest', 'var')) + pixelList = this.pixels; + else + pixelList = regionOfInterest.getPixelList(); + + if(this.isRowMajor) + pixelList = sortrows(pixelList, [2 1]); + else + pixelList = sortrows(pixelList, [1 2]); + end + end + end + + function roiIndexList = getDataIndiciesForROI(this, regionOfInterest) + roiPixelList = this.getDataOrderedPixelList(regionOfInterest); + + [c, index_A, index_B] = intersect(this.pixels, roiPixelList, 'stable', 'rows'); + + roiIndexList = this.pixelIndicies(index_A); + end + function exportToWorkspace(obj) variableName = inputdlg('Please specifiy a variable name:', 'Variable name', 1, {'dataRepresentation'}); diff --git a/src/core/ProjectedDataInMemory.m b/src/core/ProjectedDataInMemory.m index 07d6f89..e0fa5d1 100644 --- a/src/core/ProjectedDataInMemory.m +++ b/src/core/ProjectedDataInMemory.m @@ -47,18 +47,9 @@ function setData(obj, data, projectionMatrix, pixelSelection, isRowMajor, spectr % image(selectionData == 1) = obj.data(:, index); size(obj.data) d = obj.data(:, index); - pixels = obj.regionOfInterest.getPixelList(); - if(obj.isRowMajor) - % Sort by y column, then by x column - pixels = sortrows(pixels, [2 1]); - else - % Sort by x column, then by y column - pixels = sortrows(pixels, [1 2]); - end - size(pixels) - for i = 1:length(pixels) - image(pixels(i, 2), pixels(i, 1)) = d(i); + for i = 1:length(obj.pixels) + image(obj.pixels(i, 2), obj.pixels(i, 1)) = d(i); end end end diff --git a/src/processing/postprocessing/InMemoryMAF.m b/src/processing/postprocessing/InMemoryMAF.m index 3c5a649..d9b0915 100644 --- a/src/processing/postprocessing/InMemoryMAF.m +++ b/src/processing/postprocessing/InMemoryMAF.m @@ -76,7 +76,7 @@ end for roiIndex = 1:numel(rois) - pixelLists{end+1} = rois{roiIndex}.getPixelMask()'; + pixelLists{end+1} = dataRepresentation.getDataIndiciesForROI(rois{roiIndex}); xyPos{end+1} = rois{roiIndex}.getPixelList(); end @@ -106,7 +106,10 @@ projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex-1}, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex-1}.getName() ' (MAF)']); else - projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex}, ... + dataROI = RegionOfInterest(dataRepresentation.width, dataRepresentation.height); + dataROI.addPixels(and(rois{pixelListIndex}.getPixelMask(), dataRepresentation.regionOfInterest.getPixelMask())); + + projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, dataROI, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex}.getName() ' (MAF)']); end diff --git a/src/processing/postprocessing/InMemoryNMF.m b/src/processing/postprocessing/InMemoryNMF.m index 9b4db4c..c617b04 100644 --- a/src/processing/postprocessing/InMemoryNMF.m +++ b/src/processing/postprocessing/InMemoryNMF.m @@ -69,7 +69,7 @@ end for roiIndex = 1:numel(rois) - pixelLists{end+1} = rois{roiIndex}.getPixelMask()'; + pixelLists{end+1} = dataRepresentation.getDataIndiciesForROI(rois{roiIndex}); end % Change L to now be the mean @@ -96,7 +96,10 @@ projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex-1}, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex-1}.getName() ' (NMF)']); else - projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex}, ... + dataROI = RegionOfInterest(dataRepresentation.width, dataRepresentation.height); + dataROI.addPixels(and(rois{pixelListIndex}.getPixelMask(), dataRepresentation.regionOfInterest.getPixelMask())); + + projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, dataROI, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex}.getName() ' (NMF)']); end diff --git a/src/processing/postprocessing/InMemoryPCA.m b/src/processing/postprocessing/InMemoryPCA.m index 9a2fc4d..3a634f1 100644 --- a/src/processing/postprocessing/InMemoryPCA.m +++ b/src/processing/postprocessing/InMemoryPCA.m @@ -90,7 +90,7 @@ end for roiIndex = 1:numel(rois) - pixelLists{end+1} = rois{roiIndex}.getPixelMask()'; + pixelLists{end+1} = dataRepresentation.getDataIndiciesForROI(rois{roiIndex}); end usePCA = false; @@ -134,11 +134,14 @@ else dataName = [rois{pixelListIndex}.getName() ' (PCA)']; - projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex}, ... + dataROI = RegionOfInterest(dataRepresentation.width, dataRepresentation.height); + dataROI.addPixels(and(rois{pixelListIndex}.getPixelMask(), dataRepresentation.regionOfInterest.getPixelMask())); + + projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, dataROI, ... dataRepresentation.isRowMajor, peakList, dataName); end - latent{pixelListIndex} + % TODO: Incorporate this into the dataRepresentation figure, plot(cumsum(latent{pixelListIndex})./sum(latent{pixelListIndex})); title(['Explained ' dataName]); diff --git a/src/processing/postprocessing/InMemorypLSA.m b/src/processing/postprocessing/InMemorypLSA.m index ed6358c..6e3f3f3 100644 --- a/src/processing/postprocessing/InMemorypLSA.m +++ b/src/processing/postprocessing/InMemorypLSA.m @@ -94,7 +94,7 @@ end for roiIndex = 1:numel(rois) - pixelLists{end+1} = rois{roiIndex}.getPixelMask()'; + pixelLists{end+1} = dataRepresentation.getDataIndiciesForROI(rois{roiIndex}); xyPos{end+1} = rois{roiIndex}.getPixelList(); end @@ -195,7 +195,10 @@ projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex-1}, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex-1}.getName() ' (pLSA)']); else - projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex}, ... + dataROI = RegionOfInterest(dataRepresentation.width, dataRepresentation.height); + dataROI.addPixels(and(rois{pixelListIndex}.getPixelMask(), dataRepresentation.regionOfInterest.getPixelMask())); + + projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, dataROI, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex}.getName() ' (pLSA)']); end diff --git a/src/processing/postprocessing/KMeansClustering.m b/src/processing/postprocessing/KMeansClustering.m index ec3bde8..8d45a14 100644 --- a/src/processing/postprocessing/KMeansClustering.m +++ b/src/processing/postprocessing/KMeansClustering.m @@ -41,15 +41,7 @@ % curPixels = dataRepresentations{i}.regionOfInterest.pixelSelection; kmeansImage = zeros(dataRepresentation.height, dataRepresentation.width); %size(curPixels)); - pixels = dataRepresentations{i}.regionOfInterest.getPixelList(); - - if(dataRepresentations{i}.isRowMajor) - % Sort by y column, then by x column - pixels = sortrows(pixels, [2 1]); - else - % Sort by x column, then by y column - pixels = sortrows(pixels, [1 2]); - end + pixels = dataRepresentations{i}.getDataOrderedPixelList(); for j = 1:length(pixels) kmeansImage(pixels(j, 2), pixels(j, 1)) = res(j); diff --git a/src/processing/postprocessing/MemoryEfficientPCA.m b/src/processing/postprocessing/MemoryEfficientPCA.m index df2afb9..5d474e2 100644 --- a/src/processing/postprocessing/MemoryEfficientPCA.m +++ b/src/processing/postprocessing/MemoryEfficientPCA.m @@ -271,7 +271,10 @@ projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex-1}, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex-1}.getName() ' (ME PCA)']); else - projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, rois{pixelListIndex}, ... + dataROI = RegionOfInterest(dataRepresentation.width, dataRepresentation.height); + dataROI.addPixels(and(rois{pixelListIndex}.getPixelMask(), dataRepresentation.regionOfInterest.getPixelMask())); + + projectedDataRepresentation.setData(scores{pixelListIndex}, coeff{pixelListIndex}, dataROI, ... dataRepresentation.isRowMajor, peakList, [rois{pixelListIndex}.getName() ' (ME PCA)']); end