From 938647b779c3e1b3692c236de98233fbe9c40b11 Mon Sep 17 00:00:00 2001
From: Eilert Tunheim <emtunhei@stud.ntnu.no>
Date: Thu, 19 May 2022 00:37:38 +0200
Subject: [PATCH] commented linechart class

---
 .../GUI/LineChartFunctionality.java           | 385 +++++-------------
 1 file changed, 91 insertions(+), 294 deletions(-)

diff --git a/src/main/java/com/application/GUI/LineChartFunctionality.java b/src/main/java/com/application/GUI/LineChartFunctionality.java
index 93593a3..53bdb00 100644
--- a/src/main/java/com/application/GUI/LineChartFunctionality.java
+++ b/src/main/java/com/application/GUI/LineChartFunctionality.java
@@ -21,6 +21,12 @@ import java.util.*;
 
 import static com.application.Main.*;
 
+/**
+ * This class handle all the GUI functionality and statistics calculations
+ *
+ * @author Eilert Tunheim, Karin Pettersen, Mads Arnesen
+ * @version 1.0.0
+ */
 public class LineChartFunctionality {
 
     private static LineChart<String, Number> lineChart;
@@ -39,6 +45,7 @@ public class LineChartFunctionality {
     private static boolean printLiveData;
     private static boolean printPreviousData;
 
+    // Constructor
     public LineChartFunctionality() {
         xAxis = new CategoryAxis();
         yAxis = new NumberAxis();
@@ -63,7 +70,7 @@ public class LineChartFunctionality {
 
 
     /**
-     * Prints the graphs to the line chart
+     * Prints the selected graphs to the line chart
      *
      * Note: Something wrong when exceeding 8 series, think the next series choose a random series color
      */
@@ -107,15 +114,11 @@ public class LineChartFunctionality {
             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));
@@ -127,103 +130,102 @@ public class LineChartFunctionality {
     }
 
 
-
+    /**
+     * This function calculates the confidence interval
+     *
+     * @param multiMap input containing the drying cycle data
+     * @param CIShadow input to indicate if the confidence interval shadow is stored or not
+     * @return a map containing the processed data
+     */
     private static Map<Integer, ArrayList<Double>> statistics(Map<Integer, ArrayList<Double>> multiMap, boolean CIShadow){
 
-        //System.out.println("\n\nMultimap: \n");
+        // Iterates through all the data
         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();
+                SummaryStatistics data = new SummaryStatistics();
                 for (double val : entry.getValue()) {
-                    stats.addValue(val);
+                    data.addValue(val);
                 }
 
-            //System.out.println("Stats: "+stats);
-
-                // Calculate 95% confidence interval
-                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;
-                //System.out.println(String.format("Confidence Interval "+ Settings.CONFIDENCE_INTERVAL*100+"%%: %f, %f", lower, upper));
+                // Calculate the confidence interval
+                double confidenceInterval = calcMeanConfidenceInterval(data);
+                double lower = data.getMean() - confidenceInterval;
+                double upper = data.getMean() + confidenceInterval;
 
                 // 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);
 
+                // Checks if the confidence interval shall be returned or not
                 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) {
+    /**
+     * This function calculates the confidence interval mean value
+     *
+     * @param data the data to base the calculation on
+     * @return returns the confidence interval mean value
+     */
+    private static double calcMeanConfidenceInterval(SummaryStatistics data) {
         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());
+            // Create a T distribution
+            TDistribution tDistribution = new TDistribution(data.getN() - 1);
+            // Calculate the critical value
+            double criticalValue = tDistribution.inverseCumulativeProbability(1.0 - (1 - Settings.CONFIDENCE_INTERVAL) / 2);
+            // Calculate the confidence interval
+            return criticalValue * data.getStandardDeviation() / Math.sqrt(data.getN());
         } catch (MathIllegalArgumentException e) {
             return Double.NaN;
         }
     }
 
+    /**
+     * This function serves as the main function that controls all the functionality.
+     * This function takes the data inputted and plots it and calculates the statistics.
+     *
+     * @param userInput data regarding the drying cycles
+     * @throws Exception throws exception if an error occurs
+     */
+    public static void loadSingleSeries(Map<Integer, Map<String, Number>> userInput) throws Exception {
 
-    public static LineChart<String, Number> loadSingleSeries(Map<Integer, Map<String, Number>> userInput) throws Exception {
+        // Clears the linechart if there are previous graphs plotted
         clearLineChart();
 
-
+        // Defining a map to store data
         Map<Integer, ArrayList<Double>> multiMap = new HashMap<>();
 
+        // Iterates through the data
         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>();
             int index = 0;
             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));
                 index++;
             }
-            //allSeries.add(newSeries);
-            //updateLineChart(newSeries);
-            //lineChart.setOpacity(1);
         }
 
