web.diva.server.model.SomClustering.SomClustImgGenerator.java Source code

Java tutorial

Introduction

Here is the source code for web.diva.server.model.SomClustering.SomClustImgGenerator.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package web.diva.server.model.SomClustering;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;
import javax.swing.JLabel;
import no.uib.jexpress_modularized.core.dataset.AnnotationLibrary;
import no.uib.jexpress_modularized.core.dataset.AnnotationManager;
import no.uib.jexpress_modularized.core.dataset.Dataset;
import no.uib.jexpress_modularized.core.dataset.Group;
import no.uib.jexpress_modularized.core.visualization.colors.colorcomponents.ColorFactory;
import no.uib.jexpress_modularized.core.visualization.colors.ui.ScaleAndAxis;
import no.uib.jexpress_modularized.somclust.model.Node;
import org.apache.commons.codec.binary.Base64;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.encoders.ImageEncoder;
import org.jfree.chart.encoders.ImageEncoderFactory;
import org.jfree.chart.encoders.ImageFormat;
import web.diva.server.model.HeatmapColorFactory;
import web.diva.shared.beans.ClientClusterNode;
import web.diva.shared.beans.InteractiveColumnsResults;
import web.diva.shared.beans.SomClustTreeSelectionResult;
import web.diva.shared.beans.SplitedImg;

/**
 *
 * @author Yehia Farag
 */
public class SomClustImgGenerator {

    private TreeView upperTree, sideTree;
    private final Node rowNode, colNode;
    private final boolean gengenscale = false;
    private final Color GridCol = Color.DARK_GRAY;

    private final int squareW;//= 12;
    private final int squareL;//= 2;
    private final int LeftTreeWidth;//= 350;
    private final int TopTreeHeight = 70;
    private int LeftTreeHeight, TopTreeWidth;

    public int getLeftTreeHeight() {
        return LeftTreeHeight;
    }

    public int getTopTreeWidth() {
        return TopTreeWidth;
    }

    private final boolean ValueDistances = true;
    private HeatmapColorFactory colorFactory;
    private ColorFactory colors;
    private final java.text.NumberFormat numformat;

    public SomClustImgGenerator(Node rowNode, Node colNode, int rowNumber) {
        this.rowNode = rowNode;
        this.colNode = colNode;
        numformat = java.text.NumberFormat.getNumberInstance(java.util.Locale.US);
        numformat.setMaximumFractionDigits(3);
        numformat.setMinimumFractionDigits(1);
        if (rowNumber <= 1000) {
            squareL = 4;
            squareW = 12;
            LeftTreeWidth = 200;

        } else if (rowNumber <= 10000) {
            squareL = 4;
            squareW = 12;
            LeftTreeWidth = 300;

        }
        //        else if(rowNumber <= 20000){
        //        squareL = 4;
        //        squareW = 12;
        //        LeftTreeWidth = 500;       
        //        
        //        }
        else {
            squareL = 2;
            squareW = 12;
            LeftTreeWidth = 400;
        }

    }

    public int getSquareW() {
        return squareW;
    }

    public int getSquareL() {
        return squareL;
    }

    public TreeView getUpperTree() {
        return upperTree;
    }

    public TreeView getSideTree() {
        return sideTree;
    }

    public BufferedImage generateSideTree(Node root) {
        int verticalItems = countgenes(root);
        root.mark = true;
        sideTree = new TreeView(root, verticalItems, Color.WHITE, Color.BLACK);//"#e3e3e3"Color.decode("#e3e3e3")
        sideTree.leafdist = squareL;
        sideTree.actualLength = verticalItems;
        sideTree.leftmargin = (int) Math.round(squareL / 2);
        sideTree.drawframe = false;
        sideTree.valuedistances = true;
        sideTree.rightmargin = 0;
        sideTree.drawrects = false;
        sideTree.bottommargin = 0;
        //if(result!=null)
        sideTree.treewidth = LeftTreeWidth;
        sideTree.generatecoords();
        tooltipsSideNode = initToolTips(root, null);
        LeftTreeHeight = sideTree.getHeight();
        sideTreeBImg = sideTree.getImage();
        return (sideTreeBImg);

    }

