akshayballal commited on
Commit
f5e1991
·
1 Parent(s): 767e14d

chore: Refactor RTUAnomalizer1.py and lstm_vav_rtu2.ipynb

Browse files
dashboard.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import streamlit as st
2
  import pandas as pd
3
  import numpy as np
@@ -26,8 +27,26 @@ rtu_anomalizer1 = RTUAnomalizer1(
26
  num_outputs=rtu_data_pipeline.num_outputs,
27
  )
28
 
29
- print("Kmeans models:")
30
- print(rtu_anomalizer1.kmeans_models)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  # Set the layout of the page to 'wide'
33
  st.set_page_config(layout="wide")
@@ -263,21 +282,11 @@ with st.container():
263
 
264
  with row2_row2_col1:
265
  st.subheader("Energy Usage - North Wing")
266
- df_energy = generate_energy_data() # ---- REPLACE WITH ACTUAL DATA ----
267
- fig, ax = plt.subplots(figsize=(5, 1.5))
268
- ax.plot(df_energy["Time"], df_energy["Energy"])
269
- ax.set_xlabel("Time")
270
- ax.set_ylabel("Energy (kWh)")
271
- st.pyplot(fig)
272
 
273
  # with row2_row2_col2:
274
  st.subheader("Energy Usage - South Wing")
275
- df_energy = generate_energy_data() # ---- REPLACE WITH ACTUAL DATA ----
276
- fig, ax = plt.subplots(figsize=(5, 1.5))
277
- ax.plot(df_energy["Time"], df_energy["Energy"])
278
- ax.set_xlabel("Time")
279
- ax.set_ylabel("Energy (kWh)")
280
- st.pyplot(fig)
281
 
282
  # Energy Comsumption Statistics
283
  with row2_row2_col2:
@@ -287,16 +296,56 @@ with st.container():
287
  ) # ---- REPLACE WITH ACTUAL DATA ----
288
 
289
 
290
- distance_placeholder = st.empty()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  resid_placeholder = st.empty()
292
 
293
- distances = []
294
  while True:
295
 
296
  if mqtt_client.data_list:
297
  all_data.extend(mqtt_client.data_list)
 
 
298
  df = pd.DataFrame(all_data)
299
 
 
 
 
300
  df_time = df["date"].iloc[-1] # Obtain the latest datetime of data
301
 
302
  with placeholder_header_time:
@@ -312,57 +361,72 @@ while True:
312
 
313
  dist = None
314
  resid_pca_list = None
315
- df_new1, df_trans1, df_new2, df_trans2 = rtu_data_pipeline.fit(df)
 
 
 
 
316
  if (
317
  not df_new1 is None
318
  and not df_trans1 is None
319
  and not df_new2 is None
320
  and not df_trans2 is None
321
  ):
322
- actual_list, pred_list, resid_list, resid_pca_list, dist = (
323
  rtu_anomalizer1.pipeline(df_new1, df_trans1, rtu_data_pipeline.scaler1)
324
  )
 
 
 
 
 
 
 
 
325
 
326
  if resid_pca_list is not None:
 
327
  resid_pca_list = np.array(resid_pca_list)
 
328
 
329
- # plot the distances in a scatter chart in streamlit plotly express
330
- with distance_placeholder:
331
- if dist is not None:
332
- distances.append(float(dist[0][0]))
333
- fig = px.line(
334
- x=range(len(distances)),
335
- y=distances,
336
- labels={"x": "Time", "y": "Distance"},
337
- title="Distance from Cluster Center",
338
- )
339
- st.plotly_chart(fig)
340
-
341
- with resid_placeholder:
342
- if resid_pca_list is not None:
343
- fig = px.scatter(
344
- x=resid_pca_list[:, 0],
345
- y=resid_pca_list[:, 1],
346
- labels={"x": "Time", "y": "Residual"},
347
- title="Residuals",
348
- width=800,
349
- height=800,
350
- )
351
- fig.update_layout(
352
- xaxis_range=[-1, 1],
353
- yaxis_range=[-1, 1],
354
- xaxis=dict(showgrid=True, gridwidth=1, gridcolor="lightgray"),
355
- yaxis=dict(showgrid=True, gridwidth=1, gridcolor="lightgray"),
356
- margin=dict(l=20, r=20, t=20, b=20),
357
- hovermode="closest",
358
- showlegend=False,
359
- autosize=False,
360
- hoverlabel=dict(bgcolor="white", font_size=12),
361
- hoverlabel_align="left",
362
- hoverlabel_font_color="black",
363
- hoverlabel_bordercolor="lightgray",
364
- )
365
- fig.update_traces(marker=dict(size=5, color="blue"))
366
- st.plotly_chart(fig)
 
