content: /*
   * 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 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";
  	}
  
  }
  
  
  