    public String generateTopTree(Node toproot) {
        int horizontalItems = countgenes(toproot);
        toproot.mark = true;
        upperTree = new TreeView(toproot, horizontalItems, Color.WHITE, Color.black);//Color.decode("#e3e3e3")
        upperTree.leafdist = squareW;
        upperTree.actualLength = horizontalItems;
        upperTree.setHorizontal(false);
        upperTree.leftmargin = (int) Math.round(squareW / 2);
        upperTree.drawframe = false;
        upperTree.valuedistances = ValueDistances;
        upperTree.topmargin = 0;
        upperTree.drawrects = false;
        upperTree.bottommargin = 0;
        upperTree.rightmargin = 0;
        upperTree.treewidth = TopTreeHeight;
        upperTree.generatecoords();
        TopTreeWidth = upperTree.getWidth();
        tooltipsUpperNode = initToolTips(toproot, null);
        upperTreeBImg = upperTree.getImage();
        return this.generateEncodedImg(upperTreeBImg);

    }

    private ClientClusterNode tooltipsUpperNode;
    private ClientClusterNode tooltipsSideNode;
    private BufferedImage heatMapImg;

    public BufferedImage generateHeatMap(Dataset dataset, boolean clustColumn) {

        colorFactory = new HeatmapColorFactory();
        heatMapImg = null;
        if (clustColumn) {
            heatMapImg = new BufferedImage((upperTree.getWidth() + squareW), (sideTree.getHeight()),
                    BufferedImage.TYPE_INT_ARGB);
        } else {
            heatMapImg = new BufferedImage((dataset.getColumnIds().length * squareW + squareW),
                    (sideTree.getHeight()), BufferedImage.TYPE_INT_ARGB);
            TopTreeWidth = dataset.getColumnIds().length * squareW + squareW;

        }
        Graphics g = heatMapImg.getGraphics();
        g.setFont(getTableFont(12));
        drawSquares(g, new Point(0, 0), null, dataset, clustColumn);
        return heatMapImg;
    }

    public String getNavgStringImg() {
        return navgStringImg;
    }

    private String navgStringImg;
    private BufferedImage interactiveColumnImg;

    public InteractiveColumnsResults generateInteractiveColumn(Dataset dataset, int[] selection) {

        interactiveColumnImg = null;
        interactiveColumnImg = new BufferedImage(squareW + squareW, (sideTree.getHeight()),
                BufferedImage.TYPE_INT_ARGB);

        BufferedImage navgBackGroungImg = new BufferedImage(400, 10, BufferedImage.TYPE_INT_ARGB);
        Graphics navGr = navgBackGroungImg.getGraphics();
        int navUnit = (dataset.getDataLength() / 200) + 1;

        Graphics g = interactiveColumnImg.getGraphics();
        g.setFont(getTableFont(5));
        drawTable(g, new Point(0, 0), dataset, selection, navGr, navUnit);
        navgBackGroungImg = rotateImage(navgBackGroungImg, 180);
        navgStringImg = this.generateEncodedImg(navgBackGroungImg);
        InteractiveColumnsResults results = new InteractiveColumnsResults();
        results.setInteractiveColumn(splitImage(interactiveColumnImg));
        results.setNavgUrl(navgStringImg);
        return results;
    }

    public String generateScale(Dataset dataset, boolean clustColumn) {
        int W = 0;
        if (clustColumn) {
            W = (Math.min((upperTree.getWidth() + 21), 250));
        } else {
            W = (Math.min((dataset.getColumnIds().length * 12 + 21), 250));
        }
        BufferedImage nfo = new BufferedImage(W, 50, BufferedImage.TYPE_INT_ARGB);
        Graphics g = nfo.getGraphics();
        g.setFont(getTableFont(9));
        drawScale(g, new Point(0, 0), W, 30);
        return this.generateEncodedImg(nfo);

    }