367
 
368
  mqtt_client.data_list.clear()
 
1
+ from collections import deque
2
  import streamlit as st
3
  import pandas as pd
4
  import numpy as np
 
27
  num_outputs=rtu_data_pipeline.num_outputs,
28
  )
29
 
30
+
31
+ rtu_anomalizer2 = RTUAnomalizer1(
32
+ prediction_model_path="src/rtu/models/lstm_2rtu_smooth_04.keras",
33
+ clustering_model_paths=[
34
+ "src/rtu/models/kmeans_rtu_1.pkl",
35
+ "src/rtu/models/kmeans_rtu_2.pkl",
36
+ ],
37
+ pca_model_paths=[
38
+ "src/rtu/models/pca_rtu_1.pkl",
39
+ "src/rtu/models/pca_rtu_2.pkl",
40
+ ],
41
+ num_inputs=rtu_data_pipeline.num_inputs,
42
+ num_outputs=rtu_data_pipeline.num_outputs,
43
+ )
44
+
45
+ rtu_1_thresholds = deque(maxlen=60)
46
+ rtu_1_fault = False
47
+ for i in range(60):
48
+ rtu_1_thresholds.append(0)
49
+
50
 
51
  # Set the layout of the page to 'wide'
52
  st.set_page_config(layout="wide")
 
282
 
283
  with row2_row2_col1:
284
  st.subheader("Energy Usage - North Wing")
285
+ north_wing_energy_container = st.empty()
 
 
 
 
 
286
 
287
  # with row2_row2_col2:
288
  st.subheader("Energy Usage - South Wing")
289
+ south_wing_energy_container = st.empty()
 
 
 
 
 
290
 
291
  # Energy Comsumption Statistics
292
  with row2_row2_col2:
 
296
  ) # ---- REPLACE WITH ACTUAL DATA ----
297
 
298
 
299
+ distances = []
300
+
301
+
302
+ def create_residual_plot(resid_pca_list, rtu_id):
303
+ if rtu_id % 2 == 1:
304
+ ax1 = 0
305
+ ax2 = 1
306
+ elif rtu_id % 2 == 0:
307
+ ax1 = 2
308
+ ax2 = 3
309
+ fig = px.scatter(
310
+ x=resid_pca_list[:, ax1],
311
+ y=resid_pca_list[:, ax2],
312
+ labels={"x": "Time", "y": "Residual"},
313
+ width=500,
314
+ height=500,
315
+ )
316
+ fig.update_layout(
317
+ xaxis_range=[-8, 8],
318
+ yaxis_range=[-8, 8],
319
+ xaxis=dict(showgrid=True, gridwidth=1, gridcolor="lightgray"),
320
+ yaxis=dict(showgrid=True, gridwidth=1, gridcolor="lightgray"),
321
+ margin=dict(l=20, r=20, t=20, b=20),
322
+ hovermode="closest",
323
+ showlegend=False,
324
+ autosize=False,
325
+ hoverlabel=dict(bgcolor="white", font_size=12),
326
+ hoverlabel_align="left",
327
+ hoverlabel_font_color="black",
328
+ hoverlabel_bordercolor="lightgray",
329
+ )
330
+ fig.update_traces(marker=dict(size=5, color="blue"))
331
+
332
+ return fig
333
+
334
+
335
  resid_placeholder = st.empty()
336
 
337
+
338
  while True:
339
 
340
  if mqtt_client.data_list:
341
  all_data.extend(mqtt_client.data_list)
342
+ if len(all_data) > 100:
343
+ all_data.pop(0)
344
  df = pd.DataFrame(all_data)
345
 
346
+ if sum(list(rtu_1_thresholds)) > 50:
347
+ rtu_1_fault = True
348
+
349
  df_time = df["date"].iloc[-1] # Obtain the latest datetime of data
350
 
351
  with placeholder_header_time:
 
361
 
362
  dist = None
363
  resid_pca_list = None
364
+ resid_pca_list_2 = None
365
+
366
+ df_new1, df_trans1, df_new2, df_trans2 = rtu_data_pipeline.fit(
367
+ pd.DataFrame(mqtt_client.data_list)
368
+ )
369
  if (
370
  not df_new1 is None
371
  and not df_trans1 is None
372
  and not df_new2 is None
373
  and not df_trans2 is None
374
  ):
