// Path: src/main/java/jclustering/Voxel.java
// public class Voxel {
// 
//     /**
//      * X-coordinate for the voxel.
//      */
//     public final int x;
//     /**
//      * Y-coordinate for the voxel.
//      */
//     public final int y;
//     /**
//      * Slice (1-based) for the voxel.
//      */
//     public final int slice;
//     /**
//      * Time-activity curve.
//      */
//     public final double [] tac;
//     
//     /**
//      * Main constructor for this data transfer object
//      * @param x X-coordinate.
//      * @param y Y-coordinate.
//      * @param slice Slice number.
//      * @param tac Time-activity curve.
//      */
//     public Voxel(int x, int y, int slice, double [] tac) {
//         
//         this.x = x;
//         this.y = y;
//         this.slice = slice;
//         this.tac = tac;
//         
//     }
// 
// }
// 
// Path: src/main/java/jclustering/MathUtils.java
// public static int getMaxIndex(double[] d) {
// 
//     int res = 0;
//     double aux = d[0];
// 
//     for (int i = 0; i < d.length; i++) {
//         if (d[i] > aux) {
//             res = i;
//             aux = d[i];
//         }
//     }
// 
//     return res;
// }
// 
// Path: src/main/java/jclustering/Utils.java
// public static ImagePlus RealMatrix2IJ(RealMatrix rm, int [] dim, 
//         ImagePlusHyp ip, String name) {
//  // Get number of components
//     int components = rm.getRowDimension();
//         
//     // Create dynamic image
//     ImagePlus image = IJ.createImage(name, "32-bit", 
//                                          dim[0], dim[1],
//                                          dim[3] * components);
//     image.setDimensions(1, dim[3], components);
//     image.setOpenAsHyperStack(true);
//         
//     // Get stack for easy access
//     ImageStack is = image.getStack();
//         
//     int column_index = 0;
//         
//     // Assign voxels to values. It is important to iterate the image
//     // in the correct order (first x, then y, then slices), because
//     // that is the way the images are normally processed when using
//     // the ImagePlusHypIterator object.
//     for(int z = 0; z < dim[3]; z++) {
//         for(int y = 0; y < dim[1]; y++) {
//             for(int x = 0; x < dim[0]; x++) {
//                     
//                 // Test it the TAC is noise. If it is noise, 
//                 // jump to the next one
//                 double [] tac = ip.getTAC(x, y, z + 1);
//                     
//                 // Check for masked voxels                    
//                 if (!isMasked(tac, ip.CALZERO)) {
//                     // Not masked: get the next column
//                     double [] comp = rm.getColumn(column_index++);
//                         
//                     // Iterate through the component and set the values.
//                     // Each row of the component is in one frame.
//                     for (int t = 0; t < components; t++) {
//                         // Get internal slice number
//                         int sn = image.getStackIndex(1, z + 1, t + 1);
//                         is.setVoxel(x, y, sn - 1, comp[t]);                            
//                     }       
//                 }                   
//             }
//         }
//     }        
//         
//     return image;
//         
// }