    private Rectangle getSquaresBounds(Dataset dataset) {
        int[] upperArrangement = null;
        if (upperTree == null || upperTree.arrangement == null) {
            upperArrangement = new int[dataset.getDataWidth()];
        } else {
            upperArrangement = upperTree.arrangement;
        }
        if (upperArrangement == null || sideTree == null) {
            return new Rectangle(0, 0);
        }
        return new Rectangle(upperArrangement.length * squareW + 1, (sideTree.actualLength * squareL) + 1);
    }

    private void drawScale(Graphics scale, Point st, int width, int height) {
        Rectangle r = new Rectangle(st.x, st.y, width, height);
        if (width < 50 || height < 25) {
            return;
        }
        ScaleAndAxis sc = new ScaleAndAxis();
        sc.setColorFactory(colors);
        scale.translate(st.x, st.y);
        Rectangle bac = scale.getClipBounds();
        sc.setLocation(r.x, r.y);
        sc.setSize(r.width, r.height);
        sc.paintComponent(scale);
        scale.setClip(bac);
        scale.translate(-st.x, -st.y);
    }

    //    public String exportToImgGraphics(boolean clustColumn){
    //        int totalWidth = sideTreeBImg.getWidth()+ heatMapImg.getWidth()+interactiveColumnImg.getWidth();
    //        int totalHeight = 0;
    //        totalHeight = sideTree.getImage().getHeight();
    //        if (clustColumn) {
    //            totalHeight += TopTreeHeight;
    //        }
    //
    //        BufferedImage clusteringImage = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);
    //        Graphics gg = clusteringImage.getGraphics();
    //        Graphics2D g2d = (Graphics2D)gg;
    //        g2d.setBackground(Color.WHITE);
    ////        gg.translate(sideTree.getImage().getWidth(), 0);
    //        gg.drawImage(upperTreeBImg, sideTreeBImg.getWidth(), 0, null);
    //        gg.drawImage(sideTreeBImg, 0,upperTreeBImg.getHeight(), null);
    //        gg.drawImage(heatMapImg, sideTreeBImg.getWidth(), upperTreeBImg.getHeight(), null);
    //        gg.drawImage(interactiveColumnImg, sideTreeBImg.getWidth() + heatMapImg.getWidth(),upperTreeBImg.getHeight(), null);
    //        System.out.println("start the new drawer for clustering");
    //        try {
    //            ImageIO.write(clusteringImage, "PNG", new File("C:\\Users\\y-mok_000\\Desktop", "img.png"));
    //        } catch(Exception exp){exp.printStackTrace();}
    //        
    //        
    //        return "";
    //    }

    public BufferedImage getHeatMapImg() {
        return heatMapImg;
    }

    public BufferedImage getInteractiveColumnImg() {
        return interactiveColumnImg;
    }

    public BufferedImage getSideTreeBImg() {
        return sideTreeBImg;
    }

    public BufferedImage getUpperTreeBImg() {
        return upperTreeBImg;
    }