375
+ actual_list, pred_list, resid_list, resid_pca_list, dist, over_threshold = (
376
  rtu_anomalizer1.pipeline(df_new1, df_trans1, rtu_data_pipeline.scaler1)
377
  )
378
+ (
379
+ actual_list_2,
380
+ pred_list_2,
381
+ resid_list_2,
382
+ resid_pca_list_2,
383
+ dist_2,
384
+ over_threshold_2,
385
+ ) = rtu_anomalizer1.pipeline(df_new1, df_trans1, rtu_data_pipeline.scaler1)
386
 
387
  if resid_pca_list is not None:
388
+ rtu_1_thresholds.append(over_threshold[0])
389
  resid_pca_list = np.array(resid_pca_list)
390
+ resid_pca_list_2 = np.array(resid_pca_list_2)
391
 
392
+ if resid_pca_list is not None:
393
+ with resid_placeholder.container():
394
+ resid_rtu1_placeholder, resid_rtu2_placeholder = st.columns(2)
395
+ with resid_rtu1_placeholder:
396
+ st.subheader("RTU 1 Residuals")
397
+ fig = create_residual_plot(resid_pca_list, rtu_id=1)
398
+ st.plotly_chart(fig)
399
+
400
+ with resid_rtu2_placeholder:
401
+ st.subheader("RTU 2 Residuals")
402
+ fig = create_residual_plot(resid_pca_list, rtu_id=2)
403
+ st.plotly_chart(fig)
404
+
405
+ resid_rtu3_placeholder, resid_rtu4_placeholder = st.columns(2)
406
+ with resid_rtu3_placeholder:
407
+ st.subheader("RTU 3 Residuals")
408
+ fig = create_residual_plot(resid_pca_list, rtu_id=3)
409
+ st.plotly_chart(fig)
410
+
411
+ with resid_rtu4_placeholder:
412
+ st.subheader("RTU 4 Residuals")
413
+ fig = create_residual_plot(resid_pca_list, rtu_id=4)
414
+ st.plotly_chart(fig)
415
+
416
+ # with north_wing_energy_container:
417
+ # df_energy = generate_energy_data() # ---- REPLACE WITH ACTUAL DATA ----
418
+ # fig, ax = plt.subplots(figsize=(5, 1.5))
419
+ # ax.plot(df_energy["Time"], df_energy["Energy"])
420
+ # ax.set_xlabel("Time")
421
+ # ax.set_ylabel("Energy (kWh)")
422
+ # st.pyplot(fig)
423
+
424
+ # with south_wing_energy_container:
425
+ # df_energy = generate_energy_data() # ---- REPLACE WITH ACTUAL DATA ----
426
+ # fig, ax = plt.subplots(figsize=(5, 1.5))
427
+ # ax.plot(df_energy["Time"], df_energy["Energy"])
428
+ # ax.set_xlabel("Time")
429
+ # ax.set_ylabel("Energy (kWh)")
430
+ # st.pyplot(fig)
431
 
432
  mqtt_client.data_list.clear()
mqttpublisher.ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
physLSTM/lstm_vav_rtu2.ipynb CHANGED
@@ -808,6 +808,257 @@
808
  "source": [
809
  "sum(labels==0)"
810
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  }
812
  ],
