/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.cnr.iasi.giant.thread;

import it.cnr.iasi.giant.Main;
import it.cnr.iasi.giant.frame.RoleRegionsWindow;
import it.cnr.iasi.giant.util.ColorNodeUtil;
import it.cnr.iasi.giant.util.ComputeParticipationCoefficient;
import it.cnr.iasi.giant.util.ComputeZScore;
import it.cnr.iasi.giant.util.Helper;
import java.awt.Color;
import java.awt.Dimension;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitorInputStream;
import org.cytoscape.application.CyApplicationManager;
import org.cytoscape.model.*;
import org.cytoscape.model.CyTableFactory.InitialTableSize;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.presentation.property.BasicVisualLexicon;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYShapeRenderer;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 *
 * @author Fabio Cumbo
 * @info GIANT
 * @version v1.0
 * @organization IASI-CNR : Istituto di Analisi dei Sistemi ed Informatica 
 *                  "Antonio Ruberti" - Consiglio Nazionale delle Ricerche
 * 
 */
public class ComputePZThread extends Thread {
    
    private static File file;
    private static Object[][] percRegionData = new Object[][] {};
    private static Object[][] reportRegionsData = new Object[][] {};  
    final CyApplicationManager manager = Main.getGiantAdapter().getCyApplicationManager();
    final CyNetworkView networkView = manager.getCurrentNetworkView();
    
    public ComputePZThread(String clusterFilePath) {
        super(clusterFilePath);
        file = new File(clusterFilePath);
    }
    
    @Override
    public void run() {
        try {
            System.out.println("Starting Thread (PZ)");
            JFrame frame = new JFrame();
            frame.setVisible(true);
            frame.setAlwaysOnTop(true);
            try {
                InputStream fstream = new FileInputStream(file.getAbsolutePath());
                    InputStream fstreamMonitor = new ProgressMonitorInputStream(frame, "Loading...", fstream);
                    DataInputStream in = new DataInputStream(fstreamMonitor); 
                    BufferedReader br = new BufferedReader(new InputStreamReader(in));
                frame.setVisible(false);
                                
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(ClusterLoaderThread.class.getName()).log(Level.SEVERE, null, ex);
                }
                
                String strLine;
                
                try {
                    
                    double sum_R1 = 0.0;
                    double sum_R2 = 0.0;
                    double sum_R3 = 0.0;
                    double sum_R4 = 0.0;
                    double sum_R5 = 0.0;
                    double sum_R6 = 0.0;
                    double sum_R7 = 0.0;
                    
                    ColorNodeUtil colorUtil = new ColorNodeUtil();
                    
                    HashMap<String, ArrayList<Double>> _pz = new HashMap<String, ArrayList<Double>>();
                    int columns = AttributesLoaderThread.getAttrib_header().size()+8;
                    reportRegionsData = new Object[NetworkLoaderThread.getDegreeMap().keySet().size()][columns];
                    int count = 0;
                    
                    String attRegion = "Region", attP = "Participation Coefficient", attZ = "Z Score";
                    CyTable table = Main.getGiantAdapter().getCyTableFactory().createTable("GIANTtable", "name", String.class, true, true);
                    table.createColumn(attRegion, String.class, false);
                    table.createColumn(attP, String.class, false);
                    table.createColumn(attZ, String.class, false);
                    
                    /*CyNetwork currentNet = Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork();
                    currentNet.getDefaultNodeTable().createColumn(attRegion, String.class, false);
                    currentNet.getDefaultNodeTable().createColumn(attP, String.class, false);
                    currentNet.getDefaultNodeTable().createColumn(attZ, String.class, false);*/
                                        
                    while ((strLine = br.readLine()) != null) {
                        Helper helper = new Helper();
                        ArrayList<String> cluster = helper.tabPattern(strLine);
                        
                        for (String node: cluster) {
                            
                            double _P = ComputeParticipationCoefficient.compute(node, cluster);
                            double _Z = ComputeZScore.compute(node, cluster);
                            
                            double degree = NetworkLoaderThread.getDegreeMap().get(node).size();
                            double inClusterDegree = ComputeZScore.getInClusterDegree();
                            ComputeZScore.setInClusterDegree(0);
                            
                            reportRegionsData[count][0] = node;
                            reportRegionsData[count][1] = degree;
                            reportRegionsData[count][2] = inClusterDegree;
                            if (_Z<2.5 && _P<0.05) {
                                sum_R1++;
                                reportRegionsData[count][3] = "R1";
                                
                                reportRegionsData[count][4] = "NON-HUB";
                                reportRegionsData[count][5] = "Ultra-peripheral node";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R1"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R1");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R1");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z<2.5 && (_P>0.05 && _P<0.625)) {
                                sum_R2++;
                                reportRegionsData[count][3] = "R2";
                                
                                reportRegionsData[count][4] = "NON-HUB";
                                reportRegionsData[count][5] = "Peripheral node";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R2"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R2");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R2");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z<2.5 && (_P>0.625 && _P<0.8)) {
                                sum_R3++;
                                reportRegionsData[count][3] = "R3";
                                
                                reportRegionsData[count][4] = "NON-HUB";
                                reportRegionsData[count][5] = "Non-hub connector";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R3"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R3");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R3");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z<2.5 && _P>0.8) {
                                sum_R4++;
                                reportRegionsData[count][3] = "R4";
                                
                                reportRegionsData[count][4] = "NON-HUB";
                                reportRegionsData[count][5] = "Non-hub kinless node";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R4"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R4");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R4");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z>2.5 && _P<0.3) {
                                sum_R5++;
                                reportRegionsData[count][3] = "R5";
                                
                                reportRegionsData[count][4] = "HUB";
                                reportRegionsData[count][5] = "Provincial hub";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R5"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R5");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R5");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z>2.5 && (_P>0.3 && _P<0.75)) {
                                sum_R6++;
                                reportRegionsData[count][3] = "R6";
                                
                                reportRegionsData[count][4] = "HUB";
                                reportRegionsData[count][5] = "Connector hub";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R6"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R6");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R6");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            else if (_Z>2.5 && _P>0.75) {
                                sum_R7++;
                                reportRegionsData[count][3] = "R7";
                                
