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