import json import pandas as pd CO2_UNIT = "MtCO₂" with open("data/method_groups.json") as _f: method_groups: dict[str, list[str]] = json.load(_f) csv_taxonomy = pd.read_csv("data/inputs.csv") # resource_groups: group → [resources], order follows first appearance in CSV resource_groups: dict[str, list[str]] = {} for _, row in csv_taxonomy.drop_duplicates(subset=["Resource group", "Resource"]).iterrows(): group, resource = row["Resource group"], row["Resource"] resource_groups.setdefault(group, []) if resource not in resource_groups[group]: resource_groups[group].append(resource) # resource_unit_map: group → base unit (e.g. "Mha/MtCO2" → "Mha") resource_unit_map: dict[str, str] = {} for _, row in csv_taxonomy.drop_duplicates(subset=["Resource group"]).iterrows(): resource_unit_map[row["Resource group"]] = str(row["Unit"]).split("/")[0] resource_order = sum(resource_groups.values(), []) method_order = sum(method_groups.values(), []) # Resources whose name contains "other" are hidden from the standard display # (tabs 1 and 3) but remain available as reference groups in the "Add resource" # dialog so their coefficients can still be inherited by custom resources. hidden_resource_names: set[str] = { r for r in resource_order if "other" in r.lower() } try: with open("data/secondary_resources.json") as _f: secondary_resources: set[tuple[str, str]] = {tuple(p) for p in json.load(_f)} except FileNotFoundError: secondary_resources: set[tuple[str, str]] = set() # All editable copy (tooltips, per-method "why is this disabled?" notes, and # each tab's OBJECTIVE intro paragraph) lives in data/ui_text.xlsx, three sheets: # "Resources" — Resource | Tooltip # "Methods" — Method | Tooltip | Note (Note = shown in Tab 2's # "Why is this method disabled?" panel for that method) # "Section Intros" — Tab | Text (Text is the OBJECTIVE paragraph for that # tab; Tab is the module name, e.g. "tab2_constraints") # To add or edit any of this text, open that file: no code change needed. # If the file (or a given row) is missing, that piece of text is silently # skipped (no hover text / no note / no intro paragraph shown). try: tooltips_xl = pd.read_excel("data/ui_text.xlsx", sheet_name=None) df_res = tooltips_xl.get("Resources", pd.DataFrame(columns=["Resource", "Tooltip"])) df_met = tooltips_xl.get("Methods", pd.DataFrame(columns=["Method", "Tooltip", "Note"])) df_sec = tooltips_xl.get("Section Intros", pd.DataFrame(columns=["Tab", "Text"])) resource_tooltips: dict[str, str] = { row["Resource"]: row["Tooltip"] for _, row in df_res.iterrows() if pd.notna(row.get("Tooltip")) and str(row.get("Tooltip", "")).strip() } method_tooltips: dict[str, str] = { row["Method"]: row["Tooltip"] for _, row in df_met.iterrows() if pd.notna(row.get("Tooltip")) and str(row.get("Tooltip", "")).strip() } method_notes: dict[str, str] = { row["Method"]: row["Note"] for _, row in df_met.iterrows() if pd.notna(row.get("Note")) and str(row.get("Note", "")).strip() } section_intros: dict[str, str] = { row["Tab"]: row["Text"] for _, row in df_sec.iterrows() if pd.notna(row.get("Text")) and str(row.get("Text", "")).strip() } except FileNotFoundError: resource_tooltips: dict[str, str] = {} method_tooltips: dict[str, str] = {} method_notes: dict[str, str] = {} section_intros: dict[str, str] = {} # -- Theme colors and fonts for CRRA plots (used in plotly templates) ---------------------------------------------- CRRA_COLORS = { "off_white": "#eae9d8", "red": "#ff5f4d", "green_dark": "#298231", "green": "#55c95b", "green_light": "#92ef9b", "yellow": "#d9e210", "white": "#ffffff", "brown_grey": "#665d5b", "grey": "#a0a0a0", "black": "#000000", } CRRA_FONT = "Segoe UI, sans-serif" PLOTLY_COLOR_SEQUENCE = [ CRRA_COLORS["red"], CRRA_COLORS["green"], CRRA_COLORS["yellow"], CRRA_COLORS["green_dark"], CRRA_COLORS["brown_grey"], CRRA_COLORS["green_light"], CRRA_COLORS["grey"], ] PLOTLY_HEATMAP_SCALE = [ [0.0, CRRA_COLORS["white"]], [0.5, CRRA_COLORS["green_light"]], [1.0, CRRA_COLORS["green_dark"]], ] PLOTLY_TEMPLATE = "plotly_white"