Skip to content
Merged
79 changes: 75 additions & 4 deletions rate_design/ny/hp_rates/data/tariff_map/Justfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,86 @@
# Resolve project root via git (works from any subdirectory in the repo)
project_root := `git rev-parse --show-toplevel`
path_s3_resstock_metadata := "s3://data.sb/nrel/resstock/res_2024_amy2018_2/metadata"
tariff_map_dir_ny := "{{project_root}}/rate_design/ny/hp_rates/data/tariff_map"

# Usage: just map-electric-tariff [electric_utility] [SB_scenario_type] [SB_scenario_year] [upgrade_id]
# Example: just map-electric-tariff Coned default 1 00
map-electric-tariff electric_utility SB_scenario_type SB_scenario_year upgrade_id output_dir="":
# Usage: just map-electric-tariff [electric_utility] [SB_scenario_type] [SB_scenario_year] [upgrade_id] [output_dir]
# Example: just map-electric-tariff Coned default 1 00 ./rate_design/ny/hp_rates/data/tariff_map
map-electric-tariff electric_utility SB_scenario_type SB_scenario_year upgrade_id output_dir:
uv run python {{project_root}}/utils/electric_tariff_mapper.py \
--metadata_path "{{path_s3_resstock_metadata}}" \
--state NY \
--upgrade_id "{{upgrade_id}}" \
--electric_utility "{{electric_utility}}" \
--SB_scenario_type "{{SB_scenario_type}}" \
--SB_scenario_year "{{SB_scenario_year}}" \
{{ if output_dir != "" { "--output_dir \"" + output_dir + "\"" } else { "" } }}
--output_dir "{{output_dir}}"

# Some useful enumerations:

map-electric-coned-default:
just map-electric-tariff Coned default 1 00 {{tariff_map_dir_ny}}

map-electric-coned-seasonal:
just map-electric-tariff Coned seasonal 1 00 {{tariff_map_dir_ny}}

map-celectric-oned-class-specific-seasonal:
just map-electric-tariff Coned class_specific_seasonal 1 00 {{tariff_map_dir_ny}}

map-electric-national-grid-default:
just map-electric-tariff "National Grid" default 1 00 {{tariff_map_dir_ny}}

map-electric-national-grid-seasonal:
just map-electric-tariff "National Grid" seasonal 1 00 {{tariff_map_dir_ny}}

map-electric-national-grid-class-specific-seasonal:
just map-electric-tariff "National Grid" class_specific_seasonal 1 00 {{tariff_map_dir_ny}}

map-electric-nyseg-default:
just map-electric-tariff NYSEG default 1 00 {{tariff_map_dir_ny}}

map-electric-nyseg-seasonal:
just map-electric-tariff NYSEG seasonal 1 00 {{tariff_map_dir_ny}}

map-electric-nyseg-class-specific-seasonal:
just map-electric-tariff NYSEG class_specific_seasonal 1 00 {{tariff_map_dir_ny}}

# Usage: just map-gas-tariff [electric_utility] [upgrade_id] [output_dir]
# Example: just map-gas-tariff NYSEG 00 ./rate_design/ny/hp_rates/data/tariff_map
map-gas-tariff electric_utility upgrade_id output_dir:
uv run python {{project_root}}/utils/gas_tariff_mapper.py \
--metadata_path "{{path_s3_resstock_metadata}}" \
--state NY \
--upgrade_id "{{upgrade_id}}" \
--electric_utility "{{electric_utility}}" \
--output_dir "{{output_dir}}"

# Some useful enumerations:

map-gas-coned-default:
just map-gas-tariff Coned 00 {{tariff_map_dir_ny}}

map-gas-coned-seasonal:
just map-gas-tariff Coned 00 {{tariff_map_dir_ny}}

map-gas-coned-class-specific-seasonal:
just map-gas-tariff Coned 00 {{tariff_map_dir_ny}}

map-gas-national-grid-default:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ny}}

map-gas-national-grid-seasonal:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ny}}

map-gas-national-grid-class-specific-seasonal:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ny}}

map-gas-nyseg-default:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ny}}

map-gas-nyseg-seasonal:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ny}}

map-gas-nyseg-class-specific-seasonal:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ny}}


80 changes: 75 additions & 5 deletions rate_design/ri/hp_rates/data/tariff_map/Justfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,85 @@
# Resolve project root via git (works from any subdirectory in the repo)
project_root := `git rev-parse --show-toplevel`
path_s3_resstock_metadata := "s3://data.sb/nrel/resstock/res_2024_amy2018_2/metadata"
tariff_map_dir_ri := "{{project_root}}/rate_design/ri/hp_rates/data/tariff_map"