    private void drawSquares(Graphics squares, Point start, Rectangle bounds, Dataset dataset,
            boolean clusterColumns) {
        //        ColorFactory colors = ColorFactoryList.getInstance().getActiveColorFactory(dataset);
        colors = colorFactory.getActiveColorFactory(dataset);
        Rectangle view = getSquaresBounds(dataset);
        squares.translate(start.x, start.y);
        int rows = this.countgenes(this.rowNode);
        int counter = 0;
        double[] gengenscalevals = null;
        int[] upperArrangement = null;
        if (clusterColumns) {
            upperArrangement = upperTree.arrangement;
        } else {
            upperArrangement = new int[dataset.getColumnIds().length];
            for (int x = 0; x < dataset.getColumnIds().length; x++)
                upperArrangement[x] = x;
        }
        double[][] dat = null;
        dat = dataset.getData();
        if (sideTree == null) {
            return;
        }
        for (int i = 0; i < sideTree.arrangement.length; i++) {
            double v = 0;
            Rectangle sqr = new Rectangle(0, 0, squareW, squareL);
            for (int j = 0; j < upperArrangement.length; j++) {
                if (bounds == null || bounds.intersects((j * squareW), (i * squareL), squareW, squareL)) {

                    if (upperTree != null) {

                        sqr.setLocation((j * squareW), (i * squareL));
                        if (!view.intersects(sqr)) {
                            continue;
                        }

                        if (sideTree.arrangement[i] != -1 && upperArrangement[j] != -1) {

                            if (dataset.isMissing(sideTree.arrangement[i], upperArrangement[j])) {
                                squares.setColor(colors.getMissing());
                            } else {
                                if (!gengenscale) {
                                    v = dat[sideTree.arrangement[i]][upperArrangement[j]];
                                    squares.setColor(colors.getColor(v));
                                } else {
                                    v = gengenscalevals[upperArrangement[j]];
                                    squares.setColor(colors.getColor(v));
                                }
                            }
                            squares.fillRect((j * squareW), (i * squareL), squareW, squareL);
                        }
                    } else {
                        sqr.setLocation((j * squareW), (i * squareL));
                        if (!view.intersects(sqr)) {
                            continue;
                        }

                        v = dat[sideTree.arrangement[i]][upperArrangement[j]];

                        if (dataset.isMissing(sideTree.arrangement[i], upperArrangement[j])) {
                            squares.setColor(colors.getMissing());
                        } else {
                            squares.setColor(colors.getColor(v));
                        }

                        squares.fillRect((j * squareW), (i * squareL), squareW, squareL);
                    }
                }
            }
            counter++;
            if (counter == rows) {
                break;
            }
        }
        counter = 0;
        if (true) {
            squares.setColor(GridCol);
            for (int i = 0; i < sideTree.arrangement.length + 1; i++) {
                if (bounds == null
                        || bounds.intersects(0, i * squareL, upperArrangement.length * squareW, i * squareL)) {
                    squares.drawLine(0, i * squareL, (upperArrangement.length * squareW) + 0, i * squareL);
                }
                counter++;
                if (counter > rows) {
                    break;
                }
            }
            for (int j = 0; j < upperArrangement.length; j++) {
                if (bounds == null || bounds.intersects(j * squareW, 0, j * squareW, rows * squareL)) {
                    squares.drawLine(j * squareW, 0, j * squareW, rows * squareL);
                }
            }

            if (bounds == null || bounds.intersects(upperArrangement.length * squareW, 0,
                    upperArrangement.length * squareW, rows * squareL)) {
                squares.drawLine(upperArrangement.length * squareW, 0, upperArrangement.length * squareW,
                        rows * squareL);
            }

        }
        squares.translate(-start.x, -start.y);
    }

    private int[] Wd;
    private int[] WdSUM;

