khanikho8 commited on
Commit
4e6cdae
·
verified ·
1 Parent(s): 89e5a37

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -66
app.py CHANGED
@@ -1,67 +1,124 @@
1
- """
2
-
3
- # Add a new blank custom appliance
4
- with st.expander("Quick add custom appliance"):
5
- new_name = st.text_input("Appliance name", key='new_name')
6
- new_cat = st.selectbox("Category", options=list(DEFAULT_APPLIANCES.keys()), key='new_cat')
7
- new_power = st.number_input("Power (W)", min_value=1, value=100, key='new_power')
8
- new_qty = st.number_input("Quantity", min_value=0, value=1, key='new_qty')
9
- new_hours = st.number_input("Hours/day", min_value=0.0, value=1.0, key='new_hours')
10
- if st.button("Add appliance"):
11
- st.session_state.appliances.append({
12
- 'category': new_cat,
13
- 'name': new_name or 'Custom',
14
- 'qty': new_qty,
15
- 'power_w': new_power,
16
- 'hours_per_day': new_hours
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  })
18
- st.experimental_rerun()
19
-
20
- st.markdown("**Edit existing appliances (set qty/hours).**")
21
-
22
- # Show appliance inputs in an editable table-like UI
23
- for i, row in enumerate(st.session_state.appliances):
24
- cols = st.columns([1.2, 0.6, 0.8, 0.9, 0.6])
25
- cols[0].write(f"**{row['name']}** ")
26
- qty = cols[1].number_input(f"qty_{i}", min_value=0, value=int(row['qty']), key=f"qty_{i}")
27
- power = cols[2].number_input(f"power_{i}", min_value=1, value=int(row['power_w']), key=f"power_{i}")
28
- hours = cols[3].number_input(f"hours_{i}", min_value=0.0, value=float(row['hours_per_day']), step=0.25, key=f"hours_{i}")
29
- remove = cols[4].button("Remove", key=f"remove_{i}")
30
- if remove:
31
- st.session_state.appliances.pop(i)
32
- st.experimental_rerun()
33
- # write back edits
34
- st.session_state.appliances[i]['qty'] = qty
35
- st.session_state.appliances[i]['power_w'] = power
36
- st.session_state.appliances[i]['hours_per_day'] = hours
37
-
38
- st.markdown("---")
39
- advanced = st.expander("Advanced options")
40
- with advanced:
41
- depth_of_discharge = st.slider("Battery depth of discharge (usable fraction)", min_value=0.2, max_value=0.95, value=0.8)
42
- inverter_efficiency = st.slider("Inverter & battery round-trip efficiency", min_value=0.5, max_value=1.0, value=0.9)
43
- inverter_margin = st.number_input("Inverter sizing margin (x)", min_value=1.0, value=1.25, step=0.05)
44
-
45
- with col2:
46
- st.header("Results")
47
-
48
- # Build dataframe from session_state appliances
49
- appliances_df = pd.DataFrame(st.session_state.appliances)
50
- if appliances_df.empty:
51
- st.info("Add appliances to see results.")
52
- else:
53
- total_wh, detailed_df = calculate_energy(appliances_df)
54
- total_kwh = total_wh / 1000.0
55
-
56
- system_kw = recommend_system(total_kwh, avg_sun_hours, system_efficiency)
57
- num_panels = recommend_panels(system_kw, panel_wattage)
58
- inverter_kw = recommend_inverter(system_kw, inverter_margin)
59
- battery_kwh = recommend_battery(total_kwh, days_of_autonomy, depth_of_discharge, inverter_efficiency)
60
-
61
- # cost savings estimate (monthly)
62
- monthly_kwh = total_kwh * 30
63
- monthly_savings = monthly_kwh * tariff
64
-
65
- st.metric(label="Total daily energy", value=f"{total_kwh:.2f} kWh")
66
- st.metric(label="Recommended solar capacity", value=f"{system_kw:.2f} kW")
67
- st.metric(label="Estima
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ from fpdf import FPDF
5
+
6
+ st.set_page_config(page_title="Solar System Sizing Calculator", layout="wide")
7
+
8
+ # Default appliance power ratings (W)
9
+ DEFAULTS = {
10
+ "LED Light": 10,
11
+ "Fan": 75,
12
+ "AC (1.5 ton)": 1500,
13
+ "Refrigerator": 200,
14
+ "TV": 100,
15
+ "Laptop/Computer": 120,
16
+ "Washing Machine": 500,
17
+ "Water Pump": 750
18
+ }
19
+
20
+ st.title("☀️ Solar System Sizing Calculator")
21
+ st.markdown("Enter your household appliances to estimate the ideal solar system size.")
22
+
23
+ # Sidebar for appliance input
24
+ appliances = []
25
+ total_energy_wh = 0
26
+
27
+ with st.sidebar:
28
+ st.header("Appliance Details")
29
+ for device, power in DEFAULTS.items():
30
+ qty = st.number_input(f"Number of {device}s", min_value=0, value=0, step=1)
31
+ hours = st.number_input(f"Usage hours/day for {device}", min_value=0, value=0, step=1)
32
+ power_w = st.number_input(f"Power (W) for {device}", min_value=1, value=power, step=1)
33
+ if qty > 0 and hours > 0:
34
+ energy = qty * power_w * hours
35
+ total_energy_wh += energy
36
+ appliances.append({
37
+ "Device": device,
38
+ "Quantity": qty,
39
+ "Power (W)": power_w,
40
+ "Hours/day": hours,
41
+ "Daily Energy (Wh)": energy
42
  })
43
+
44
+ st.subheader("Custom Appliance")
45
+ custom_name = st.text_input("Custom Appliance Name")
46
+ custom_qty = st.number_input("Custom Quantity", min_value=0, value=0)
47
+ custom_power = st.number_input("Custom Power (W)", min_value=1, value=100)
48
+ custom_hours = st.number_input("Custom Usage Hours/day", min_value=0, value=0)
49
+ if custom_name and custom_qty > 0 and custom_hours > 0:
50
+ energy = custom_qty * custom_power * custom_hours
51
+ total_energy_wh += energy
52
+ appliances.append({
53
+ "Device": custom_name,
54
+ "Quantity": custom_qty,
55
+ "Power (W)": custom_power,
56
+ "Hours/day": custom_hours,
57
+ "Daily Energy (Wh)": energy
58
+ })
59
+
60
+ # Convert to DataFrame
61
+ df = pd.DataFrame(appliances)
62
+
63
+ # Main results
64
+ if not df.empty:
65
+ total_energy_kwh = total_energy_wh / 1000
66
+ st.subheader("📊 Energy Consumption Summary")
67
+ st.dataframe(df)
68
+
69
+ fig = px.pie(df, values="Daily Energy (Wh)", names="Device", title="Energy Usage Breakdown")
70
+ st.plotly_chart(fig, use_container_width=True)
71
+
72
+ st.subheader("🔍 System Recommendations")
73
+ sun_hours = st.number_input("Average sunlight hours/day", min_value=1, value=5)
74
+ efficiency = st.slider("System efficiency (%)", min_value=50, max_value=100, value=80) / 100
75
+ system_size_kw = total_energy_kwh / (sun_hours * efficiency)
76
+
77
+ panel_watt = st.number_input("Solar panel wattage (W)", min_value=50, value=350)
78
+ num_panels = (system_size_kw * 1000) / panel_watt
79
+
80
+ battery_days = st.number_input("Days of backup (battery)", min_value=0, value=1)
81
+ battery_capacity_kwh = total_energy_kwh * battery_days
82
+
83
+ inverter_size_kw = system_size_kw * 1.25 # buffer
84
+
85
+ st.write(f"**Total Daily Energy:** {total_energy_kwh:.2f} kWh")
86
+ st.write(f"**Recommended Solar System Size:** {system_size_kw:.2f} kW")
87
+ st.write(f"**Number of Panels ({panel_watt}W):** {num_panels:.0f}")
88
+ st.write(f"**Battery Capacity:** {battery_capacity_kwh:.2f} kWh")
89
+ st.write(f"**Recommended Inverter Size:** {inverter_size_kw:.2f} kW")
90
+
91
+ # PDF Export
92
+ if st.button("Download PDF Report"):
93
+ class PDF(FPDF):
94
+ def header(self):
95
+ self.set_font('Arial', 'B', 14)
96
+ self.cell(200, 10, "Solar System Sizing Report", ln=True, align="C")
97
+
98
+ def chapter_title(self, title):
99
+ self.set_font('Arial', 'B', 12)
100
+ self.cell(0, 10, title, ln=True)
101
+
102
+ def chapter_body(self, body):
103
+ self.set_font('Arial', '', 10)
104
+ self.multi_cell(0, 10, body)
105
+
106
+ pdf = PDF()
107
+ pdf.add_page()
108
+ pdf.chapter_title("Energy Consumption Details")
109
+ for _, row in df.iterrows():
110
+ pdf.chapter_body(f"{row['Device']}: {row['Quantity']} × {row['Power (W)']}W × {row['Hours/day']}h = {row['Daily Energy (Wh)']} Wh")
111
+ pdf.chapter_title("System Recommendations")
112
+ pdf.chapter_body(
113
+ f"Total Daily Energy: {total_energy_kwh:.2f} kWh\n"
114
+ f"Recommended Solar System Size: {system_size_kw:.2f} kW\n"
115
+ f"Number of Panels ({panel_watt}W): {num_panels:.0f}\n"
116
+ f"Battery Capacity: {battery_capacity_kwh:.2f} kWh\n"
117
+ f"Inverter Size: {inverter_size_kw:.2f} kW"
118
+ )
119
+
120
+ pdf.output("solar_report.pdf")
121
+ with open("solar_report.pdf", "rb") as f:
122
+ st.download_button("Download Report", f, file_name="solar_report.pdf")
123
+ else:
124
+ st.warning("Please enter appliance details in the sidebar.")