# Usage: just map-electric-tariff [electric_utility] [SB_scenario_type] [SB_scenario_year] [upgrade_id]
# Example: just map-electric-tariff Coned default 1 00
map-electric-tariff electric_utility SB_scenario_type SB_scenario_year upgrade_id output_dir="":
# Usage: just map-electric-tariff [electric_utility] [SB_scenario_type] [SB_scenario_year] [upgrade_id] [output_dir]
# Example: just map-electric-tariff Coned default 1 00 ./rate_design/ri/hp_rates/data/tariff_map
map-electric-tariff electric_utility SB_scenario_type SB_scenario_year upgrade_id output_dir:
uv run python {{project_root}}/utils/electric_tariff_mapper.py \
--metadata_path "{{path_s3_resstock_metadata}}" \
--state RI \
--upgrade_id "{{upgrade_id}}" \
--electric_utility "{{electric_utility}}" \
--SB_scenario_type "{{SB_scenario_type}}" \
--SB_scenario_year "{{SB_scenario_year}}"
{{ if output_dir != "" { "--output_dir \"" + output_dir + "\"" } else { "" } }}
--SB_scenario_year "{{SB_scenario_year}}" \
--output_dir "{{output_dir}}"

# Some useful enumerations:

map-electric-coned-default:
just map-electric-tariff Coned default 1 00 {{tariff_map_dir_ri}}

map-electric-coned-seasonal:
just map-electric-tariff Coned seasonal 1 00 {{tariff_map_dir_ri}}

map-celectric-oned-class-specific-seasonal:
just map-electric-tariff Coned class_specific_seasonal 1 00 {{tariff_map_dir_ri}}

map-electric-national-grid-default:
just map-electric-tariff "National Grid" default 1 00 {{tariff_map_dir_ri}}

map-electric-national-grid-seasonal:
just map-electric-tariff "National Grid" seasonal 1 00 {{tariff_map_dir_ri}}

map-electric-national-grid-class-specific-seasonal:
just map-electric-tariff "National Grid" class_specific_seasonal 1 00 {{tariff_map_dir_ri}}

map-electric-nyseg-default:
just map-electric-tariff NYSEG default 1 00 {{tariff_map_dir_ri}}

map-electric-nyseg-seasonal:
just map-electric-tariff NYSEG seasonal 1 00 {{tariff_map_dir_ri}}

map-electric-nyseg-class-specific-seasonal:
just map-electric-tariff NYSEG class_specific_seasonal 1 00 {{tariff_map_dir_ri}}


# Usage: just map-gas-tariff [electric_utility] [upgrade_id] [output_dir]
# Example: just map-gas-tariff "National Grid" 00 ./rate_design/ri/hp_rates/data/tariff_map
map-gas-tariff electric_utility upgrade_id output_dir:
uv run python {{project_root}}/utils/gas_tariff_mapper.py \
--metadata_path "{{path_s3_resstock_metadata}}" \
--state RI \
--upgrade_id "{{upgrade_id}}" \
--electric_utility "{{electric_utility}}" \
--output_dir "{{output_dir}}"

# Some useful enumerations:

map-gas-coned-default:
just map-gas-tariff Coned 00 {{tariff_map_dir_ri}}

map-gas-coned-seasonal:
just map-gas-tariff Coned 00 {{tariff_map_dir_ri}}

map-gas-coned-class-specific-seasonal:
just map-gas-tariff Coned 00 {{tariff_map_dir_ri}}

map-gas-national-grid-default:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ri}}

map-gas-national-grid-seasonal:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ri}}

map-gas-national-grid-class-specific-seasonal:
just map-gas-tariff "National Grid" 00 {{tariff_map_dir_ri}}

map-gas-nyseg-default:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ri}}

map-gas-nyseg-seasonal:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ri}}

map-gas-nyseg-class-specific-seasonal:
just map-gas-tariff NYSEG 00 {{tariff_map_dir_ri}}
34 changes: 34 additions & 0 deletions utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,35 @@
"""Utility helpers wrapping external packages (stub)."""

import os
import subprocess
from pathlib import Path


def get_aws_region(default: str = "us-west-2") -> str:
"""Return AWS region from env (AWS_REGION / AWS_DEFAULT_REGION) or from AWS config (~/.aws/config) via boto3."""
region = os.environ.get("AWS_REGION") or os.environ.get("AWS_DEFAULT_REGION")
if region:
return region
try:
import boto3
session = boto3.Session()
if session.region_name:
return session.region_name
except ImportError:
pass
return default


def get_project_root() -> Path:
"""Return the repository root as an absolute path (via git rev-parse --show-toplevel)."""
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
capture_output=True,
text=True,
cwd=Path.cwd(),
)
if result.returncode != 0:
raise RuntimeError(
"Could not find project root (run from inside the git repository)"
)
return Path(result.stdout.strip()).resolve()
64 changes: 24 additions & 40 deletions utils/electric_tariff_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@
import polars as pl
from cloudpathlib import S3Path

from utils import get_aws_region
from utils.types import SBScenario, electric_utility

# Project root (rate-design-platform); independent of cwd or caller
_PROJECT_ROOT = Path(__file__).resolve().parent.parent
RATE_DESIGN_DIR = _PROJECT_ROOT / "rate_design"

