mudassarrafique commited on
Commit
21d7e79
·
verified ·
1 Parent(s): a21e780

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -109
app.py CHANGED
@@ -1,126 +1,118 @@
1
  import streamlit as st
2
  import pandas as pd
3
- import plotly.graph_objects as go
4
- from datetime import datetime
5
- import difflib # For string similarity matching
6
-
7
- # Function to create the luminous indicator
8
- def create_glowing_indicator(color, status):
9
- return f"<div style='width: 50px; height: 50px; border-radius: 25px; background: {color}; box-shadow: 0 0 20px {color}; margin: auto;'>{status}</div>"
10
-
11
- # Function to load data
 
 
 
 
12
  @st.cache_data
13
  def load_data():
14
  try:
15
- # Load the Excel data
16
- data = pd.read_excel("grid_load_data.xlsx")
17
-
18
- # Normalize the column names to lowercase for easy comparison
19
- data.columns = [col.strip().lower() for col in data.columns] # Strip spaces and convert to lowercase
20
-
21
- # Find the closest match for the 'time' column
22
- time_column = difflib.get_close_matches('time', data.columns, n=1, cutoff=0.8) # 80% similarity
23
-
24
- # Check if a close match is found
25
- if time_column:
26
- time_column_name = time_column[0]
27
- data[time_column_name] = pd.to_datetime(data[time_column_name])
28
- else:
29
- st.error("No 'Time' column found or a close match.")
30
- return pd.DataFrame() # Return an empty DataFrame to avoid further errors
31
-
32
- return data
 
 
33
  except Exception as e:
34
- st.error(f"Error loading data: {e}")
35
- return pd.DataFrame() # Return an empty DataFrame in case of an error
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  def main():
38
- st.set_page_config(layout="wide") # Set page config first
39
 
40
  # Load dataset
41
- df = load_data()
 
 
42
 
43
- # Check if data is empty (in case of error)
44
- if df.empty:
45
- st.stop() # Stop the app if the data is not loaded correctly
46
 
47
- # Sidebar options
48
- mode = st.sidebar.radio("Select Mode", ["Automatic", "Manual"])
 
49
 
50
- # Current time
51
- current_time = datetime.now()
52
- current_hour = current_time.hour
53
 
