/* * Copyright (C) 2016 - Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.apps.gui.roi; import ij.IJ; import ij.process.ByteProcessor; import org.fastica.FastICAException; import edu.stanford.rsl.conrad.data.numeric.Grid3D; import edu.stanford.rsl.conrad.data.numeric.MultiChannelGrid2D; import edu.stanford.rsl.conrad.filtering.PatchwiseComponentComputationTool; import edu.stanford.rsl.conrad.utils.ImageUtil; import edu.stanford.rsl.jpop.utils.UserUtil; /** * Very useful tool to explore the components of small patches. It features PCA, SVD, and ICA. * @author akmaier * */ public class ComputeIndependentComponents extends EvaluateROI { private Grid3D multiGrid = null; private int currentImage = -1; private int numChannels = -1; private String operation = null; public static final String SVD = " SVD "; public static final String PCA = " PCA "; public static final String ICA = " ICA "; public void configure() throws Exception { image = IJ.getImage(); roi = image.getRoi(); if (roi != null){ configured = true; } multiGrid = ImageUtil.wrapImagePlus(image); currentImage = image.getCurrentSlice() -1; numChannels = ((MultiChannelGrid2D) multiGrid.getSubGrid(0)).getNumberOfChannels(); String [] operations = {SVD, PCA, ICA}; operation = (String) UserUtil.chooseObject("Select operation: ", "Operation Selection", operations, operation); } @Override public Object evaluate() { double [][] signals = null; if (roi.getMask() == null){ signals = new double [numChannels][roi.getBounds().height*roi.getBounds().width]; for (int j=0; j < roi.getBounds().height; j++){ for (int i=0; i < roi.getBounds().width; i++){ int x = roi.getBounds().x + i; int y = roi.getBounds().y + j; for (int k=0;k<numChannels;k++){ signals[k][(j*roi.getBounds().width)+i] = ((MultiChannelGrid2D) multiGrid.getSubGrid(currentImage)).getChannel(k).getPixelValue(x, y); } } } } else { // Count pixels in mask int count = 0; ByteProcessor mask = (ByteProcessor)roi.getMask(); for (int j=0; j < roi.getBounds().height; j++){ for (int i=0; i < roi.getBounds().width; i++){ if (mask.getPixel(i, j) == 255){ count++; } } } signals = new double [numChannels][count]; int index = 0; for (int j=0; j < roi.getBounds().height; j++){ for (int i=0; i < roi.getBounds().width; i++){ int x = roi.getBounds().x + i; int y = roi.getBounds().y + j; if (mask.getPixel(i, j) == 255){ for (int k=0;k<numChannels;k++){ signals[k][index] = ((MultiChannelGrid2D) multiGrid.getSubGrid(currentImage)).getChannel(k).getPixelValue(x, y); } index++; } } } } try { double [][] vectors = PatchwiseComponentComputationTool.getComponents(signals, numChannels, operation); ByteProcessor mask = (ByteProcessor)roi.getMask(); MultiChannelGrid2D out = new MultiChannelGrid2D(roi.getBounds().width, roi.getBounds().height, numChannels); if (roi.getMask() == null){ for (int j=0; j < roi.getBounds().height; j++){ for (int i=0; i < roi.getBounds().width; i++){ for (int k=0;k<numChannels;k++){ out.getChannel(k).putPixelValue(i, j, vectors[k][(j*roi.getBounds().width)+i]); } } } } else { int index = 0; for (int j=0; j < roi.getBounds().height; j++){ for (int i=0; i < roi.getBounds().width; i++){ if (mask.getPixel(i, j) == 255){ for (int k=0;k<numChannels;k++){ out.getChannel(k).putPixelValue(i, j, vectors[k][index]); } index++; } } } } out.show("Components using" + operation); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public String toString() { return "Compute Components"; } }