813
  "metadata": {
 
808
  "source": [
809
  "sum(labels==0)"
810
  ]
811
+ },
812
+ {
813
+ "cell_type": "code",
814
+ "execution_count": 2,
815
+ "metadata": {},
816
+ "outputs": [],
817
+ "source": [
818
+ "import pandas as pd\n",
819
+ "import numpy as np\n",
820
+ "df = pd.DataFrame()\n",
821
+ "\n",
822
+ "# create a dataframe with random data with 4 columns with random names\n",
823
+ "\n",
824
+ "df['col1'] = np.random.rand(100)\n",
825
+ "df['col2'] = np.random.rand(100)\n",
826
+ "df['col3'] = np.random.rand(100)\n",
827
+ "\n"
828
+ ]
829
+ },
830
+ {
831
+ "cell_type": "code",
832
+ "execution_count": 3,
833
+ "metadata": {},
834
+ "outputs": [
835
+ {
836
+ "data": {
837
+ "text/html": [
838
+ "<div>\n",
839
+ "<style scoped>\n",
840
+ " .dataframe tbody tr th:only-of-type {\n",
841
+ " vertical-align: middle;\n",
842
+ " }\n",
843
+ "\n",
844
+ " .dataframe tbody tr th {\n",
845
+ " vertical-align: top;\n",
846
+ " }\n",
847
+ "\n",
848
+ " .dataframe thead th {\n",
849
+ " text-align: right;\n",
850
+ " }\n",
851
+ "</style>\n",
852
+ "<table border=\"1\" class=\"dataframe\">\n",
853
+ " <thead>\n",
854
+ " <tr style=\"text-align: right;\">\n",
855
+ " <th></th>\n",
856
+ " <th>col1</th>\n",
857
+ " <th>col2</th>\n",
858
+ " <th>col3</th>\n",
859
+ " </tr>\n",
860
+ " </thead>\n",
861
+ " <tbody>\n",
862
+ " <tr>\n",
863
+ " <th>0</th>\n",
864
+ " <td>0.766087</td>\n",
865
+ " <td>0.869167</td>\n",
866
+ " <td>0.189766</td>\n",
867
+ " </tr>\n",
868
+ " <tr>\n",
869
+ " <th>1</th>\n",
870
+ " <td>0.663337</td>\n",
871
+ " <td>0.732319</td>\n",
872
+ " <td>0.916248</td>\n",
873
+ " </tr>\n",
874
+ " <tr>\n",
875
+ " <th>2</th>\n",
876
+ " <td>0.691630</td>\n",
877
+ " <td>0.013371</td>\n",
878
+ " <td>0.542655</td>\n",
879
+ " </tr>\n",
880
+ " <tr>\n",
881
+ " <th>3</th>\n",
882
+ " <td>0.184282</td>\n",
883
+ " <td>0.222953</td>\n",
884
+ " <td>0.066323</td>\n",
885
+ " </tr>\n",
886
+ " <tr>\n",
887
+ " <th>4</th>\n",
888
+ " <td>0.522267</td>\n",
889
+ " <td>0.938941</td>\n",
890
+ " <td>0.147908</td>\n",
891
+ " </tr>\n",
892
+ " <tr>\n",
893
+ " <th>...</th>\n",
894
+ " <td>...</td>\n",
895
+ " <td>...</td>\n",
896
+ " <td>...</td>\n",
897
+ " </tr>\n",
898
+ " <tr>\n",
899
+ " <th>95</th>\n",
900
+ " <td>0.179310</td>\n",
901
+ " <td>0.093981</td>\n",
902
+ " <td>0.248775</td>\n",
903
+ " </tr>\n",
904
+ " <tr>\n",
905
+ " <th>96</th>\n",
906
+ " <td>0.097265</td>\n",
907
+ " <td>0.834429</td>\n",
908
+ " <td>0.612038</td>\n",
909
+ " </tr>\n",
910
+ " <tr>\n",
911
+ " <th>97</th>\n",
912
+ " <td>0.385221</td>\n",
913
+ " <td>0.788180</td>\n",
914
+ " <td>0.324235</td>\n",
915
+ " </tr>\n",
916
+ " <tr>\n",
917
+ " <th>98</th>\n",
918
+ " <td>0.429241</td>\n",
919
+ " <td>0.834097</td>\n",
920
+ " <td>0.065782</td>\n",
921
+ " </tr>\n",
922
+ " <tr>\n",
923
+ " <th>99</th>\n",
924
+ " <td>0.267903</td>\n",
925
+ " <td>0.639509</td>\n",
926
+ " <td>0.804702</td>\n",
927
+ " </tr>\n",
928
+ " </tbody>\n",
929
+ "</table>\n",
930
+ "<p>100 rows × 3 columns</p>\n",
931
+ "</div>"
932
+ ],
933
+ "text/plain": [
934
+ " col1 col2 col3\n",
935
+ "0 0.766087 0.869167 0.189766\n",
936
+ "1 0.663337 0.732319 0.916248\n",
937
+ "2 0.691630 0.013371 0.542655\n",
938
+ "3 0.184282 0.222953 0.066323\n",
939
+ "4 0.522267 0.938941 0.147908\n",
940
+ ".. ... ... ...\n",
941
+ "95 0.179310 0.093981 0.248775\n",
942
+ "96 0.097265 0.834429 0.612038\n",
943
+ "97 0.385221 0.788180 0.324235\n",
944
+ "98 0.429241 0.834097 0.065782\n",
945
+ "99 0.267903 0.639509 0.804702\n",
946
+ "\n",
947
+ "[100 rows x 3 columns]"
948
+ ]
949
+ },
950
+ "execution_count": 3,
951
+ "metadata": {},
952
+ "output_type": "execute_result"
953
+ }
954
+ ],
955
+ "source": [
956
+ "df"
957
+ ]
958
+ },
959
+ {
960
+ "cell_type": "code",
961
+ "execution_count": 4,
962
+ "metadata": {},
963
+ "outputs": [],
964
+ "source": [
965
+ "df2 = pd.DataFrame()\n",
966
+ "df2['col1'] = np.random.rand(1)\n",
967
+ "df2['col2'] = np.random.rand(1)\n",
968
+ "df2['col3'] = np.random.rand(1)"
969
+ ]
970
+ },
971
+ {
972
+ "cell_type": "code",
973
+ "execution_count": 5,
974
+ "metadata": {},
975
+ "outputs": [
976
+ {
977
+ "data": {
978
+ "text/html": [
979
+ "<div>\n",
980
+ "<style scoped>\n",
981
+ " .dataframe tbody tr th:only-of-type {\n",
982
+ " vertical-align: middle;\n",
983
+ " }\n",
984
+ "\n",
985
+ " .dataframe tbody tr th {\n",
986
+ " vertical-align: top;\n",
987
+ " }\n",
988
+ "\n",
989
+ " .dataframe thead th {\n",
990
+ " text-align: right;\n",
991
+ " }\n",
992
+ "</style>\n",
993
+ "<table border=\"1\" class=\"dataframe\">\n",
994
+ " <thead>\n",
995
+ " <tr style=\"text-align: right;\">\n",
996
+ " <th></th>\n",
997
+ " <th>col1</th>\n",
998
+ " <th>col2</th>\n",
999
+ " <th>col3</th>\n",
1000
+ " </tr>\n",
1001
+ " </thead>\n",
1002
+ " <tbody>\n",
1003
+ " <tr>\n",
1004
+ " <th>0</th>\n",
1005
+ " <td>0.474836</td>\n",
1006
+ " <td>0.927463</td>\n",
1007
+ " <td>0.761931</td>\n",
1008
+ " </tr>\n",
1009
+ " </tbody>\n",
1010
+ "</table>\n",
1011
+ "</div>"
1012
+ ],
1013
+ "text/plain": [
1014
+ " col1 col2 col3\n",
1015
+ "0 0.474836 0.927463 0.761931"
1016
+ ]
1017
+ },
1018
+ "execution_count": 5,
1019
+ "metadata": {},
1020
+ "output_type": "execute_result"
1021
+ }
1022
+ ],
1023
+ "source": [
1024
+ "df2"
1025
+ ]
1026
+ },
1027
+ {
1028
+ "cell_type": "code",
1029
+ "execution_count": 12,
1030
+ "metadata": {},
1031
+ "outputs": [],
1032
+ "source": [
1033
+ "c = []\n",
1034
+ "a = [2,3]\n",
1035
+ "b = [3,4]"
1036
+ ]
1037
+ },
1038
+ {
1039
+ "cell_type": "code",
1040
+ "execution_count": 14,
1041
+ "metadata": {},
1042
+ "outputs": [],
1043
+ "source": [
1044
+ "c = c+a"
1045
+ ]
1046
+ },
1047
+ {
1048
+ "cell_type": "code",
1049
+ "execution_count": 16,
1050
+ "metadata": {},
1051
+ "outputs": [],
1052
+ "source": [
1053
+ "c = c+b"
1054
+ ]
1055
+ },
1056
+ {
1057
+ "cell_type": "code",
1058
+ "execution_count": null,
1059
+ "metadata": {},
1060
+ "outputs": [],
1061
+ "source": []
1062
  }
1063
  ],
1064
  "metadata": {
src/rtu/RTUAnomalizer1.py CHANGED
@@ -217,4 +217,12 @@ class RTUAnomalizer1:
217
  actual, pred = self.inverse_transform(scaler, pred, df_trans)
218
  actual_list, pred_list, resid_list = self.update_lists(actual, pred, resid)
219
  dist = self.calculate_distances(resid)
220
- return actual_list, pred_list, resid_list, self.resid_pca_list, dist
 
 
 
 
 
 
 
 
 
217
  actual, pred = self.inverse_transform(scaler, pred, df_trans)
218
  actual_list, pred_list, resid_list = self.update_lists(actual, pred, resid)
219
  dist = self.calculate_distances(resid)
220
+ over_threshold = dist > 0.5
221
+ return (
222
+ actual_list,
223
+ pred_list,
224
+ resid_list,
225
+ self.resid_pca_list,
226
+ dist,
227
+ over_threshold,
228
+ )