                                reportRegionsData[count][4] = "HUB";
                                reportRegionsData[count][5] = "Kinless hub";
                                
                                //SET NODE COLOR
                                networkView.getNodeView(getNode(node)).setVisualProperty(
                                        BasicVisualLexicon.NODE_FILL_COLOR, colorUtil.getPaint("R7"));
                                
                                CyRow row = table.getRow(node);
                                row.set(attRegion, "R7");
                                row.set(attP, String.valueOf(_P));
                                row.set(attZ, String.valueOf(_Z));
                                
                                /*currentNet.getDefaultNodeTable().getRow(node).set("Region", "R7");
                                currentNet.getDefaultNodeTable().getRow(node).set("Participation Coefficient", String.valueOf(_P));
                                currentNet.getDefaultNodeTable().getRow(node).set("Z Score", String.valueOf(_Z));*/
                            }
                            
                            if (AttributesLoaderThread.getAttributesNumber() > 0) {
                                try {
                                    int last = 5;
                                    ArrayList<String> att = AttributesLoaderThread.getAttributes().get(node);
                                    for (int k=0; k<att.size(); k++) {
                                        reportRegionsData[count][last+1] = att.get(k);
                                        last++;
                                    }
                                } catch (NullPointerException e) {
                                    int last = 5;
                                    for (int k=0; k<AttributesLoaderThread.getAttributesNumber(); k++) {
                                        reportRegionsData[count][last+1] = "";
                                        last++;
                                    }
                                }
                                
                            }
                            
                            reportRegionsData[count][columns-2] = _P;
                            reportRegionsData[count][columns-1] = _Z;
                            
                            ArrayList<Double> data = new ArrayList<Double>();
                            data.add(_P);
                            data.add(_Z);
                            _pz.put(node, data);
                            count++;
                        }
                        
                    }
                    
                    List<CyTable> targetTables = new ArrayList<CyTable>();
                    CyNetwork currentNetwork = Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork();
                    targetTables.add(currentNetwork.getDefaultNodeTable());
                    mapAll(targetTables, table);
                    
                    
                    plotDistribution("", _pz);
                                        
                    br.close();
                    in.close();
                    fstreamMonitor.close();
                    fstream.close();
                    
                    //OPEN REPORT WINDOW
                    new RoleRegionsWindow().setVisible(true);
                    
                    percRegionData = new Object[1][8];
                    percRegionData[0][0] = "%";
                    percRegionData[0][1] = (((double)((sum_R1 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][2] = (((double)((sum_R2 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][3] = (((double)((sum_R3 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][4] = (((double)((sum_R4 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][5] = (((double)((sum_R5 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][6] = (((double)((sum_R6 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    percRegionData[0][7] = (((double)((sum_R7 * 100)/NetworkLoaderThread.getDegreeMap().keySet().size())));
                    
                    RoleRegionsWindow.setRPerc_data(percRegionData);
                    RoleRegionsWindow.setNode2R_data(reportRegionsData, AttributesLoaderThread.getAttrib_header());
                    
                    if (Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork()!=null || !Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork().getNodeList().isEmpty()) {
                        if (!ClusterLoaderThread.getClustersData().isEmpty()) {
                            Main.getApp().getComputePZ_button().setEnabled(true);
                        }
                    }
                    
                    Main.getGiantAdapter().getCyApplicationManager().getCurrentNetworkView().updateView();
                    
                    System.err.println("Z excluded set: " + ComputeZScore.getExcluded());
                    System.err.println("P excluded set: " + ComputeParticipationCoefficient.getExcluded());
                    
                }
                catch (NullPointerException e) { 
                    JOptionPane.showMessageDialog(Main.getApp().getFrameOverride(), "INTERNAL ERROR FOR COMPUTE PZ THREAD", "ERROR!", JOptionPane.ERROR_MESSAGE);
                    //e.printStackTrace();
                    br.close();
                    in.close();
                    fstreamMonitor.close();
                    fstream.close();
                }
            }
            catch (FileNotFoundException e ){
                //e.printStackTrace();
            }
        } catch (IOException e) { 
            JOptionPane.showMessageDialog(Main.getApp().getFrameOverride(), "INTERNAL ERROR FOR COMPUTE PZ THREAD", "ERROR!", JOptionPane.ERROR_MESSAGE);
            //e.printStackTrace();
        }
    }
    
    private void plotDistribution(String title, HashMap<String, ArrayList<Double>> _pz) {
        ColorNodeUtil util = new ColorNodeUtil();
        HashMap<String, XYDataset> datasets = createDataset(_pz);
        JFreeChart chart = createChart(null, "Participation coefficient, P", "Within-module degree, Z", title);
        
        XYPlot xyPlot = (XYPlot) chart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R1"))) {
            XYItemRenderer rend1 = new XYShapeRenderer();
            xyPlot.setDataset(0, datasets.get("R1")); 
            rend1.setSeriesPaint(0, util.getPaint("R1"));
            xyPlot.setRenderer(0, rend1);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R2"))) {
            XYItemRenderer rend2 = new XYShapeRenderer();
            xyPlot.setDataset(1, datasets.get("R2"));
            rend2.setSeriesPaint(1, util.getPaint("R2"));
            xyPlot.setRenderer(1, rend2);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R3"))) {
            XYItemRenderer rend3 = new XYShapeRenderer();
            xyPlot.setDataset(2, datasets.get("R3"));
            rend3.setSeriesPaint(2, util.getPaint("R3"));
            xyPlot.setRenderer(2, rend3);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R4"))) {
            XYItemRenderer rend4 = new XYShapeRenderer();
            xyPlot.setDataset(3, datasets.get("R4"));
            rend4.setSeriesPaint(3, util.getPaint("R4"));
            xyPlot.setRenderer(3, rend4);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R5"))) {
            XYItemRenderer rend5 = new XYShapeRenderer();
            xyPlot.setDataset(4, datasets.get("R5"));
            rend5.setSeriesPaint(4, util.getPaint("R5"));
            xyPlot.setRenderer(4, rend5);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R6"))) {
            XYItemRenderer rend6 = new XYShapeRenderer();
            xyPlot.setDataset(5, datasets.get("R6"));
            rend6.setSeriesPaint(5, util.getPaint("R6"));
            xyPlot.setRenderer(5, rend6);
        }
        
        if (!DatasetUtilities.isEmptyOrNull(datasets.get("R7"))) {
            XYItemRenderer rend7 = new XYShapeRenderer();
            xyPlot.setDataset(6, datasets.get("R7"));
            rend7.setSeriesPaint(6, util.getPaint("R7"));
            xyPlot.setRenderer(6, rend7);
        }
        
        ChartPanel chartPanel = new ChartPanel(chart);
        
        chartPanel.setPreferredSize(new java.awt.Dimension(450, 280));

        JFrame frame = new JFrame("Participation coefficient P vs Within-module degree z");
        frame.setSize(new Dimension(500, 350));
        frame.setContentPane(chartPanel);
        frame.setVisible(true);
    }
    
    private HashMap<String, XYDataset> createDataset(HashMap<String, ArrayList<Double>> _pz) {
        HashMap<String, XYDataset> result = new HashMap<String, XYDataset>();
        XYSeries series_r1 = new XYSeries("R1");
        XYSeries series_r2 = new XYSeries("R2");
        XYSeries series_r3 = new XYSeries("R3");
        XYSeries series_r4 = new XYSeries("R4");
        XYSeries series_r5 = new XYSeries("R5");
        XYSeries series_r6 = new XYSeries("R6");
        XYSeries series_r7 = new XYSeries("R7");
                
        //0 : P
        //1 : Z
        for (String arr: _pz.keySet()) {
            if (_pz.get(arr).get(0)!=Double.POSITIVE_INFINITY && _pz.get(arr).get(1)!=Double.POSITIVE_INFINITY &&
                _pz.get(arr).get(0)!=Double.NEGATIVE_INFINITY && _pz.get(arr).get(1)!=Double.NEGATIVE_INFINITY &&
                _pz.get(arr).get(0)!=Double.NaN && _pz.get(arr).get(1)!=Double.NaN) {
                
                if (_pz.get(arr).get(1)<2.5 && _pz.get(arr).get(0)<0.05) {
                    series_r1.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)<2.5 && (_pz.get(arr).get(0)>0.05 && _pz.get(arr).get(0)<0.625)) {
                    series_r2.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)<2.5 && (_pz.get(arr).get(0)>0.625 && _pz.get(arr).get(0)<0.8)) {
                    series_r3.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)<2.5 && _pz.get(arr).get(0)>0.8) {
                    series_r4.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)>2.5 && _pz.get(arr).get(0)<0.3) {
                    series_r5.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)>2.5 && (_pz.get(arr).get(0)>0.3 && _pz.get(arr).get(0)<0.75)) {
                    series_r6.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
                else if (_pz.get(arr).get(1)>2.5 && _pz.get(arr).get(0)>0.75) {
                    series_r7.add(_pz.get(arr).get(0), _pz.get(arr).get(1));
                }
            }
            System.out.println(arr + ":\t" + "P=" + _pz.get(arr).get(0) + "\t" + "Z=" + _pz.get(arr).get(1));
        }
        
        XYSeriesCollection dataset_r1 = new XYSeriesCollection();
        dataset_r1.addSeries(series_r1);
        result.put("R1", dataset_r1);
        
        XYSeriesCollection dataset_r2 = new XYSeriesCollection();
        dataset_r2.addSeries(series_r2);
        result.put("R2", dataset_r2);
        
        XYSeriesCollection dataset_r3 = new XYSeriesCollection();
        dataset_r3.addSeries(series_r3);
        result.put("R3", dataset_r3);
        
        XYSeriesCollection dataset_r4 = new XYSeriesCollection();
        dataset_r4.addSeries(series_r4);
        result.put("R4", dataset_r4);
        
        XYSeriesCollection dataset_r5 = new XYSeriesCollection();
        dataset_r5.addSeries(series_r5);
        result.put("R5", dataset_r5);
        
        XYSeriesCollection dataset_r6 = new XYSeriesCollection();
        dataset_r6.addSeries(series_r6);
        result.put("R6", dataset_r6);
        
        XYSeriesCollection dataset_r7 = new XYSeriesCollection();
        dataset_r7.addSeries(series_r7);
        result.put("R7", dataset_r7);
        
        return result;
    }

	private JFreeChart createChart(XYDataset dataset, String xTitle, String yTitle, String title) {
    
	    // create the chart...
	    JFreeChart chart = ChartFactory.createXYLineChart(
	        title,      // chart title
	        xTitle,                      // x axis label
	        yTitle,                      // y axis label
	        dataset,                  // data
	        PlotOrientation.VERTICAL,
	        true,                     // include legend
	        true,                     // tooltips
	        false                     // urls
	    );
	
	    // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
	    chart.setBackgroundPaint(Color.white);
	
	//    final StandardLegend legend = (StandardLegend) chart.getLegend();
	//      legend.setDisplaySeriesShapes(true);
	    
	    // get a reference to the plot for further customisation...
	    XYPlot plot = chart.getXYPlot();
	    plot.setBackgroundPaint(Color.lightGray);
	//    plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
	    plot.setDomainGridlinePaint(Color.white);
	    plot.setRangeGridlinePaint(Color.white);
            
	    XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
	    renderer.setSeriesLinesVisible(0, false);
	    renderer.setSeriesShapesVisible(1, false);
	    plot.setRenderer(renderer);
	
	    // change the auto tick unit selection to integer units only...
	    NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
	    rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
	    // OPTIONAL CUSTOMISATION COMPLETED.
	            
            return chart;
    
	}
        
        public static Object[][] getNode2RegionData() {
            return reportRegionsData;
        }
        
        public static Object[][] getPercRegionsData() {
            return percRegionData;
        }
    
        private static CyNode getNode(String node) {
        for (org.cytoscape.model.CyNode n: Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork().getNodeList()) {
            if (Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork().getRow(n).get(CyNetwork.NAME, String.class).equals(node))
                return n;
        }
        return null;
    }

    private void mapAll(List<CyTable> targetTables, CyTable newTable) {
        if (targetTables.isEmpty())
            return;
        if (newTable.getPrimaryKey().getType() != String.class)
            throw new IllegalStateException("The new table's primary key is not of type String!");
        String sourceTableJoinColumn = newTable.getPrimaryKey().getName();
        for (CyTable targetTable: targetTables)
            targetTable.addVirtualColumns(newTable, sourceTableJoinColumn, false);
    }
        
}