AWS_REGION = "us-west-2"

STORAGE_OPTIONS = {"aws_region": AWS_REGION}
STORAGE_OPTIONS = {"aws_region": get_aws_region()}


def define_electrical_tariff_key(
Expand Down Expand Up @@ -49,12 +44,12 @@ def generate_electrical_tariff_mapping(


def map_electric_tariff(
SB_metadata_lazy_df: pl.LazyFrame,
SB_metadata_df: pl.LazyFrame,
electric_utility: electric_utility,
SB_scenario: SBScenario,
state: str,
) -> pl.LazyFrame:
utility_metadata_df = SB_metadata_lazy_df.filter(
utility_metadata_df = SB_metadata_df.filter(
pl.col("sb.electric_utility") == electric_utility
)

Expand All @@ -75,7 +70,9 @@ def map_electric_tariff(


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Map electrical tariff.")
parser = argparse.ArgumentParser(
description="Utility to help assign electricity tariffs to utility customers."
)
parser.add_argument(
"--metadata_path",
required=True,
Expand All @@ -92,12 +89,12 @@ def map_electric_tariff(
help="SB scenario type (e.g. default, seasonal, class_specific_seasonal)",
)
parser.add_argument(
"--SB_scenario_year", required=True, help="SB scenario year (e.g. 2024)"
"--SB_scenario_year", required=True, help="SB scenario year (e.g. 1 , 2, 3)"
)
parser.add_argument(
"--output_dir",
default=None,
help="Optional directory for output CSV; default is rate_design/<state>/hp_rates/data/tariff_map/",
required=True,
help="Output directory for output CSV",
)
args = parser.parse_args()

Expand All @@ -115,7 +112,7 @@ def map_electric_tariff(
if not metadata_path.exists():
raise FileNotFoundError(f"Metadata path {metadata_path} does not exist")
# Polars scan_parquet needs a string path; S3Path.as_uri() gives s3:// URL
SB_metadata_lazy_df = pl.scan_parquet(
SB_metadata_df = pl.scan_parquet(
str(metadata_path), storage_options=STORAGE_OPTIONS
)
except ValueError:
Expand All @@ -129,10 +126,10 @@ def map_electric_tariff(
)
if not metadata_path.exists():
raise FileNotFoundError(f"Metadata path {metadata_path} does not exist")
SB_metadata_lazy_df = pl.scan_parquet(str(metadata_path))
SB_metadata_df = pl.scan_parquet(str(metadata_path))

# Add dummy electric utility column (deterministic by bldg_id). Later this column will be pre-existing in the SB metadata parquet.
SB_metadata_lazy_df_with_electric_utility = SB_metadata_lazy_df.with_columns(
SB_metadata_df_with_electric_utility = SB_metadata_df.with_columns(
pl.when(pl.col("bldg_id").hash() % 3 == 0)
.then(pl.lit("Coned"))
.when(pl.col("bldg_id").hash() % 3 == 1)
Expand All @@ -144,35 +141,22 @@ def map_electric_tariff(

sb_scenario = SBScenario(args.SB_scenario_type, args.SB_scenario_year)
electrical_tariff_mapping_df = map_electric_tariff(
SB_metadata_lazy_df=SB_metadata_lazy_df_with_electric_utility,
SB_metadata_df=SB_metadata_df_with_electric_utility,
electric_utility=args.electric_utility,
SB_scenario=sb_scenario,
state=args.state,
)
if args.output_dir:
try:
base_path = S3Path(args.output_dir)
output_path = base_path / f"{args.electric_utility}_{sb_scenario}.csv"
if not output_path.parent.exists():
output_path.parent.mkdir(parents=True)
electrical_tariff_mapping_df.sink_csv(
str(output_path), storage_options=STORAGE_OPTIONS
)
except ValueError:
base_path = Path(args.output_dir)
output_path = base_path / f"{args.electric_utility}_{sb_scenario}.csv"
if not output_path.parent.exists():
output_path.parent.mkdir(parents=True)
electrical_tariff_mapping_df.sink_csv(str(output_path))
else:
output_path = (
RATE_DESIGN_DIR
/ args.state.lower()
/ "hp_rates"
/ "data"
/ "tariff_map"
/ f"{args.electric_utility}_{sb_scenario}.csv"
try:
base_path = S3Path(args.output_dir)
output_path = base_path / f"{args.electric_utility}_{sb_scenario}.csv"
if not output_path.parent.exists():
output_path.parent.mkdir(parents=True)
electrical_tariff_mapping_df.sink_csv(
str(output_path), storage_options=STORAGE_OPTIONS
)
except ValueError:
base_path = Path(args.output_dir)
output_path = base_path / f"{args.electric_utility}_{sb_scenario}.csv"
if not output_path.parent.exists():
output_path.parent.mkdir(parents=True)
electrical_tariff_mapping_df.sink_csv(str(output_path))
Loading
Loading