54
- # Dynamic controls for manual mode
55
- if mode == "Manual":
56
- grid_load = st.sidebar.slider("Select Grid Load (kW)", min_value=0, max_value=5000, value=2500, step=100)
57
- else:
58
- current_grid_data = df[df['time'].dt.hour == current_hour] # Assuming 'time' column after processing
59
- grid_load = current_grid_data['Grid Load (kW)'].mean() if not current_grid_data.empty else 2500
60
-
61
- # Displaying grid load meter
62
- st.markdown("### Grid Load Meter")
63
- fig_grid = go.Figure(go.Indicator(
64
- mode="gauge+number",
65
- value=grid_load,
66
- gauge={
67
- "axis": {"range": [0, 5000]},
68
- "steps": [
69
- {"range": [0, 3000], "color": "lightgreen"},
70
- {"range": [3000, 3500], "color": "yellow"},
71
- {"range": [3500, 5000], "color": "red"}
72
- ],
73
- "threshold": {"line": {"color": "red", "width": 4}, "thickness": 0.75, "value": 3000}
74
- },
75
- title={"text": "Grid Load (kW)"}
76
- ))
77
- st.plotly_chart(fig_grid, use_container_width=True)
78
-
79
- # Alarm indicators
80
- left_indicator_color = "green" if grid_load < 3000 else "red"
81
- right_indicator_color = "green" if grid_load >= 3000 else "red"
82
-
83
- left_alarm = create_glowing_indicator(left_indicator_color, "")
84
- right_alarm = create_glowing_indicator(right_indicator_color, "")
85
-
86
- st.markdown(f"""
87
- <div style='display: flex; justify-content: space-between;'>
88
- {left_alarm}
89
- {right_alarm}
90
- </div>
91
- """, unsafe_allow_html=True)
92
-
93
- # EV Section
94
- st.markdown("### EV Section")
95
-
96
- # EV Connection Toggle
97
- ev_export_toggle = st.checkbox("Allow EV Energy Export to Grid", value=False)
98
-
99
- # EVs and Grid Calculation
100
- ev_power = 50 # Assume each EV contributes 50 kW
101
-
102
- if grid_load > 3000:
103
- excess_load = grid_load - 3000
104
- evs_required = -(-excess_load // ev_power) # Round up EVs required
105
-
106
- st.warning(f"Grid is overloaded by {excess_load} kW. Approximately {evs_required} EVs are needed to stabilize the grid.")
107
-
108
- if ev_export_toggle:
109
- # Add EVs slider
110
- evs_to_connect = st.slider("Number of EVs to Connect", min_value=0, max_value=int(evs_required), value=0, step=1)
111
-
112
- # Update grid load dynamically
113
- grid_load = max(0, grid_load - evs_to_connect * ev_power)
114
- st.success(f"{evs_to_connect} EVs connected. Updated Grid Load: {grid_load} kW.")
115
-
116
- elif grid_load <= 3000:
117
- remaining_capacity = 3000 - grid_load
118
- ev_slots_available = remaining_capacity // ev_power
119
- st.success(f"Grid is stable. Approximately {ev_slots_available} EV slots available for charging.")
120
-
121
- # Updated Grid Load Meter
122
- fig_grid.update_traces(value=grid_load)
123
- st.plotly_chart(fig_grid, use_container_width=True)
124
 
125
  if __name__ == "__main__":
126
  main()
 
1
  import streamlit as st
2
  import pandas as pd
3
+ import datetime
4
+ from difflib import get_close_matches
5
+
6
+ # Function to standardize and find the closest column name
7
+ def get_closest_column(columns, target, threshold=0.6):
8
+ target = target.lower().replace(" ", "").replace("(", "").replace(")", "").replace("-", "")
9
+ columns_cleaned = [col.lower().replace(" ", "").replace("(", "").replace(")", "").replace("-", "") for col in columns]
10
+ matches = get_close_matches(target, columns_cleaned, n=1, cutoff=threshold)
11
+ if matches:
12
+ return columns[columns_cleaned.index(matches[0])]
13
+ return None
14
+
15
+ # Load the dataset
16
  @st.cache_data
17
  def load_data():
18
  try:
19
+ df = pd.read_excel("grid_load_data.xlsx")
20
+
21
+ # Identify the closest matches for required columns
22
+ grid_load_col = get_closest_column(df.columns, "Grid Load (kW)")
23
+ time_col = get_closest_column(df.columns, "Time")
24
+
25
+ if not grid_load_col or not time_col:
26
+ st.error("The dataset must include columns similar to 'Grid Load (kW)' and 'Time'. Please check the formatting.")
27
+ return None, None
28
+
29
+ # Rename columns for consistent processing
30
+ df = df.rename(columns={grid_load_col: "Grid Load (kW)", time_col: "Time"})
31
+
32
+ # Ensure 'Time' column is datetime formatted
33
+ df["Time"] = pd.to_datetime(df["Time"], errors="coerce")
34
+ return df, "Grid Load (kW)"
35
+
36
+ except FileNotFoundError:
37
+ st.error("The file 'grid_load_data.xlsx' was not found. Please upload the correct file.")
38
+ return None, None
39
  except Exception as e:
40
+ st.error(f"An error occurred while loading the dataset: {e}")
41
+ return None, None
42
+
43
+ # Function to calculate the predicted grid load for the current hour of the day
44
+ def calculate_predicted_grid_load(df, current_time, grid_load_col):
45
+ if df is None:
46
+ st.error("Dataset is not loaded correctly.")
47
+ return None
48
+
49
+ # Extract the hour and day from the current time
50
+ current_hour = current_time.hour
51
+
52
+ # Filter dataset for the given hour across all days
53
+ df["Hour"] = df["Time"].dt.hour
54
+ hourly_data = df[df["Hour"] == current_hour]
55
 
56
+ if not hourly_data.empty:
57
+ # Calculate the average grid load for the given hour across all days
58
+ avg_grid_load = hourly_data[grid_load_col].mean()
59
+ return avg_grid_load
60
+ else:
61
+ st.warning("No data found for the current hour. Using default value.")
62
+ return 0 # Default to 0 if no data is found for the given hour
63
+
64
+ # Display the live clock
65
+ def display_clock():
66
+ current_time = datetime.datetime.now()
67
+ st.sidebar.markdown(f"### 🕒 {current_time.strftime('%Y-%m-%d %H:%M:%S')}")
68
+ return current_time
69
+
70
+ # Main app
71
  def main():
72
+ st.title("Optimized EV Charging and Grid Management")
73
 
74
  # Load dataset
75
+ df, grid_load_col = load_data()
76
+ if df is None or grid_load_col is None:
77
+ return # Exit if the dataset is not loaded properly
78
 
79
+ # Sidebar for user inputs
80
+ with st.sidebar:
81
+ st.header("User Inputs")
82
 
83
+ # Battery details (manually entered)
84
+ state_of_charge = st.number_input("State of Charge (SOC) in kWh", min_value=0, max_value=100, step=1)
85
+ battery_capacity = st.number_input("Battery Capacity (kWh)", min_value=10, max_value=200, step=1)
86
 
87
+ # ON/OFF button for exporting battery power to the grid
88
+ export_power = st.checkbox("Export Power to Grid (ON/OFF)")
 
89
 
90
+ # Display live clock
91
+ current_time = display_clock()
92
+
93
+ # Predicted grid load
94
+ predicted_grid_load = calculate_predicted_grid_load(df, current_time, grid_load_col)
95
+ if predicted_grid_load is not None:
96
+ st.write(f"### Predicted Grid Load at {current_time.strftime('%H:%M:%S')}: **{predicted_grid_load:.2f} kW**")
97
+
98
+ # Evaluate grid status based on the predicted load
99
+ if predicted_grid_load > 3400:
100
+ st.error("Grid is Overloaded! EV Charging Disallowed")
101
+ st.write("🚫 Red Light: EV Charging is Disconnected.")
102
+ else:
103
+ st.success("Grid is Stable! EV Charging Allowed")
104
+ st.write("✅ Green Light: EV Charging is Active.")
105
+
106
+ # Calculate available EV slots
107
+ available_capacity = 3400 - predicted_grid_load
108
+ ev_slots = available_capacity // 50 # Assuming each EV slot requires 50kW
109
+ st.write(f"### Available EV Slots: **{ev_slots}**")
110
+
111
+ # Export power status
112
+ if export_power:
113
+ st.warning("Battery is exporting power to the grid.")
114
+ else:
115
+ st.info("Battery is not exporting power.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  if __name__ == "__main__":
118
  main()