    public void drawTable(Graphics gr, Point UL, Dataset dataset, int[] selection, Graphics navgGr,
            int countNavUnit) {

        Font f = getTableFont(squareL - 1);
        AnnotationManager annManager = AnnotationManager.getAnnotationManager();
        String[] rowIds = dataset.getRowIds();

        Set<String> annotations = dataset.getRowAnnotationNamesInUse();
        if (annotations == null) {
            annotations = annManager.getManagedRowAnnotationNames();
        }

        String[][] inf; // row annotation matrix
        String[] headers; // header of the row annotation matrix
        if (annotations.isEmpty()) {
            inf = new String[dataset.getDataLength()][1];
            for (int i = 0; i < inf.length; i++) {
                inf[i][0] = rowIds[i];
            }
            headers = new String[] { "Row ID" };
        } else {
            headers = annotations.toArray(new String[annotations.size()]);
            inf = new String[dataset.getDataLength()][annotations.size()];
            for (int i = 0; i < headers.length; i++) {
                //ann manager need to re implemeinted?
                AnnotationLibrary anns = annManager.getRowAnnotations(headers[i]);
                for (int j = 0; j < inf.length; j++) {
                    inf[j][i] = rowIds[j];//anns.getAnnotation(rowIds[j]);//
                }
            }
        }

        Graphics2D g2d = (Graphics2D) gr;
        Graphics2D g2dNav = (Graphics2D) navgGr;
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2dNav.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        int X = UL.x;
        int Y = UL.y;
        //        int H = squareL;

        int L = dataset.getDataLength();
        int W = headers.length;

        JLabel l = new JLabel("    ");
        JLabel lNav = new JLabel(" ");
        //        l.setFont(f);
        //        l.setIconTextGap(2);
        javax.swing.border.Border UB = javax.swing.BorderFactory.createMatteBorder(0, 0, 0, 0, Color.WHITE);
        javax.swing.border.Border LB = javax.swing.BorderFactory.createMatteBorder(0, 0, 0, 0, Color.WHITE);

        //          Color borderColor = hex2Rgb("#e3e3e3");
        javax.swing.border.Border navBorder = javax.swing.BorderFactory.createMatteBorder(2, 0, 0, 0, Color.WHITE);

        l.setMaximumSize(new Dimension(200, squareL));
        lNav.setSize(new Dimension(2, 5));
        lNav.setBorder(navBorder);

        boolean drawTableHeader = false;

        //if there is not enough room for a header.. skip header.
        //        if (UL.y < squareL) {
        //            drawTableHeader = false;
        //        }

        if (Wd == null) {
            Wd = new int[inf[0].length];
            WdSUM = new int[inf[0].length];

            if (drawTableHeader) {
                for (int i = 0; i < headers.length; i++) {
                    l.setText(headers[i]);
                    l.validate();
                    if (l.getPreferredSize().width > Wd[i]) {
                        Wd[i] = l.getPreferredSize().width + 16;
                    }
                }
            }
            for (String[] inf1 : inf) {
                for (int j = 0; j < Wd.length; j++) {
                    if (squareL < 6) {
                        Wd[j] = 5;
                        continue;
                    }
                    l.setText(inf1[j]);
                    l.validate();
                    if (l.getPreferredSize().width > Wd[j]) {
                        Wd[j] = l.getPreferredSize().width + 16;
                    }
                }
            }

            WdSUM[0] = 0;

            for (int i = 0; i < Wd.length; i++) {
                WdSUM[i] = -1;
                for (int j = 0; j < i; j++) {
                    WdSUM[i] += Wd[j] + 3;
                }
            }
        }

        Rectangle BNDS = new Rectangle();

        l.setBackground(Color.WHITE);
        l.setOpaque(true);

        lNav.setBackground(Color.WHITE);
        lNav.setOpaque(true);

        if (sideTree == null) {
            return;
        }

        f = getTableFont(squareL - 1);
        l.setFont(f);

        int[] LArr = sideTree.arrangement;
        int Rindex = 0;

        //draw the table header.. (if wanted)
        //        if (drawTableHeader) {
        //
        //            l.setBackground(Color.WHITE);
        //            l.setForeground(Color.white);
        //
        //            for (int j = 0; j < W; j++) {
        //                X = UL.x + WdSUM[j];
        //                Y = UL.y;
        //                BNDS.setBounds(X, Y, Wd[j], squareL + 1);
        //
        //                if (gr.getClipBounds() != null && !gr.getClipBounds().intersects(BNDS)) {
        //                    continue;
        //                }
        //                gr.translate(X, Y);
        //                l.setBounds(0, 0, Wd[j] + 1, squareL + 1);
        //                l.setBorder(LB);
        //
        //                if (squareL >= 6) {
        //                    l.setText(headers[j]);
        //                }
        //                l.validate();
        //                l.paint(gr);
        //                gr.translate(-X, -Y);
        //            }
        //        }
        l.setForeground(Color.WHITE);

        boolean[] sel = selectedRows((selection == null ? null : selection), dataset);
        boolean coloredNav = false;
        int navCounter = 0;
        for (int i = 0; i < L; i++) {

            Rindex = LArr[i];
            for (int j = 0; j < W; j++) {
                X = UL.x + WdSUM[j];
                Y = UL.y + (squareL * (i + 1));

                BNDS.setBounds(X, Y, Wd[j], squareL + 1);

                if (gr.getClipBounds() != null && !gr.getClipBounds().intersects(BNDS)) {
                    continue;
                }

                if (sel[LArr[i]]) {

                    for (Group group : dataset.getRowGroups()) {
                        if (group.isActive()) {
                            if (group.hasMember(Rindex)) {
                                l.setBackground(group.getColor());
                                if (!coloredNav) {
                                    lNav.setBackground(Color.RED);
                                    lNav.setForeground(Color.RED);
                                    coloredNav = true;
                                }

                                break;

                            }
                        }

                    }

                    //                    l.setBackground(new Color(225, 225, 255));
                } else {
                    //                   
                    //                    if (!coloredNav) {
                    //                                    lNav.setBackground(Color.WHITE);
                    //                                    lNav.setForeground(Color.WHITE);                                  
                    //                                }

                    l.setBackground(Color.WHITE);
                }
                if (i != 0)
                    gr.translate(X, Y);
                l.setBounds(0, 0, Wd[j] + 1, squareL + 1);

                if (i < L - 1) {
                    l.setBorder(UB);
                } else {
                    l.setBounds(0, 0, Wd[j] + 1, squareL + 1);
                    l.setBorder(LB);
                }
                if (squareL >= 6) {
                    l.setText(inf[Rindex][j]);
                }
                l.validate();
                l.paint(gr);
                gr.translate(-X, -Y);

            }
            if (navCounter >= countNavUnit) {
                navCounter = 0;
                lNav.validate();
                lNav.paint(navgGr);
                navgGr.translate(2, 0);
                coloredNav = false;
                lNav.setBackground(Color.WHITE);
                lNav.setForeground(Color.WHITE);

            }
            navCounter++;
        }

        //        if (squareL < 6) {
        //            return;
        //        }
        //
        //        l.setBackground(Color.WHITE);
        //        f = getTableFont(squareL - 2);
        //        //f = new Font("Arial",1,squareL-2);
        //        l.setFont(f);
        //
        //
        //        for (int j = 0; j < W; j++) {
        //            X = UL.x + WdSUM[j];
        //            Y = UL.y;
        //
        //            BNDS.setBounds(X, Y, Wd[j], squareL + 1);
        //            if (gr.getClipBounds() != null && !gr.getClipBounds().intersects(BNDS)) {
        //                continue;
        //            }
        //
        //            gr.translate(X, Y);
        //            l.setBounds(0, 0, Wd[j], squareL + 1);
        ////            l.setBorder(javax.swing.BorderFactory.createLineBorder(GridCol));
        //            l.setText(headers[j]);
        //            l.validate();
        //            gr.translate(-X, -Y);
        //        }

    }