import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.util.Arrays;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularValueDecomposition;
import ij.IJ;
import ij.ImagePlus;
import jclustering.Voxel;
import static jclustering.MathUtils.getMaxIndex;
import static jclustering.Utils.RealMatrix2IJ;
            ImagePlus SVD_image = RealMatrix2IJ(result.transpose(), dim, 
                                                this.ip, 
                                                "SVD image");
            SVD_image.show();
        }
        
        // Please note: this is somehow incorrect. As the clustering model
        // that we are following needs one voxel -> one cluster, this step
        // below assigns each voxel to the principal component with the
        // maximum weight for its particular kinetics. In "real life", the
        // resulting images would contain the contribution of that component
        // in all voxels, but for segmentation purposes this approach is
        // chosen.
        int column_index = 0;        
        for (Voxel v : ip) {
                       
            double [] projection = result.getRow(column_index++);   
            
            // Every Voxel belongs to the maximum index of its projected TAC
            int max = getMaxIndex(projection) + 1;
            addTACtoCluster(v, max);            
        }
        
        // Fill in the additionalInfo array.
        additionalInfo = new String[2];
        additionalInfo[0] = "svd_v_matrix";        
        StringBuilder sb = new StringBuilder();
        int rows = svdv.getRowDimension();
        for (int j = 0; j < rows; j++) {
            double [] row = svdv.getRow(j);
// Path: src/main/java/jclustering/Voxel.java
// public class Voxel {
// 
//     /**
//      * X-coordinate for the voxel.
//      */
//     public final int x;
//     /**
//      * Y-coordinate for the voxel.
//      */
//     public final int y;
//     /**
//      * Slice (1-based) for the voxel.
//      */
//     public final int slice;
//     /**
//      * Time-activity curve.
//      */
//     public final double [] tac;
//     
//     /**
//      * Main constructor for this data transfer object
//      * @param x X-coordinate.
//      * @param y Y-coordinate.
//      * @param slice Slice number.
//      * @param tac Time-activity curve.
//      */
//     public Voxel(int x, int y, int slice, double [] tac) {
//         
//         this.x = x;
//         this.y = y;
//         this.slice = slice;
//         this.tac = tac;
//         
//     }
// 
// }
// 
// Path: src/main/java/jclustering/MathUtils.java
// public static int getMaxIndex(double[] d) {
// 
//     int res = 0;
//     double aux = d[0];
// 
//     for (int i = 0; i < d.length; i++) {
//         if (d[i] > aux) {
//             res = i;
//             aux = d[i];
//         }
//     }
// 
//     return res;
// }
// 
// Path: src/main/java/jclustering/Utils.java
// public static ImagePlus RealMatrix2IJ(RealMatrix rm, int [] dim, 
//         ImagePlusHyp ip, String name) {
//  // Get number of components
//     int components = rm.getRowDimension();
//         
//     // Create dynamic image
//     ImagePlus image = IJ.createImage(name, "32-bit", 
//                                          dim[0], dim[1],
//                                          dim[3] * components);
//     image.setDimensions(1, dim[3], components);
//     image.setOpenAsHyperStack(true);
//         
//     // Get stack for easy access
//     ImageStack is = image.getStack();
//         
//     int column_index = 0;
//         
//     // Assign voxels to values. It is important to iterate the image
//     // in the correct order (first x, then y, then slices), because
//     // that is the way the images are normally processed when using
//     // the ImagePlusHypIterator object.
//     for(int z = 0; z < dim[3]; z++) {
//         for(int y = 0; y < dim[1]; y++) {
//             for(int x = 0; x < dim[0]; x++) {
//                     
//                 // Test it the TAC is noise. If it is noise, 
//                 // jump to the next one
//                 double [] tac = ip.getTAC(x, y, z + 1);
//                     
//                 // Check for masked voxels                    
//                 if (!isMasked(tac, ip.CALZERO)) {
//                     // Not masked: get the next column
//                     double [] comp = rm.getColumn(column_index++);
//                         
//                     // Iterate through the component and set the values.
//                     // Each row of the component is in one frame.
//                     for (int t = 0; t < components; t++) {
//                         // Get internal slice number
//                         int sn = image.getStackIndex(1, z + 1, t + 1);
//                         is.setVoxel(x, y, sn - 1, comp[t]);                            
//                     }       
//                 }                   
//             }
//         }
//     }        
//         
//     return image;
//         
// }


// Path: src/main/java/jclustering/techniques/SVD.java
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.util.Arrays;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularValueDecomposition;
import ij.IJ;
import ij.ImagePlus;
import jclustering.Voxel;
import static jclustering.MathUtils.getMaxIndex;
import static jclustering.Utils.RealMatrix2IJ;

            ImagePlus SVD_image = RealMatrix2IJ(result.transpose(), dim, 
                                                this.ip, 
                                                "SVD image");
            SVD_image.show();
        }
        
        // Please note: this is somehow incorrect. As the clustering model
        // that we are following needs one voxel -> one cluster, this step
        // below assigns each voxel to the principal component with the
        // maximum weight for its particular kinetics. In "real life", the
        // resulting images would contain the contribution of that component
        // in all voxels, but for segmentation purposes this approach is
        // chosen.
        int column_index = 0;        
        for (Voxel v : ip) {
                       
            double [] projection = result.getRow(column_index++);   
            
            // Every Voxel belongs to the maximum index of its projected TAC
            int max = getMaxIndex(projection) + 1;
            addTACtoCluster(v, max);            
        }
        
        // Fill in the additionalInfo array.
        additionalInfo = new String[2];
        additionalInfo[0] = "svd_v_matrix";        
        StringBuilder sb = new StringBuilder();
        int rows = svdv.getRowDimension();
        for (int j = 0; j < rows; j++) {
            double [] row = svdv.getRow(j);
            sb.append(Arrays.toString(row));