CarlyneB's picture
[FIX] Try fixing the position of the sidebar
4885a3b
Raw History Blame
4.41 kB
import hashlib
import os
import sys
import subprocess
import pathlib
import streamlit as st
from streamlit_option_menu import option_menu
# ── Auto-update: regenerate JSON files if inputs_aggregated.csv has changed ───
# Uses a hash file to detect changes — works both locally and on Hugging Face.
# Must run before importing config/tabs, which read the generated JSON files.
csv = "data/inputs_aggregated.csv"
hash_file = "data/.csv_hash"
generated = [
"data/cost_sliders.json",
"data/method_groups.json",
"data/secondary_resources.json",
]
def md5(path):
hasher = hashlib.md5()
with open(path, "rb") as f:
hasher.update(f.read())
return hasher.hexdigest()
if os.path.exists(csv):
current_hash = md5(csv)
stored_hash = open(hash_file).read().strip() if os.path.exists(hash_file) else ""
missing = any(not os.path.exists(f) for f in generated)
if current_hash != stored_hash or missing:
print("inputs_aggregated.csv has changed — running data/update.py ...")
subprocess.run([sys.executable, "data/update.py"], check=True)
with open(hash_file, "w") as file:
file.write(current_hash)
print("Data files updated successfully.")
from tabs import (tab0_welcome, tab1_inputs, tab2_constraints,
tab3_coefficients, tab4_optimization, tab5_sensitivity,
tab6_scenarios)
from utils.data_utils import load_slider_data, strip_unit_suffix
from config.config import method_order, secondary_resources
st.set_page_config("Carbon Portfolio Optimizer", layout="wide")
def load_css(file_path):
with open(file_path) as f:
st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)
css_path = pathlib.Path("assets/styles.css")
load_css(css_path)
st.markdown('<h1 class="custom-title">CRRA <span class="crra-hl">Toolkit</span>: CDR Portfolio Optimization</h1>', unsafe_allow_html=True)
with st.sidebar:
selected = option_menu(
"Navigation",
options=[
"Welcome",
"Resource inputs",
"Method constraints",
"Resource coefficients",
"Portfolio generation",
"Sensitivity analysis",
"Scenario comparison",
],
icons=["house", "upload", "gear", "sliders", "graph-up-arrow", "card-checklist", "search"],
default_index=0,
orientation="vertical",
key="crra-menu",
styles={
"container":{
"border-radius":"0px",
},
"menu-title":{
"font-family": "Segoe UI, sans-serif",
"font-weight":"bold",
"color": "#ff5f4d",
"text-transform": "uppercase",
"font-style": "italic",
},
"nav-link": {
"font-family": "Segoe UI, sans-serif",
"margin": "4px 0",
"--hover-color": "#F5F5F5",
"text-transform": "uppercase",
"font-weight":"600",
"font-style": "italic",
},
"nav-link-selected": {
"background-color": "#eae9d8",
"color": "#298231",
"font-weight": "900",
},
}
)
if "constraints" not in st.session_state:
st.session_state.constraints = {}
for m in method_order:
if m not in st.session_state.constraints:
st.session_state.constraints[m] = {"active": True, "cap_type": "percent", "cap_value": 100}
cost_sliders = load_slider_data()
if "costs" not in st.session_state or st.session_state.costs == {}:
st.session_state.costs = {
m: {
strip_unit_suffix(r): (0.0 if (m, strip_unit_suffix(r)) in secondary_resources else cost_sliders[m][r]["median"])
for r in cost_sliders[m]
}
for m in cost_sliders
}
if selected == "Welcome":
tab0_welcome.render_tab()
elif selected == "Resource inputs":
tab1_inputs.render_tab(cost_sliders)
elif selected == "Method constraints":
tab2_constraints.render_tab()
elif selected == "Resource coefficients":
tab3_coefficients.render_tab(cost_sliders)
elif selected == "Portfolio generation":
tab4_optimization.render_tab()
elif selected == "Sensitivity analysis":
tab5_sensitivity.render_tab()
elif selected == "Scenario comparison":
tab6_scenarios.render_tab()