    private boolean[] selectedRows(int[] selectedRows, Dataset dataset) {
        boolean[] ret = new boolean[dataset.getDataLength()];
        if (selectedRows != null) {
            for (int i = 0; i < selectedRows.length; i++) {
                ret[selectedRows[i]] = true;
            }
        }
        //        for (int i = 0; i < draggedOverIndices.size(); i++) {
        //            ret[((Integer) draggedOverIndices.elementAt(i)).intValue()] = true;
        //        }
        return ret;
    }

    private Font getTableFont(int size) {
        Font f;
        f = new Font("Sans Serif", 0, size);
        return f.deriveFont((float) size);
    }

    public int countgenes(Node trunk) {
        java.util.Stack c = new java.util.Stack();
        int ret = 0;
        c.push(trunk);
        Node tr = trunk;

        if (trunk == null) {
            System.out.print("\n!No trunk\n");
        }

        while (!c.empty()) {
            tr = (Node) c.pop();

            if (tr.merged) {
                c.push(tr.left);
                c.push(tr.right);
            } else {
                ret++;
            }
        }

        return ret;
    }

    public Node getNodeAt(int xcor, int ycor, Node trunk) {
        Node ret = null;

        if (trunk != null) {

            if (trunk.getx() > xcor - squareL && trunk.getx() < xcor + squareL && trunk.gety() > ycor - squareL
                    && trunk.gety() < ycor + squareL) {
                ret = trunk;
            } else {
                ret = getNodeAt(xcor, ycor, trunk.right);
            }
            if (ret == null) {
                ret = getNodeAt(xcor, ycor, trunk.left);
            }
        }

        return ret;
    }

