Skip to content
Snippets Groups Projects
LineChartFunctionality.java 26.4 KiB
Newer Older
package com.application.GUI;

import com.application.DB.Constants;
import com.application.DB.Settings;
import com.application.GUI.PopUpWindows.NotificationPopUp;
import com.application.Main;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;

import org.apache.commons.math3.distribution.TDistribution;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import org.jblas.DoubleMatrix;
import org.jblas.Solve;
import java.text.SimpleDateFormat;
import static com.application.Main.*;
public class LineChartFunctionality {

    private static LineChart<String, Number> lineChart;
    private static XYChart.Series<String, Number> liveDataSeries;
    private static XYChart.Series<String, Number> regressionSeries;
    private static XYChart.Series<String, Number> regressionSeriesConfidenceInterval;
    private static CategoryAxis xAxis;
    private static NumberAxis yAxis;
    private static int dataPointsXAxis = 0;
    private static int dataPointsYAxis = 0;
    private static Map<String, Number> liveData;
    private static ArrayList<XYChart.Series<String, Number>> previousData;

    private static boolean printRegression;
    private static boolean printRegressionConfidenceInterval;
    private static boolean printLiveData;
    private static boolean printPreviousData;
        xAxis = new CategoryAxis();
        yAxis = new NumberAxis();
        lineChart = new LineChart<>(xAxis, yAxis);
        lineChart.setTitle("Drying Processes");
        lineChart.setAnimated(false);
        xAxis.setAnimated(false);
        yAxis.setAnimated(false);
        regressionSeries = new XYChart.Series<String, Number>();
        regressionSeriesConfidenceInterval = new XYChart.Series<String, Number>();
        liveDataSeries = new XYChart.Series<String, Number>();
        previousData = new ArrayList<>();

