From db3057c1de1ca173a231eb1d7534fd684ea18338 Mon Sep 17 00:00:00 2001 From: Eilert Tunheim <emtunhei@stud.ntnu.no> Date: Fri, 22 Apr 2022 11:02:07 +0200 Subject: [PATCH] Implemented linear regression and fixed splitting process into two threads --- .../java/com/application/DB/Constants.java | 6 +-- src/main/java/com/application/DB/DB.java | 45 ++++++++++++++++++ .../com/application/GUI/InputPopUpWindow.java | 38 ++++++++++++++- .../GUI/LineChartFunctionality.java | 37 +++++++++----- .../com/application/DB/Constants.class | Bin 6026 -> 5925 bytes .../GUI/LineChartFunctionality.class | Bin 10227 -> 9859 bytes 6 files changed, 109 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/application/DB/Constants.java b/src/main/java/com/application/DB/Constants.java index 7455cef..8ca102c 100644 --- a/src/main/java/com/application/DB/Constants.java +++ b/src/main/java/com/application/DB/Constants.java @@ -43,7 +43,7 @@ public final class Constants { public static final String VALASEN_START_DRYING_NAME = "DryingStarted"; public static final String VALASEN_STOP_DRYING_NAME = "CalculatedStop"; public static final String VALASEN_KILIN_NAME = "KilnName"; - public static int VALASEN_KILIN_ID = 5; // Kammer 5 + //public static int VALASEN_KILIN_ID = 5; // Kammer 5 //public static int VALASEN_KILIN_ID = 6; // Kammer 6 public static final int VALASEN_LIMIT = 1000; public static final ArrayList<Integer> VALASEN_VALMETICS_CHAMBER_IDS = new ArrayList<>(Arrays.asList(5,6)); @@ -52,7 +52,7 @@ public final class Constants { public static final String VALASEN_KWH_NAME = "VariantValue"; public static final String VALASEN_TIMESTAMP_NAME = "Timestamp"; public static final String VALASEN_VALUE_ID_NAME = "ValueID"; - public static final int VALASEN_VALUE_ID = 51; // Kammer 5 + //public static final int VALASEN_VALUE_ID = 51; // Kammer 5 //public static final int VALASEN_VALUE_ID = 56; // Kammer 6 public static final ArrayList<Integer> VALASEN_KWH_CHAMBER_IDS = new ArrayList<>(Arrays.asList(51,56)); @@ -131,7 +131,7 @@ public final class Constants { valasenWinccsensordataParameters.put("KwhName", VALASEN_KWH_NAME); valasenWinccsensordataParameters.put("Timestamp", VALASEN_TIMESTAMP_NAME); valasenWinccsensordataParameters.put("ValueIDName", VALASEN_VALUE_ID_NAME); - valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID)); + //valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID)); //valasenWinccsensordataParameters.put("ValueID", String.valueOf(VALASEN_VALUE_ID)); return valasenWinccsensordataParameters; } diff --git a/src/main/java/com/application/DB/DB.java b/src/main/java/com/application/DB/DB.java index c588236..5bd3abf 100644 --- a/src/main/java/com/application/DB/DB.java +++ b/src/main/java/com/application/DB/DB.java @@ -319,6 +319,51 @@ public class DB { } + + /** + * + * + * @throws Exception + */ + /* + public static void getManualMeasurements() throws Exception { + + // Sqlstatement + final String sqlStatement = ""; + + System.out.println(sqlStatement); + + // Retrieves the results from the queryjob + TableResult result = createQueryJob(sqlStatement); + + //System.out.println("InTidTork\t\t\tUtTidTork"); + // Iterating through the results + for (FieldValueList row : result.iterateAll()) { + + row.get("DryingStarted").getTimestampValue(); + } + + // Defining a treemap to sort the data incrementally + //NavigableMap<String, String> sortedFinalResults = new TreeMap<>(dates); + + System.out.println("\n"); + + for (Map.Entry<String, String> entry : sortedFinalResults.entrySet()) { + System.out.printf("Intid: \t%s\t\t\tUttid: \t%s\n",entry.getKey(),entry.getValue()); + } + + + + //System.out.printf("Size of dates: %s\n\n", sortedFinalResults.size()); + + + // Returns a treemap that sorts the dates incrementally + //return new TreeMap<>(sortedFinalResults); + } + */ + + + /** * Retrieves information about kWh and the corresponding date * diff --git a/src/main/java/com/application/GUI/InputPopUpWindow.java b/src/main/java/com/application/GUI/InputPopUpWindow.java index a0ac17b..a6f477a 100644 --- a/src/main/java/com/application/GUI/InputPopUpWindow.java +++ b/src/main/java/com/application/GUI/InputPopUpWindow.java @@ -1,5 +1,6 @@ package com.application.GUI; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Pos; @@ -9,6 +10,7 @@ import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.stage.*; +import java.util.Map; import java.util.concurrent.*; import static com.application.DB.Constants.*; @@ -171,7 +173,7 @@ public class InputPopUpWindow { */ - +/* try { //getData(); @@ -186,6 +188,10 @@ public class InputPopUpWindow { ); + */ + + + @@ -215,6 +221,31 @@ public class InputPopUpWindow { */ + // Fungerende ny thread!!@@@@@ + try{ + Thread thread = new Thread(() -> { + try { + // Henter her data fra databasen + Map<Integer, Map<String, Number>> data = setInputParameters(); + Platform.runLater(() -> { + try { + loadSingleSeries(data); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + thread.start(); + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + ); /* // Fungerende ny thread!!@@@@@ try{ @@ -239,8 +270,11 @@ public class InputPopUpWindow { } ); + */ + + + - */ /* class KwhThread implements Runnable { diff --git a/src/main/java/com/application/GUI/LineChartFunctionality.java b/src/main/java/com/application/GUI/LineChartFunctionality.java index d5d3eb9..52057b8 100644 --- a/src/main/java/com/application/GUI/LineChartFunctionality.java +++ b/src/main/java/com/application/GUI/LineChartFunctionality.java @@ -1,5 +1,6 @@ package com.application.GUI; +import javafx.collections.ObservableList; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; @@ -9,6 +10,7 @@ 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.apache.commons.math3.*; import java.util.*; @@ -17,7 +19,6 @@ public class LineChartFunctionality { private static LineChart<String, Number> lineChart; private static CategoryAxis xAxis; private static NumberAxis yAxis; - private static final double CONFIDENCE_INTERVAL = 0.90; @@ -89,7 +90,9 @@ public class LineChartFunctionality { public static LineChart<String, Number> loadSingleSeries(Map<Integer, Map<String, Number>> userInput) throws Exception { - clearLineChart(); + //clearLineChart(); + //newSeries.setData(null); + Map<Integer, ArrayList<Double>> multiMap = new HashMap<>(); @@ -113,12 +116,15 @@ public class LineChartFunctionality { // Connect the data to a series newSeries.getData().add(new XYChart.Data<String, Number>(String.valueOf(index), kwhValue)); - index += 1; + index++; } + //allSeries.add(newSeries); updateLineChart(newSeries); - lineChart.setOpacity(0.5); + //lineChart.setOpacity(1); } + //System.out.println("Series size: "+allSeries.size()); + // Stores the data from the confidence interval in a new map Map<Integer, ArrayList<Double>> confidenceIntervalData = statistics(multiMap); @@ -132,18 +138,21 @@ public class LineChartFunctionality { // Defines an array to be used for the regression - double[][] data = new double[confidenceIntervalData.size()][jMaxSize]; + 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); - System.out.println(list.size()); for (int j = 0; j < list.size(); j++) { - data[i][j] = list.get(j); + data[index][0] = i; + data[index][1] = list.get(j); + index++; } + /* for (int j = 0; j < data[i].length; j++) { System.out.println("data[i][j]: "+data[i][j]); if(data[i][j] == 0.0){ @@ -159,11 +168,13 @@ public class LineChartFunctionality { data[i][j] = sum/index; } } + + */ } System.out.println(data.length); - System.out.println(data[12][1]); + //System.out.println(data[12][1]); SimpleRegression simpleRegression = new SimpleRegression(); @@ -172,23 +183,25 @@ public class LineChartFunctionality { for (double[] datum : data) { - System.out.println(""); for (double v : datum) { - System.out.println(v); + System.out.println("Data: "+v); } } XYChart.Series<String, Number> regressionSeries = new XYChart.Series<String, Number>(); - for (int i = 0; i < simpleRegression.getN(); i++) { + for (int i = 0; i < confidenceIntervalData.size(); 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))); } updateLineChart(regressionSeries); - lineChart.setOpacity(1); + //lineChart.setOpacity(1); + + + System.out.println("Get R: " + simpleRegression.getR()); System.out.println("Get getRSquare: " + simpleRegression.getRSquare()); diff --git a/target/classes/com/application/DB/Constants.class b/target/classes/com/application/DB/Constants.class index 935d57ead8c7405cef6220d66de39651a4d10b64..8bcc60db79a0dd82c0be6154885ac50fd17b0884 100644 GIT binary patch delta 2167 zcmeCuU#eGs>ff$?3=9k=40pL0EEsy(8Tz;wm_T$t7lSFo1TF>^hKV4NNg&o_5HW>= zVJb*u8i+HUgJA}Up2@*5i-Tb{2g4i=hPfOJ^Eephb1*F6U|7h-u!vzXCj$$^5)Ou? z91P1i7?yJ|tl(f+2@+eymCL}wuo`5*8W6FTgJB&9!+H*e4IB&`K?*i;Fl+|VTR0fD zaxrXU*v`eUgJCC#wF@M?n}cBwh~5h#_JN4~AmRXsILOX$h@Igu7sC;Tqg)Io49D0R zj!*p9&v;^TBjfJL{!FJf8!}&JV@_d6oy^W<YJHO76c0lYLk<taX@)aA42>XG8AA>u z17}!bPHt*RW^yqP!&!!NJPef}QD*P*3?7C$5L01t47cp$DO{P{=Xn@TGF;$c@MG|w z%)xCh6w2Vw!_W*esRcx|GvrK;<c>;+XYgla;0#Jl%n3`(DNW^JNCpWAS5{V5>iYWX zrlcr%cv$7;S``<wGhF0hxWsUoo#6@(!&QcBJPg+vZtyTzGFUM(Fz_%~Gg$F3*nkLI z5Mc)*>=_&;OYrD$-{fJq#c-R4A%)@2W`7<#rg{qo1_nh2Nswj+1_n-$W-x8TU<Iaa zp|l;8wr6l)U|^7BaAdGzU}SJ&U|?WkaAuHXaA9zO^IaJv8QhTM`57b`+>!VK43Z2U z5Pm(_06_*x22Y3pm@mX2$>4>=7h#ZO@J8Z`GDtG`AX(_kAPEXx21bSeu>L>>NroUK z^->Iy48cfzX$DD#5HP<U;saR*Nrq4ce-s14kSqvikYtDeYk;U%VvuBrMB*zmNHRnr z@j)JnM&g4!6obT9VUT2q1@Y^lL8!_g$q<KRA;?GZXbwsMX@II%XOLt_MB;;dl!U|w zc_<l0KR*K#LkdGG10zEk0|SFG10w??0|SE@tJZb~#*N@mOJ`tU0Oeo?20jKB1_6c) z22g4OsbXcwWXJ+1hirx%1}28I$=3zU7}F>735uJ-RB<rKGUPJkF)%RXL-j#K3K$rm zu~Nvu1<Fcb{ZWF}z99RA7+4q>7*ZKH7}6Ld7}6Ou7&74Yaxf?{6r-645-EY3Sjxc3 zPzH6;BSBrp^vME3$SxAW&<_$RhwHCk-~#1au#5hQXiaVtQesS>yi!OR$yde<RcLMi zi6EQ7$xzKu12%(ESX2|_D>iW0)<OMU%fJOH5<n^#7#Io}n8C8DlkJ67>NhYjFfcQK z^oTLAGB7YSF>o+6GYB%YFi0`9GAJ{2Accl3Lp_>HKq9CvX@Izdfq_8=YzqSe%O(an zkS&a0TOcm$fw_!}feTcoft)t^k1%qSOk&_*n9Lx-Foi*bVJea%lo*=O903wRjgn?) zl(dNGB1Q5{1`dW<41x@^8KfBIAejh?64Yb^5<&JB7efow#D5|_jOmlTMV0Fj$<COe z70pE;5oG<G3~ktgMGZYzR>OjYfs3IXVk2^d?Pg$#+|I!4ttBKWH2JNl9Ao-q9x-Vo zm&h`7pt%Gjg6fh^Y%bA2cgYU8OE?(1;F<Or0~-SftP;}P!JxH+L3<m6&gRL>#H8wX zGnhoO?qx8IWaikxz#1IMBESZscQBZ3XE5K)Ac2q<Fa}9PvItm!XqW;yBn5&XiAWX! zArK8ypoXMC7$gzNA^@hr3Y^V1GiZPc5lAA_V&Gz6U=U{DV-RByW)NqPV31${6-Y`9 dG7M@Ah74{DmJI0({tO)qVGN86-QdEf2LO>BHUt0w delta 2329 zcmZ3g*QH;7>ff$?3=9k=43D@NEEy)UGfd)QU;@#TxfskCrf@N^FiZuBOarl|gNPX% z3^PF@vp}5L91L?n^jr>xc^nM$IT#jjFf8O?Sj54wn1f*n2g6b>hGh)PIT=_OR&X$^ z<X~9E!LXWxVGRevT9DW}u6hO*hV>u=Hh_qY91NQ{7&db-Y~f(o3R19*gJC;}-oe4J zlZ#;&!)`8yJq&w6tbHKi{TvJjK=eTnaR@{l1`$U<#8D7&jGf^)JHrVshLa4ZxEM?s zPO~$dVPxPA@po~I432kk44L?|iSg{@8php%0%49mj=`>e@!p<3o__J3E|X1}&WOQ9 z!yJ7=UE@7nm>C!tj5q&hy2{3!!H_xmI;W}iIfnB*3}p-jJPa2YF7hz6f>>1y1&j=w zVTn1psU?}o#XJm`7%uZL)Ph8ry~{Ir7@9y#g~>YHvXfJ|GP$qtFq~t!%EJ)A5IFe; zm%UIVLm&@BJIJIC5Yf$0Fj<p3sy>+^kdc8iC^a!BEHS4vm4_i6Bp_T_Sy`#;>#LiR zqTu0Sm78l-T+GgJjfden!wq(Zn>-A+7;f`0++n!O!(hc=&B(yO!(hW;&BI^|BJ4nf zJ&15%aO7d|WpHF<5Y9?0OVlqd$;{DrEGkN@^vNtPVPp`@n*5hri2EK7!+nMaJPa8O z4>wEk*fG^xGB7YGGf0BWW?*381epz{Z5gb=v>lYThtduVjtmS8k_=7^)(ngc&I}9; zObjjzk_@g4j&QykgCv7Hk~}|yB!dSMUw}c9!4tx-2OA*BAj#kb5diar7$h0Ik@zAE zk_<jbd{G8YkYB+L@k6rMpFt872@H%3L11%&86+7(kn~A0NHT;X@ueB+B^kny1Y{W` z8N!haj9`#th-3&vF)#{AKAJ(2AqGjm5`!c|ED|3SvT;a!kVoT@_(Jszk_-t*0xArW z42ej5RR&3hBqR$#K1@b)PzsWIbp}a>R3yGMgCs*55?_`<5|r%V9`Xxj;AdcB$Y981 zU}VSwWe)~M21W)323D=@42&DWp_t9UzyK;U7#R2%SQrEtau`5~5UhwHmmv?FO!65D z7?>EcCU*&#F=kIbC?IYMQ^mm`%TUNr#K6E%4Aln_DPdrM#!@K*7bpjU_0Ja;pR6LN z;tR4<h=GNHfgzQFgCUJUf+3wjgCPTMHwS|fLphqMAdw2Vsg(?z3{_B9O%>EdGBJmN zgCUnekRgvjiXk7#L=g-VK_b;~6Kfc_K!pI<oeM>@CR++AF=kJW5mK&4_|=%94$V~{ z5o9ws8R{7tKxQy7Fvx&|nt_336NAJC1_lO329Uqmz@l}~&}n4g0+lyV9gPgkU|GZ6 z3`~*R8JNAbgd~L+r6x}l6|WbP6)@hxAij-(JzNW98Z+25DF!wM28JdE4u)n1L53Cv zDTY=CWrj8eeTEJsziToyqq!R-g6i%TZ0?o=*#ves$Rbdp=s|LLD>MS;3tJ;az$69^ zhRF;P3{x017^WgQLW!Xb%@H6G)F^F-ny4;<9HlcEI2dLz2r|rOkYbpFWFja6QIj4> z1le0$3>{Dt7mD~WW>0=6f*PHjXf85l=wv|F&&kk*Em+jx!NLHE&ecev(haeZfq|hA z8l9@h(K&g7s2pSV<n^M`D4D1S%_Xu7J!mfJg}7w$e^F6QL_*pDx0!>Xj{%m?-+_|_ z1H-z>wqk1a9Ge+Tb~BhpvhHOti)7~5!N3|E$s)i8qIWQuZ)dRB%pie~2PHGG0t;jX za!3jUK@yQH0zx1fW`Y`$0%4FuB#Qu;-r)_kLjzRcfD;pg9s@T61A{OFAA=Z!FoQUQ p1cL+vsPIx^kYP|`&|}bIFl6vzuw=+)@Mq{@2xDMm=m!^8699jjTjBr! diff --git a/target/classes/com/application/GUI/LineChartFunctionality.class b/target/classes/com/application/GUI/LineChartFunctionality.class index 30aa13c4fd74adfb7823e3ea88c92328da5dd2da..07809ca136bbd886e5a43251d3b4cf697a129c50 100644 GIT binary patch delta 3825 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 E08on?zW@LL delta 4261 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 -- GitLab