-        //System.out.println("Series size: "+allSeries.size());
-
-
-
         // Finds the end datapoint at the end of each graph
         int numberOfGraphs = 0;
 
+        // Defines lists to store data
         ArrayList<Double> dataArraylistXAxis = new ArrayList<>();
         ArrayList<Double> dataArraylistYAxis = new ArrayList<>();
-
         Map<Integer, ArrayList<Double>> endOfGraphPointsXAxis = new HashMap<>();
         Map<Integer, ArrayList<Double>> endOfGraphPointsYAxis = new HashMap<>();
 
+        // Iterates through the data
         for (int i = 0; i < multiMap.size(); i++) {
             ArrayList<Double> list = multiMap.get(i);
             for (int j = 0; j < list.size(); j++) {
@@ -231,11 +233,8 @@ public class LineChartFunctionality {
                     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();
                 }
             }
@@ -243,56 +242,33 @@ public class LineChartFunctionality {
         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("------------");
-
-
+        // X-axis
         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);
-
+        // Y-axis
         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++) {
@@ -301,23 +277,20 @@ public class LineChartFunctionality {
             }
         }
 
-
-        // Defines an array to be used for the regression
+        // Defines an array to be used for the linear regression
         double[][] data = new double[confidenceIntervalData.size()*jMaxSize][2];
 
         int index = 0;
-        //System.out.println(confidenceIntervalData);
         for (int i = 0; i < confidenceIntervalData.size(); i++) {
-
             ArrayList<Double> list = confidenceIntervalData.get(i);
-
-            for (int j = 0; j < list.size(); j++) {
+            for (Double aDouble : list) {
                 data[index][0] = i;
-                data[index][1] = list.get(j);
+                data[index][1] = aDouble;
                 index++;
             }
         }
 
+        // Adds the data to the confidence interval shadow
         getRegressionSeriesConfidenceInterval().getData().clear();
         Map<Integer, ArrayList<Double>> confidenceIntervalShadow = statistics(multiMap,true);
         for ( Map.Entry<Integer, ArrayList<Double>> entry : confidenceIntervalShadow.entrySet()) {
@@ -327,59 +300,14 @@ public class LineChartFunctionality {
             }
         }
 
-        System.out.println(data.length);
-        //System.out.println(data[12][1]);
-
+        // Does the linear regression
         SimpleRegression simpleRegression = new SimpleRegression();
-
         simpleRegression.addData(data);
-        //simpleRegression.regress();
-
-
-        for (double[] datum : data) {
-            //System.out.println("");
-            for (double v : datum) {
-                //System.out.println("Data: "+v);
-            }
-        }
 
-
-        //updateLineChart(liveDataSeries);
-
-
-        //XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>();
+        // Does the logistic regression
         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(
@@ -389,21 +317,14 @@ public class LineChartFunctionality {
                             i,
                             getDataPointsXAxis()
                     )));
-
-
         }