    private String generateEncodedImg(BufferedImage upperTreeBImage) {
        String sideTreeBase64 = "";
        try {
            ImageEncoder in = ImageEncoderFactory.newInstance(ImageFormat.PNG, 0);

            byte[] imageData = in.encode(upperTreeBImage);
            sideTreeBase64 = Base64.encodeBase64String(imageData);
            sideTreeBase64 = "data:image/png;base64," + sideTreeBase64;
            System.gc();
        } catch (IOException exp) {
            System.err.println(exp.getLocalizedMessage());
        }
        return sideTreeBase64;
    }

    private BufferedImage sideTreeBImg;

    public SomClustTreeSelectionResult updateSideTreeSelection(int x, int y, double w, double h) {
        sideTreeBImg = sideTree.getImage();
        SomClustTreeSelectionResult result = new SomClustTreeSelectionResult();
        Node n = this.getNodeAt(x, y, rowNode);
        if (n != null) {
            sideTree.painttree(n, sideTreeBImg.getGraphics(), Color.red);
            Stack st = new Stack();
            Vector v = new Vector();
            n.fillMembers(v, st);
            int[] sel = new int[v.size()];
            for (int i = 0; i < v.size(); i++) {
                sel[i] = ((Integer) v.elementAt(i));
            }
            result.setSelectedIndices(sel);
        }
        //        try {
        //            byte[] imageData = ChartUtilities.encodeAsPNG(sideTreeBImg);
        //            String base64 = Base64.encodeBase64String(imageData);
        //            base64 = "data:image/png;base64," + base64;
        SplitedImg si = this.splitImage(sideTreeBImg);
        result.setTreeImg1Url(si.getImg1Url());
        result.setTreeImg(si);
        System.gc();

        return result;

        //        } catch (IOException e) {
        //            System.err.println(e.getLocalizedMessage());
        //        }
        //        return null;

    }

    private BufferedImage upperTreeBImg;

    public SomClustTreeSelectionResult updateUpperTreeSelection(int x, int y, double w, double h) {
        upperTreeBImg = upperTree.getImage();
        Node n = this.getNodeAt(y, x, colNode);
        SomClustTreeSelectionResult result = new SomClustTreeSelectionResult();
        if (n != null) {
            upperTree.painttree(n, upperTreeBImg.getGraphics(), Color.red);

            Stack st = new Stack();
            Vector v = new Vector();
            n.fillMembers(v, st);
            int[] sel = new int[v.size()];
            for (int i = 0; i < v.size(); i++) {
                sel[i] = ((Integer) v.elementAt(i));
            }
            result.setSelectedIndices(sel);
        }
        try {
            byte[] imageData = ChartUtilities.encodeAsPNG(upperTreeBImg);
            String base64 = Base64.encodeBase64String(imageData);
            base64 = "data:image/png;base64," + base64;
            result.setTreeImg1Url(base64);

            System.gc();

            //            result.setTreeImgUrl(navgStringImg);

            return result;
        } catch (IOException e) {
            System.err.println(e.getLocalizedMessage());
        }
        return null;

    }