        printRegression = true;
        printRegressionConfidenceInterval = false;
        printLiveData = true;
        printPreviousData = true;
    /**
     * Prints the graphs to the line chart
     *
     * Note: Something wrong when exceeding 8 series, think the next series choose a random series color
     */
    public static void printGraphs() {
        if(isPrintRegressionConfidenceInterval()){
            updateLineChart(getRegressionSeriesConfidenceInterval());
            getMenuViewRegressionShadow().setSelected(true);
            getRegressionConfidenceIntervalBox().setSelected(true);
        } else {
            updateLineChart(new XYChart.Series<>());
            getMenuViewRegressionShadow().setSelected(false);
            getRegressionConfidenceIntervalBox().setSelected(false);
        if(isPrintRegression()){
            updateLineChart(getRegressionSeries());
            getMenuViewRegression().setSelected(true);
            getRegressionBox().setSelected(true);
        } else {
            updateLineChart(new XYChart.Series<>());
            getMenuViewRegression().setSelected(false);
            getRegressionBox().setSelected(false);
        if(isPrintLiveData()){
            updateLineChart(getLiveDataSeries());
            getMenuViewLiveData().setSelected(true);
            getLiveDataBox().setSelected(true);
        } else {
            updateLineChart(new XYChart.Series<>());
            getMenuViewLiveData().setSelected(false);
            getLiveDataBox().setSelected(false);
        if(isPrintPreviousData()){

            getPreviousBox().setSelected(true);
            getMenuViewPreviousData().setSelected(true);

            // If there are more than 5 series, adds 3 new empty series to keep the color scheme
            //int index = getLineChart().getData().size();
            for (int i = 0; i < getPreviousData().size(); i++) {
                int index = getLineChart().getData().size();
                //System.out.println(getPreviousData().size());
                if (index % 8 == 0 ){
                    for (int j = 0; j < 3; j++) {
                        updateLineChart(new XYChart.Series<>());
                        //index++;
                        System.out.println("@@@@@@@");
                    }
                }
                updateLineChart(getPreviousData().get(i));
            }
        } else {
            getPreviousBox().setSelected(false);
            getMenuViewPreviousData().setSelected(false);
    private static Map<Integer, ArrayList<Double>> statistics(Map<Integer, ArrayList<Double>> multiMap, boolean CIShadow){
        for (Map.Entry<Integer, ArrayList<Double>> entry : multiMap.entrySet()) {
            //System.out.printf("\nIndex: \t%s\t\t\tkWh: \t%s\n", entry.getKey(), entry.getValue());
            //System.out.println("entry: "+entry);
            //if(entry.getValue().size()>1){
                SummaryStatistics stats = new SummaryStatistics();
                for (double val : entry.getValue()) {
                    stats.addValue(val);
                }
            //System.out.println("Stats: "+stats);

                double ci = calcMeanCI(stats, Settings.CONFIDENCE_INTERVAL);
                //System.out.println(String.format("Mean: %f", stats.getMean()));
                double lower = stats.getMean() - ci;
                double upper = stats.getMean() + ci;
Eilert Tunheim's avatar
Eilert Tunheim committed
                //System.out.println(String.format("Confidence Interval "+ Settings.CONFIDENCE_INTERVAL*100+"%%: %f, %f", lower, upper));
                // Deletes entries if they are out of bounds with the confidence interval
                entry.getValue().removeIf(value -> Double.compare(value, lower) < 0 || Double.compare(value, upper) > 0);

                if(CIShadow){
                    ArrayList<Double> lowerUpperBounds = new ArrayList<>();
                    lowerUpperBounds.add(lower);
                    lowerUpperBounds.add(upper);
                    multiMap.replace(entry.getKey(), lowerUpperBounds);
                }
        }
        return multiMap;
    }

    private static double calcMeanCI(SummaryStatistics stats, double level) {
        try {
            // Create T Distribution with N-1 degrees of freedom
            TDistribution tDist = new TDistribution(stats.getN() - 1);
            // Calculate critical value
            double critVal = tDist.inverseCumulativeProbability(1.0 - (1 - level) / 2);
            // Calculate confidence interval
            return critVal * stats.getStandardDeviation() / Math.sqrt(stats.getN());
        } catch (MathIllegalArgumentException e) {
            return Double.NaN;
    public static LineChart<String, Number> loadSingleSeries(Map<Integer, Map<String, Number>> userInput) throws Exception {
        Map<Integer, ArrayList<Double>> multiMap = new HashMap<>();
        for (Map.Entry<Integer, Map<String, Number>> entryKwh : userInput.entrySet()) {
            Map data = entryKwh.getValue();
            //System.out.println(data.size());
            XYChart.Series<String, Number> newSeries = new XYChart.Series<String, Number>();
            for (Object entryData : data.entrySet()) {
                //System.out.println("data: \t"+entryData);
                String entryString = entryData.toString();
                String[] arr = entryString.split("=");
                String date = arr[0];
                Double kwhValue = Double.parseDouble(arr[1]);
                //System.out.printf("Date: \t%s\t\t\tkWh: \t%s\n",date,kwhValue);

                // Checks if the index already got an arraylist, if not one is created
                multiMap.computeIfAbsent(index, k -> new ArrayList<Double>());
                multiMap.get(index).add(kwhValue);

                // Connect the data to a series
                newSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue));
            //updateLineChart(newSeries);
        //System.out.println("Series size: "+allSeries.size());



        // Finds the end datapoint at the end of each graph
        int numberOfGraphs = 0;
        ArrayList<Double> dataArraylistXAxis = new ArrayList<>();
        ArrayList<Double> dataArraylistYAxis = new ArrayList<>();
        Map<Integer, ArrayList<Double>> endOfGraphPointsXAxis = new HashMap<>();
        Map<Integer, ArrayList<Double>> endOfGraphPointsYAxis = new HashMap<>();
        for (int i = 0; i < multiMap.size(); i++) {
            ArrayList<Double> list = multiMap.get(i);
            for (int j = 0; j < list.size(); j++) {
                if (numberOfGraphs < list.size()) {
                    numberOfGraphs = list.size();
                }
                if (list.size() < numberOfGraphs) {

                    dataArraylistXAxis.add((double) i);
                    dataArraylistYAxis.add(multiMap.get(i).get(j));
                    //System.out.println(tempList);

                    numberOfGraphs = list.size();
                }
            }
        }
        dataArraylistXAxis.add((double) multiMap.size());
        dataArraylistYAxis.add(multiMap.get(multiMap.size()-1).get(0));

        //System.out.println(dataArraylistYAxis);


        endOfGraphPointsXAxis.put(0,dataArraylistXAxis);
        endOfGraphPointsYAxis.put(0,dataArraylistYAxis);

        System.out.println(endOfGraphPointsXAxis);
        System.out.println(endOfGraphPointsYAxis);

        Map<Integer, ArrayList<Double>> endOfGraphPointsConfidenceXAxis = statistics(endOfGraphPointsXAxis,false);
        Map<Integer, ArrayList<Double>> endOfGraphPointsConfidenceYaxis = statistics(endOfGraphPointsYAxis,false);
        System.out.println("X-axis:"+ endOfGraphPointsConfidenceXAxis);
        System.out.println("X-axis size: "+ endOfGraphPointsConfidenceXAxis.size());
        System.out.println("------------");
        System.out.println("Y-axis:"+ endOfGraphPointsConfidenceYaxis);
        System.out.println("Y-axis size: "+ endOfGraphPointsConfidenceYaxis.size());
        System.out.println("------------");


        dataPointsXAxis = 0;
        for (Map.Entry<Integer, ArrayList<Double>> entry : endOfGraphPointsConfidenceXAxis.entrySet()) {
            System.out.println("Arraylist: "+ entry.getValue());
            for (int i = 0; i < entry.getValue().size(); i++) {
                System.out.println("End of graphs: "+ entry.getValue().get(i));
                dataPointsXAxis += entry.getValue().get(i);
            }
        }
        dataPointsXAxis = dataPointsXAxis /endOfGraphPointsConfidenceXAxis.get(0).size();

        System.out.println("Datapoints: " + dataPointsXAxis);

        dataPointsYAxis = 0;
        for (Map.Entry<Integer, ArrayList<Double>> entry : endOfGraphPointsConfidenceYaxis.entrySet()) {
            System.out.println("Arraylist: "+ entry.getValue());
            for (int i = 0; i < entry.getValue().size(); i++) {
                System.out.println("End of graphs: "+ entry.getValue().get(i));
                dataPointsYAxis += entry.getValue().get(i);
            }
        }
        dataPointsYAxis = dataPointsYAxis /endOfGraphPointsConfidenceYaxis.get(0).size();

        System.out.println("Datapoints Y-axis: " + dataPointsYAxis);


        // Stores the data from the confidence interval in a new map
        Map<Integer, ArrayList<Double>> confidenceIntervalData = statistics(multiMap,false);
        //getNonLinearRegression(confidenceIntervalData);

        // Checks the max size for the arraylists needed for the data array later
        int jMaxSize = 0;
        for (int i = 0; i < confidenceIntervalData.size(); i++) {
            if(confidenceIntervalData.get(i).size() > jMaxSize){
                jMaxSize = confidenceIntervalData.get(i).size();
            }
        }

        // Defines an array to be used for the regression
        double[][] data = new double[confidenceIntervalData.size()*jMaxSize][2];
        for (int i = 0; i < confidenceIntervalData.size(); i++) {
            ArrayList<Double> list = confidenceIntervalData.get(i);
            for (int j = 0; j < list.size(); j++) {
                data[index][0] = i;
                data[index][1] = list.get(j);
                index++;
        getRegressionSeriesConfidenceInterval().getData().clear();
        Map<Integer, ArrayList<Double>> confidenceIntervalShadow = statistics(multiMap,true);
        for ( Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalShadow.entrySet()) {
            for (int i = 0; i < entry.getValue().size(); i++) {
                Double doubleData = entry.getValue().get(i);
                getRegressionSeriesConfidenceInterval().getData().add(new XYChart.Data<String, Number>(String.valueOf(entry.getKey()), doubleData.intValue()));
            }
        }
        System.out.println(data.length);

        SimpleRegression simpleRegression = new SimpleRegression();

        simpleRegression.addData(data);
        //simpleRegression.regress();


        for (double[] datum : data) {
            //System.out.println("");
            for (double v : datum) {
        //updateLineChart(liveDataSeries);
        //XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>();
        getRegressionSeries().getData().clear();
        for (int i = 0; i <= getDataPointsXAxis(); i++) {

            // Connect the data to a series
            //System.out.println(simpleRegression.predict(i));
            //regressionSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(i), simpleRegression.predict(i)));
            regressionSeries.getData().add(new XYChart.Data<String, Number>(
                            String.valueOf(i),
                            getNonLinearRegression(
                                confidenceIntervalData,
                                getDataPointsYAxis(),
                                //simpleRegression.getIntercept(),
                                simpleRegression.getSlope(),
                                //simpleRegression.getIntercept()
                                getDataPointsYAxis(),
                                i,
                                    getDataPointsXAxis()
                            )));
            regressionSeries.getData().add(new XYChart.Data<String, Number>(
                    String.valueOf(i),
                    getCubicNonLinearRegression(confidenceIntervalData,i)
            ));
            getRegressionSeries().getData().add(new XYChart.Data<String, Number>(
                    String.valueOf(i),
                    getNonLinearRegression(
                            confidenceIntervalData,
                            Math.sqrt(Math.pow(simpleRegression.getIntercept(),2)),
                            simpleRegression.getSlope(),
                            i,
                            getDataPointsXAxis()
                    )));
        //updateLineChart(getRegressionSeries());
        getPreviousData().clear();
        for (Map.Entry<Integer, Map<String, Number>> entryKwh : userInput.entrySet()) {
            //System.out.println(data.size());
            XYChart.Series<String, Number> newSeries = new XYChart.Series<String, Number>();
            index = 0;
            for (Object entryData : entryKwh.getValue().entrySet()) {
                //System.out.println("data: \t"+entryData);
                String entryString = entryData.toString();
                Double kwhValue = Double.parseDouble(entryString.split("=")[1]);

                // Connect the data to a series
                newSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue));
                index++;
            }
            addPreviousData(newSeries);
            //allSeries.add(newSeries);
            //updateLineChart(newSeries);
            //lineChart.setOpacity(1);
        }




        System.out.println("Get R: " + simpleRegression.getR());
        System.out.println("Get getRSquare: " + simpleRegression.getRSquare());
        System.out.println("Get getRegressionSumSquares: " + simpleRegression.getRegressionSumSquares());

        System.out.println("Get N: " + simpleRegression.getN());

        // and then you can predict the time at a given temperature value
        System.out.println("Predicted Time: "  + simpleRegression.predict(35));

        // You can also get the slope and intercept from your data
        System.out.println("Alpha! = " + simpleRegression.getSlope());
        System.out.println("intercept = " + simpleRegression.getIntercept());

        //simpleRegression.add
        getTimeLeft(0);

    public static void loadLiveData(Map<String, Number> userInput) throws Exception {
        // Clears any data already there
        getLiveDataSeries().getData().clear();

        // Sets the livedata in series
        setLiveData(userInput);
        getTimeLeft(userInput.size());

        for (Map.Entry<String, Number> entryKwh : userInput.entrySet()) {
            int index = (int) (findDifference(Constants.START_TIME, entryKwh.getKey()) / 10);
            Double kwhValue = entryKwh.getValue().doubleValue();
            // Connect the data to a series
            getLiveDataSeries().getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue));
    private static long findDifference(String start_date, String end_date) {
        // Defining a simple date format
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try{
            // try to convert the string to Date datatype
            Date dateStart = dateFormat.parse(start_date);
            Date dateEnd = dateFormat.parse(end_date);

            // Finds the difference in millis
            long differenceMillis = dateEnd.getTime() - dateStart.getTime();

            // Finds the difference in minutes
            return (differenceMillis / (1000 * 60 )) % 60;

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return 0;
    }

    public static void getTimeLeft(int liveData){
        int minutes = 0;
        int hours = 0;

        if(liveData == 0) {
            minutes = getDataPointsXAxis()*10;
            minutes = (getDataPointsXAxis()/liveData)*10;
        if(minutes > 60){
            hours = minutes/60;
            Main.setTimeLeftText(hours + " h");
            if(hours == 3){
                NotificationPopUp.displayNotificationWindow("3 Hours Left!");}
        } else {
            if(minutes == 60){NotificationPopUp.displayNotificationWindow("1 Hours Left!");}
            Main.setTimeLeftText(minutes + " min");
        if(minutes == 0 && getDataPointsXAxis() != 0){
            NotificationPopUp.displayNotificationWindow("Drying Process Finished!");
    public static double getNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, double y0, double alpha, double j, double n) {
        //return Math.exp(intercept+slope*i)/(1+Math.exp(intercept+slope*i));

        double beta = 0.0;
        //double n = confidenceIntervalData.size();
        for (Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalData.entrySet()) {
            for (int i = 0; i < entry.getValue().size(); i++) {
                if(beta < entry.getValue().get(i)){
                    beta = entry.getValue().get(i);
        beta = getDataPointsYAxis()+y0;
        //System.out.println("Beta: " +beta);
        //System.out.println("y0: "+y0);


        //System.out.println("maxYValue: " + maxYValue);
        //System.out.println("j*n: "+j/n);

        //double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/(ADJUST_REGRESSION)))))-y0;      //Beste til nå
        double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/((alpha/10))))))-y0;      //Beste til nå
        //double p_t = (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*(j-n)))))-y0;      //Beste til nå
        System.out.println("---------------------------");
        System.out.println("y0: " + y0);
        System.out.println("Alpha: " + alpha);
        System.out.println("Beta: " + beta);

    /**
     * Third degree cubic non-linear regression
     *
     * n =
     *
     * sumT1 =
     * sumT2 =
     * sumT3 =
     * sumT4 =
     *
     * sumY =
     * sumYxT1=
     * sumYxT2 =
     *  @param confidenceIntervalData Data to process
     * @return
     */
    public static double getCubicNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, int index){

        double n = confidenceIntervalData.size();
        //double n = getDataPointsYAxis();
        //System.out.println(n);

        double sumT1 = 0;
        double sumT2 = 0;
        double sumT3 = 0;
        double sumT4 = 0;

        double sumY = 0;
        double sumYxT1 = 0;
        double sumYxT2 = 0;



        for (Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalData.entrySet()) {

            sumT1 += entry.getKey();
            sumT2 += Math.pow(entry.getKey(),2);
            sumT3 += Math.pow(entry.getKey(),3);
            sumT4 += Math.pow(entry.getKey(),4);

            for (int j = 0; j < entry.getValue().size(); j++) {

                sumY += entry.getValue().get(j);
                sumYxT1 += entry.getValue().get(j) * entry.getKey();
                sumYxT2 += entry.getValue().get(j) * Math.pow(entry.getKey(), 2);
            }
        }




/*
        for (Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalData.entrySet()) {



            for (int j = 0; j < entry.getValue().size(); j++) {

                sumT1 += Math.pow(entry.getValue().get(j), 1);
                sumT2 += Math.pow(entry.getValue().get(j), 2);
                sumT3 += Math.pow(entry.getValue().get(j), 3);
                sumT4 += Math.pow(entry.getValue().get(j), 4);

                sumY += entry.getKey();
                sumYxT1 += entry.getKey() * entry.getValue().get(j);
                sumYxT2 += entry.getKey() * Math.pow(entry.getValue().get(j), 2);
            }
        }

 */



        DoubleMatrix firstMatrix = new DoubleMatrix(new double[][]{{n,sumT1,sumT2},{sumT1,sumT2,sumT3},{sumT2,sumT3,sumT4}});
        DoubleMatrix secondMatrix = new DoubleMatrix( new double[]{sumY, sumYxT1, sumYxT2});


        DoubleMatrix solvedMatrix = Solve.solve(firstMatrix,secondMatrix);
        //System.out.println(solvedMatrix);

        //return ((solvedMatrix.get(0)) + (solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2)));
        //return ((solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2)))*(-1);
        return ((solvedMatrix.get(1) * index) + (solvedMatrix.get(2) * Math.pow(index, 2)));

    }

    public static int getDataPointsXAxis() {
        return dataPointsXAxis;
    }

    public static int getDataPointsYAxis() {
        return dataPointsYAxis;
    }

    public static Map<String, Number> getLiveData() {
        return liveData;
    }

    public static void setLiveData(Map<String, Number> input) {
        liveData = input;
    }

    public static XYChart.Series<String, Number> getLiveDataSeries() {
        return liveDataSeries;
    }

    public static void setRegressionSeries(XYChart.Series<String, Number> regressionSeries) {
        LineChartFunctionality.regressionSeries = regressionSeries;
    }

    public static XYChart.Series<String, Number> getRegressionSeries() {
        return regressionSeries;
    }

    public static boolean isPrintRegression() {
        return printRegression;
    }

    public static void setPrintRegression(boolean printRegression) {
        LineChartFunctionality.printRegression = printRegression;
    }

    public static boolean isPrintRegressionConfidenceInterval() {
        return printRegressionConfidenceInterval;
    }

    public static void setPrintRegressionConfidenceInterval(boolean printRegressionConfidenceInterval) {
        LineChartFunctionality.printRegressionConfidenceInterval = printRegressionConfidenceInterval;
    }

    public static boolean isPrintLiveData() {
        return printLiveData;
    }

    public static void setPrintLiveData(boolean printLiveData) {
        LineChartFunctionality.printLiveData = printLiveData;
    }

    public static boolean isPrintPreviousData() {
        return printPreviousData;
    }

    public static void setPrintPreviousData(boolean printPreviousData) {
        LineChartFunctionality.printPreviousData = printPreviousData;
    }

    public static ArrayList<XYChart.Series<String, Number>> getPreviousData() {
        return previousData;
    }

    public static void addPreviousData(XYChart.Series<String, Number> previousData) {
        LineChartFunctionality.previousData.add(previousData);
    }

    public static XYChart.Series<String, Number> getRegressionSeriesConfidenceInterval() {
        return regressionSeriesConfidenceInterval;
    }

    public static void setRegressionSeriesConfidenceInterval(XYChart.Series<String, Number> regressionSeriesConfidenceInterval) {
        LineChartFunctionality.regressionSeriesConfidenceInterval = regressionSeriesConfidenceInterval;
    }

    public static LineChart<String, Number> getLineChart() {
        return lineChart;
    }

    public static void updateLineChart(XYChart.Series<String, Number> series) {
        getLineChart().getData().add(series);
        series.getNode().setId("dataGraphs");
        getLineChart().getStylesheets().add(LineChartFunctionality.class.getResource("/com.application/GUI/graphStyles.css").toExternalForm());
    }

    public static void clearLineChart() {
        getLineChart().getData().clear();
        //lineChart.getData().
    }