Spaces:
Sleeping
Sleeping
File size: 8,461 Bytes
8879278 7c4cea5 e583e5b 7c4cea5 e583e5b 8879278 7c4cea5 d1cd9d0 8879278 d1cd9d0 8879278 7c4cea5 d1cd9d0 7c4cea5 d1cd9d0 e583e5b d1cd9d0 7c4cea5 d1cd9d0 e583e5b d1cd9d0 8879278 d1cd9d0 7c4cea5 8879278 d1cd9d0 8879278 d1cd9d0 8879278 d1cd9d0 8879278 d1cd9d0 8879278 7c4cea5 d1cd9d0 7c4cea5 d1cd9d0 7c4cea5 d1cd9d0 e583e5b d1cd9d0 e583e5b d1cd9d0 8879278 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import streamlit as st
from typing import Dict
# Constants
ONE_BR_UNITS = 23
TWO_BR_UNITS = 45
SOLAR_PANEL_RATING = 625 # W
BATTERY_CAPACITY = 200 # Ah
BATTERY_VOLTAGE = 12 # V
SYSTEM_LOSSES = 0.20
FEED_IN_TARIFF = 12
# Lighting specifications
LIGHTS_1BR = 5
LIGHTS_2BR = 8
LIGHT_POWER = 6 # Watts per light
def initialize_session_state():
"""Initialize session state variables"""
defaults = {
'solar_panels': 100,
'batteries': 50,
'panel_price': 13000,
'battery_price': 39000,
'grid_price': 28.44
}
for key, value in defaults.items():
if key not in st.session_state:
st.session_state[key] = value
def calculate_lighting_consumption(occupancy_1br: float, occupancy_2br: float) -> float:
"""Calculate daily lighting consumption"""
return (
(occupancy_1br * ONE_BR_UNITS * LIGHTS_1BR * LIGHT_POWER / 1000) +
(occupancy_2br * TWO_BR_UNITS * LIGHTS_2BR * LIGHT_POWER / 1000)
) * 24 # Daily kWh
def calculate_appliance_consumption(occupancy_1br: float, occupancy_2br: float) -> float:
"""Calculate daily appliance consumption"""
return (
(occupancy_1br * ONE_BR_UNITS * (250 - (LIGHTS_1BR * LIGHT_POWER * 24 / 1000))) +
(occupancy_2br * TWO_BR_UNITS * (400 - (LIGHTS_2BR * LIGHT_POWER * 24 / 1000)))
) # Daily kWh
def total_consumption(occupancy_1br: float, occupancy_2br: float, common_area: float) -> float:
"""Calculate total monthly consumption"""
lighting = calculate_lighting_consumption(occupancy_1br, occupancy_2br)
appliances = calculate_appliance_consumption(occupancy_1br, occupancy_2br)
return (lighting + appliances + common_area) * 30 # Monthly kWh
def solar_production(panels: int) -> float:
"""Monthly solar production with losses"""
return panels * SOLAR_PANEL_RATING * 5 * 0.8 * 30 / 1000 # 5 sun hours
def battery_storage(batteries: int) -> float:
"""Usable battery capacity"""
return batteries * BATTERY_CAPACITY * BATTERY_VOLTAGE * 0.8 / 1000
def financial_analysis(consumption: float, production: float, storage: float) -> Dict:
"""Detailed financial calculations"""
solar_used = min(production, consumption)
grid_purchased = max(consumption - solar_used - storage, 0)
return {
'solar_contribution': solar_used / consumption * 100,
'grid_dependency': grid_purchased / consumption * 100,
'monthly_savings': (consumption * st.session_state.grid_price) -
(grid_purchased * st.session_state.grid_price),
'payback_period': (st.session_state.solar_panels * st.session_state.panel_price +
st.session_state.batteries * st.session_state.battery_price) /
((consumption - grid_purchased) * st.session_state.grid_price * 12)
}
def create_consumption_breakdown(occupancy_1br: float, occupancy_2br: float, common_area: float):
"""Create detailed consumption breakdown"""
breakdown = {
'Lighting': calculate_lighting_consumption(occupancy_1br, occupancy_2br) * 30,
'Appliances': calculate_appliance_consumption(occupancy_1br, occupancy_2br) * 30,
'Common Areas': common_area * 30
}
return pd.DataFrame.from_dict(breakdown, orient='index', columns=['kWh'])
# Streamlit Interface
def main():
st.set_page_config("Solar Analysis Suite", "🌞", "wide")
initialize_session_state()
st.title("🌞 Advanced Solar Performance Analyzer")
with st.sidebar:
st.header("System Configuration")
st.number_input("Solar Panels", 1, 1000, key='solar_panels')
st.number_input("Batteries", 0, 500, key='batteries')
st.number_input("Panel Price (Ksh)", 1000, 50000, key='panel_price')
st.number_input("Battery Price (Ksh)", 5000, 100000, key='battery_price')
st.number_input("Grid Price (Ksh/kWh)", 10.0, 50.0, key='grid_price')
scenarios = {
"Low Occupancy": {"1br": 0.0, "2br": 1.0, "common": 5.904},
"Medium Occupancy": {"1br": 0.25, "2br": 1.0, "common": 5.904},
"High Occupancy": {"1br": 0.5, "2br": 1.0, "common": 5.904}
}
analysis_data = []
for name, params in scenarios.items():
consumption = total_consumption(
params["1br"], params["2br"], params["common"]
)
production = solar_production(st.session_state.solar_panels)
storage = battery_storage(st.session_state.batteries)
financials = financial_analysis(consumption, production, storage)
analysis_data.append({
"Scenario": name,
"Consumption": consumption,
"Production": production,
**financials
})
df = pd.DataFrame(analysis_data)
# Energy Flow Analysis
st.header("Energy Flow Composition")
fig, ax = plt.subplots(figsize=(10, 6))
sns.barplot(df.melt(id_vars=['Scenario'],
value_vars=['solar_contribution', 'grid_dependency'],
x='Scenario', y='value', hue='variable', ax=ax)
ax.set_ylabel("Percentage (%)")
ax.set_title("Energy Contribution Breakdown")
st.pyplot(fig)
with st.expander("🔍 Energy Flow Interpretation"):
st.markdown("""
**Understanding the Chart:**
- **Solar Contribution**: Percentage of total energy needs met by solar production
- **Grid Dependency**: Remaining energy required from grid
- Ideal scenario shows high solar contribution with minimal grid dependency
""")
# Financial Analysis
st.header("Financial Performance Metrics")
# Metric 1: Monthly Savings
fig1, ax1 = plt.subplots(figsize=(10, 4))
sns.barplot(data=df, x='Scenario', y='monthly_savings', ax=ax1)
ax1.set_title("Monthly Cost Savings")
ax1.set_ylabel("Ksh")
st.pyplot(fig1)
with st.expander("💵 Savings Analysis"):
st.markdown(f"""
**Key Observations:**
- Savings calculated as: `(Total Consumption × Grid Price) - (Grid Purchased × Grid Price)`
- Current Grid Price: Ksh {st.session_state.grid_price}/kWh
- Maximum potential savings limited by solar production capacity
""")
st.table(df[['Scenario', 'Consumption', 'Production', 'monthly_savings']])
# Metric 2: Payback Period
fig2, ax2 = plt.subplots(figsize=(10, 4))
sns.barplot(data=df, x='Scenario', y='payback_period', ax=ax2)
ax2.set_title("System Payback Period")
ax2.set_ylabel("Years")
st.pyplot(fig2)
with st.expander("⏳ Payback Explanation"):
st.markdown(f"""
**Calculation Methodology:**
- Total Investment: (Panels × {st.session_state.panel_price:,}Ksh) + (Batteries × {st.session_state.battery_price:,}Ksh)
- Annual Savings: Monthly Savings × 12
- Payback Period = Total Investment / Annual Savings
""")
st.table(df[['Scenario', 'payback_period']])
# Consumption Breakdown
st.header("Detailed Consumption Analysis")
scenario_select = st.selectbox("Select Scenario", list(scenarios.keys()))
selected_params = scenarios[scenario_select]
breakdown_df = create_consumption_breakdown(
selected_params["1br"],
selected_params["2br"],
selected_params["common"]
)
col1, col2 = st.columns(2)
with col1:
st.subheader("Energy Composition")
fig3, ax3 = plt.subplots()
breakdown_df.plot.pie(y='kWh', ax=ax3, autopct='%1.1f%%')
st.pyplot(fig3)
with col2:
st.subheader("Component Breakdown")
st.table(breakdown_df)
analysis_text = f"""
**Key Insights for {scenario_select}:**
- Lighting contributes {breakdown_df.loc['Lighting', 'kWh']/breakdown_df.sum().values[0]*100:.1f}% of total consumption
- Common areas account for {breakdown_df.loc['Common Areas', 'kWh']:.0f}kWh monthly
- 2BR units dominate appliance usage at {selected_params['2br']*100}% occupancy
"""
st.markdown(analysis_text)
if __name__ == "__main__":
main()
|