-        //updateLineChart(getRegressionSeries());
-        //lineChart.setOpacity(1);
-
-
 
+        // Adds the previous data to series
         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]);
 
@@ -412,36 +333,17 @@ public class LineChartFunctionality {
                 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);
-
         printGraphs();
-
-        return getLineChart();
     }
 
+    /**
+     * This function loads the live data and plots the data in the graph
+     *
+     * @param userInput the input parameter for the live data
+     * @throws Exception throws an exception if an error occur
+     */
     public static void loadLiveData(Map<String, Number> userInput) throws Exception {
 
         // Clears any data already there
@@ -466,6 +368,13 @@ public class LineChartFunctionality {
         }
     }
 
+    /**
+     * Finds the difference between two dates
+     *
+     * @param start_date input parameter for the first date
+     * @param end_date input parameter for the second date
+     * @return returns the differnce in minutes
+     */
     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");
@@ -487,11 +396,19 @@ public class LineChartFunctionality {
         return 0;
     }
 
+    /**
+     * This function calculates the remaining time of the current drying cycle
+     *
+     * @param liveData input parameter for the data to base the calculations on
+     */
     public static void getTimeLeft(int liveData){
+
+        // Defines variables
         int minutes = 0;
         int hours = 0;
 
         if(liveData == 0) {
+            // There are 10 minutes between each datapoint
             minutes = getDataPointsXAxis()*10;
 
         } else {
@@ -512,135 +429,22 @@ public class LineChartFunctionality {
     }
 
 
-    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);
-        //System.out.println(p_t);
-
-         */
-
-
-
-        return p_t;
-
-    }
-
-
     /**
-     * Third degree cubic non-linear regression
+     * This function handles the logistic regression
      *
-     * n =
-     *
-     * sumT1 =
-     * sumT2 =
-     * sumT3 =
-     * sumT4 =
-     *
-     * sumY =
-     * sumYxT1=
-     * sumYxT2 =
-     *  @param confidenceIntervalData Data to process
-     * @return
+     * @param confidenceIntervalData the input parameter for the data to base the regression on
+     * @param y0 the input parameter for the intercept from the linear regression
+     * @param alpha the input parameter for the slope value from the linear regression
+     * @param j the input parameter for current x-axis datapoint to predict the value for
+     * @param n the input parameter for the total number of points along the x-axis
+     * @return the predicted value at a given point
      */
-    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 double getNonLinearRegression(Map<Integer, ArrayList<Double>> confidenceIntervalData, double y0, double alpha, double j, double n) {
+        double beta = getDataPointsYAxis()+y0;
+        return (((beta * y0))/(y0 +((beta- y0)*Math.exp(-alpha*j/n/((alpha/10))))))-y0;
     }
 
+
     public static int getDataPointsXAxis() {
         return dataPointsXAxis;
     }
@@ -661,10 +465,8 @@ public class LineChartFunctionality {
         return liveDataSeries;
     }
 
-    public static void setRegressionSeries(XYChart.Series<String, Number> regressionSeries) {
-        LineChartFunctionality.regressionSeries = regressionSeries;
-    }
 
+    // Getters and setters
     public static XYChart.Series<String, Number> getRegressionSeries() {
         return regressionSeries;
     }
@@ -713,10 +515,6 @@ public class LineChartFunctionality {
         return regressionSeriesConfidenceInterval;
     }
 
-    public static void setRegressionSeriesConfidenceInterval(XYChart.Series<String, Number> regressionSeriesConfidenceInterval) {
-        LineChartFunctionality.regressionSeriesConfidenceInterval = regressionSeriesConfidenceInterval;
-    }
-
     public static LineChart<String, Number> getLineChart() {
         return lineChart;
     }
@@ -729,6 +527,5 @@ public class LineChartFunctionality {
 
     public static void clearLineChart() {
         getLineChart().getData().clear();
-        //lineChart.getData().
     }
 }
-- 
GitLab