    private ClientClusterNode initToolTips(Node root, ClientClusterNode parent) {
        if (root != null) {
            ClientClusterNode clientClusterNode = new ClientClusterNode();
            clientClusterNode.setMembers(root.members);
            clientClusterNode.setX(root.getx());
            clientClusterNode.setY(root.gety());
            clientClusterNode.setName(root.nme + "");
            try {
                clientClusterNode.setValue(Double.valueOf(numformat.format(root.value)));
            } catch (Exception e) {
                System.out.println(e.getLocalizedMessage());
                clientClusterNode.setValue(root.value);
            }
            clientClusterNode.setParent(parent);
            clientClusterNode.setRight(initToolTips(root.right, clientClusterNode));
            clientClusterNode.setLeft(initToolTips(root.left, clientClusterNode));
            return clientClusterNode;
        } else {
            return null;
        }

    }

    public ClientClusterNode getTooltipsUpperNode() {
        return tooltipsUpperNode;
    }

    public ClientClusterNode getTooltipsSideNode() {
        return tooltipsSideNode;
    }

    public int getLeftTreeWidth() {
        return LeftTreeWidth;
    }

    public int getTopTreeHeight() {
        return TopTreeHeight;
    }

    /**
    *
    * @param colorStr e.g. "#FFFFFF"
    * @return
    */
    private Color hex2Rgb(String colorStr) {
        return new Color(Integer.valueOf(colorStr.substring(1, 3), 16),
                Integer.valueOf(colorStr.substring(3, 5), 16), Integer.valueOf(colorStr.substring(5, 7), 16));
    }

    private BufferedImage rotateImage(BufferedImage masterImage, int angle) {
        int virtualAngle = getVirtualAngle(angle);
        Dimension size = new Dimension(masterImage.getWidth(), masterImage.getHeight());
        int masterWidth = masterImage.getWidth();
        int masterHeight = masterImage.getHeight();

        double x = 0; //masterWidth / 2.0;
        double y = 0; //masterHeight / 2.0;

        switch (virtualAngle) {
        case 0:
            break;
        case 180:
            break;
        case 90:
        case 270:
            size = new Dimension(masterImage.getHeight(), masterImage.getWidth());
            x = (masterHeight - masterWidth) / 2.0;
            y = (masterWidth - masterHeight) / 2.0;
            break;
        }
        BufferedImage renderedImage = new BufferedImage(size.width, size.height, masterImage.getTransparency());
        Graphics2D g2d = renderedImage.createGraphics();

        AffineTransform at = AffineTransform.getTranslateInstance(x, y);

        at.rotate(Math.toRadians(virtualAngle), masterWidth / 2.0, masterHeight / 2.0);
        g2d.drawImage(masterImage, at, null);

        g2d.dispose();
        return renderedImage;
    }

    protected int getVirtualAngle(int angle) {
        float fRotations = (float) angle / 360f;
        int rotations = (int) (fRotations - (fRotations / 1000));

        int virtual = angle - (rotations * 360);

        if (virtual < 0) {
            virtual = 360 + virtual;
        }

        return virtual;
    }

    public SplitedImg splitImage(BufferedImage img) {
        int imgHeight1 = (img.getHeight() / 4);

        BufferedImage bf1 = img.getSubimage(0, 0, img.getWidth(), imgHeight1);
        String str1 = this.generateEncodedImg(bf1);

        //     int imgHeight2 = img.getHeight()-imgHeight1;
        BufferedImage bf2 = img.getSubimage(0, imgHeight1, img.getWidth(), imgHeight1);
        String str2 = this.generateEncodedImg(bf2);

        BufferedImage bf3 = img.getSubimage(0, (2 * imgHeight1), img.getWidth(), imgHeight1);
        String str3 = this.generateEncodedImg(bf3);

        int imgHeight2 = img.getHeight() - (3 * imgHeight1);

        BufferedImage bf4 = img.getSubimage(0, (3 * imgHeight1), img.getWidth(), imgHeight2);
        String str4 = this.generateEncodedImg(bf4);

        SplitedImg si = new SplitedImg();
        si.setHeightFirst(imgHeight1);
        si.setHeightLast(imgHeight2);

        si.setImg1Url(str1);
        si.setImg2Url(str2);
        si.setImg3Url(str3);
        si.setImg4Url(str4);

        return si;

    }

}