import gymnasium as gym import sinergym import pandas as pd import numpy as np import os import json import sys from unihvac.find_files import ( detect_paths, find_manifest, find_building_and_weather_from_manifest, ) from unihvac.tables import ( print_monthly_tables_extra, print_monthly_tables_split, ) from unihvac.rollout import run_rollout_to_df from unihvac.data_generator import save_dt_training_data # ============================================ # FOR TABLE pd.set_option("display.max_columns", None) pd.set_option("display.width", 240) pd.set_option("display.max_colwidth", 32) pd.set_option("display.float_format", lambda x: f"{x:,.2f}") # ============================================ # ============================================================================== # USER CONFIGURATION # ============================================================================== TARGET_LOCATION = "Fairbanks" TARGET_THERMAL = "default" TARGET_OCCUPANCY = "standard" HEATING_SP = 21.0 COOLING_SP = 24.0 # ========================================== # PATH DISCOVERY (ROBUST) # ========================================== paths = detect_paths(outputs_dirname="baseline_results") # Get manifest (patched preferred) manifest_path = find_manifest(paths, building="OfficeSmall", prefer_patched=True) output_root = str(paths.outputs_root) os.makedirs(output_root, exist_ok=True) OUTPUT_DIR = "rollout_run" TIME_STEP_HOURS = 900.0 / 3600.0 # 0.25 h # ========================================== # 3. COMMON ACTUATORS & VARIABLES # ========================================== hot_actuators = { "Htg_Core": ("Zone Temperature Control", "Heating Setpoint", "CORE_ZN"), "Clg_Core": ("Zone Temperature Control", "Cooling Setpoint", "CORE_ZN"), "Htg_P1": ("Zone Temperature Control", "Heating Setpoint", "PERIMETER_ZN_1"), "Clg_P1": ("Zone Temperature Control", "Cooling Setpoint", "PERIMETER_ZN_1"), "Htg_P2": ("Zone Temperature Control", "Heating Setpoint", "PERIMETER_ZN_2"), "Clg_P2": ("Zone Temperature Control", "Cooling Setpoint", "PERIMETER_ZN_2"), "Htg_P3": ("Zone Temperature Control", "Heating Setpoint", "PERIMETER_ZN_3"), "Clg_P3": ("Zone Temperature Control", "Cooling Setpoint", "PERIMETER_ZN_3"), "Htg_P4": ("Zone Temperature Control", "Heating Setpoint", "PERIMETER_ZN_4"), "Clg_P4": ("Zone Temperature Control", "Cooling Setpoint", "PERIMETER_ZN_4"), } hot_variables = { "outdoor_temp": ("Site Outdoor Air DryBulb Temperature", "Environment"), "core_temp": ("Zone Air Temperature", "Core_ZN"), "perim1_temp": ("Zone Air Temperature", "Perimeter_ZN_1"), "perim2_temp": ("Zone Air Temperature", "Perimeter_ZN_2"), "perim3_temp": ("Zone Air Temperature", "Perimeter_ZN_3"), "perim4_temp": ("Zone Air Temperature", "Perimeter_ZN_4"), "elec_power": ("Facility Total HVAC Electricity Demand Rate", "Whole Building"), "core_occ_count": ("Zone People Occupant Count", "CORE_ZN"), "perim1_occ_count": ("Zone People Occupant Count", "PERIMETER_ZN_1"), "perim2_occ_count": ("Zone People Occupant Count", "PERIMETER_ZN_2"), "perim3_occ_count": ("Zone People Occupant Count", "PERIMETER_ZN_3"), "perim4_occ_count": ("Zone People Occupant Count", "PERIMETER_ZN_4"), "outdoor_dewpoint": ("Site Outdoor Air Dewpoint Temperature", "Environment"), "outdoor_wetbulb": ("Site Outdoor Air Wetbulb Temperature", "Environment"), "core_rh": ("Zone Air Relative Humidity", "CORE_ZN"), "perim1_rh": ("Zone Air Relative Humidity", "PERIMETER_ZN_1"), "perim2_rh": ("Zone Air Relative Humidity", "PERIMETER_ZN_2"), "perim3_rh": ("Zone Air Relative Humidity", "PERIMETER_ZN_3"), "perim4_rh": ("Zone Air Relative Humidity", "PERIMETER_ZN_4"), } class BaselineReward: def __init__(self, *args, **kwargs): pass def __call__(self, obs_dict): return 0.0, {} # ========================================== # 5. RBC CONTROLLER (CONSTANT SETPOINTS) # ========================================== def get_constant_rbc(): h_sp, c_sp = HEATING_SP, COOLING_SP action = np.array([h_sp, c_sp] * 5, dtype=np.float32) return action, h_sp, c_sp def run_baseline_for_location(location, building_path, weather_path): print("\n" + "=" * 80) print(f"Running baseline for location: {location}") print(f" Building: {building_path}") print(f" Weather: {weather_path}") print("=" * 80) out_dir = os.path.join(output_root, location) os.makedirs(out_dir, exist_ok=True) def policy_fn(obs, info, step): action, _, _ = get_constant_rbc() return action df = run_rollout_to_df( building_path=str(building_path), weather_path=str(weather_path), variables=hot_variables, actuators=hot_actuators, policy_fn=policy_fn, location=location, timestep_hours=TIME_STEP_HOURS, heating_sp=HEATING_SP, cooling_sp=COOLING_SP, reward=BaselineReward, max_steps=None, verbose=True, ) print("setpoint_htg min/max:", df["setpoint_htg"].min(), df["setpoint_htg"].max()) print("setpoint_clg min/max:", df["setpoint_clg"].min(), df["setpoint_clg"].max()) print("comfort_violation min/mean/max:", df["comfort_violation_degCh"].min(), df["comfort_violation_degCh"].mean(), df["comfort_violation_degCh"].max()) df["setpoint_htg"] = HEATING_SP df["setpoint_clg"] = COOLING_SP # 7) Print the same tables print_monthly_tables_extra(df, location) print_monthly_tables_split(df, location, time_step_hours=TIME_STEP_HOURS) # Save raw timeseries for inspection df.to_csv(os.path.join(out_dir, "baseline_timeseries.csv"), index=False) save_dt_training_data(df, out_dir, location=location) if "month" in df.columns: monthly_energy = df.groupby("month") return df, monthly_energy return df, None if __name__ == "__main__": bpath, wpath = find_building_and_weather_from_manifest( manifest_path, location=TARGET_LOCATION, occupancy=TARGET_OCCUPANCY, thermal=TARGET_THERMAL, require_patched=True, ) run_baseline_for_location(TARGET_LOCATION, str(bpath), str(wpath))