Pipeline Helpers

High-level functions for end-to-end analysis workflows.

End-to-End Model Fitting

better_lbnl_os.fit_models_with_auto_weather(bills, floor_area, address=None, latitude=None, longitude=None, google_maps_api_key=None, openmeteo_api_key=None, min_r_squared=0.6, max_cv_rmse=0.5, use_typed=True)[source]

Convenience function that fetches weather and fits models in one call.

Parameters:
  • bills (list[UtilityBillData]) – List of utility bills

  • floor_area (float) – Building floor area in square meters (must be positive)

  • address (str | None) – Address string to geocode (if lat/lon not supplied)

  • latitude (float | None) – Latitude coordinate if known

  • longitude (float | None) – Longitude coordinate if known

  • google_maps_api_key (str | None) – Google Maps API key for geocoding (required)

  • openmeteo_api_key (str | None) – Optional OpenMeteo API key (paid archive)

  • min_r_squared (float) – Minimum R² threshold for model acceptance

  • max_cv_rmse (float) – Maximum CV-RMSE threshold for model acceptance

  • use_typed (bool) – If True, use typed CalendarizedData (recommended)

Returns:

Dictionary mapping energy type to fitted model results

Return type:

dict[str, ChangePointModelResult]

better_lbnl_os.fit_models_from_inputs(bills, floor_area, weather, min_r_squared=0.6, max_cv_rmse=0.5)[source]

Fit change-point models directly from raw utility bills and weather data.

Parameters:
  • bills (list[UtilityBillData]) – List of utility bills

  • floor_area (float) – Building floor area in square meters (must be positive)

  • weather (list[WeatherData] | None) – Optional list of weather data

  • min_r_squared (float) – Minimum R² threshold for model acceptance

  • max_cv_rmse (float) – Maximum CV-RMSE threshold for model acceptance

  • use_typed – If True, use typed CalendarizedData (recommended)

Returns:

Dictionary mapping energy type to fitted model results

Raises:

ValueError – If floor_area is not positive

Return type:

dict[str, ChangePointModelResult]

better_lbnl_os.fit_calendarized_models(calendarized, min_r_squared=0.6, max_cv_rmse=0.5, energy_types=('ELECTRICITY', 'FOSSIL_FUEL'))[source]

Fit change-point models for available energy types from calendarized data.

Parameters:
  • calendarized (dict | CalendarizedData) – Either a CalendarizedData object or legacy dict format

  • min_r_squared (float) – Minimum R² threshold for model acceptance

  • max_cv_rmse (float) – Maximum CV-RMSE threshold for model acceptance

  • energy_types (tuple[str, ...]) – Energy types to attempt fitting

Returns:

Dictionary mapping energy type to fitted model results

Return type:

dict[str, ChangePointModelResult]

Data Preparation

better_lbnl_os.prepare_model_data(calendarized, energy_types=('ELECTRICITY', 'FOSSIL_FUEL'), window=12)[source]

Extract, gate, and trim model-ready arrays per energy type.

Parameters:
  • calendarized (CalendarizedData | dict) – CalendarizedData model or legacy dict format

  • energy_types (tuple[str, ...]) – Energy types to process

  • window (int) – Minimum consecutive months required

Returns:

Dict keyed by energy type with ModelData (temperature, eui, months, days). Only includes energy types with sufficient consecutive data after trimming.

Return type:

dict[str, ModelData]

Note

Uses get_consecutive_months() which handles both CalendarizedData and dict.

better_lbnl_os.get_weather_for_bills(bills, address=None, latitude=None, longitude=None, google_maps_api_key=None, openmeteo_api_key=None)[source]

Fetch monthly weather for the full bill date range using OpenMeteo.

Parameters:
  • bills (list[UtilityBillData]) – Utility bills to derive the date range

  • address (str | None) – Address string to geocode (if lat/lon not supplied)

  • latitude (float | None) – Latitude coordinate if known

  • longitude (float | None) – Longitude coordinate if known

  • google_maps_api_key (str | None) – Google Maps API key for geocoding (required)

  • openmeteo_api_key (str | None) – Optional OpenMeteo API key (paid archive)

Returns:

List of WeatherData, one per month.

Raises:

ValueError – If neither coordinates nor address provided, or if geocoding API key missing

Return type:

list[WeatherData]

Location Resolution

better_lbnl_os.resolve_location(*, address=None, latitude=None, longitude=None, google_maps_api_key=None)[source]

Resolve location metadata using Google Maps geocoding.

Parameters:
  • address (str | None)

  • latitude (float | None)

  • longitude (float | None)

  • google_maps_api_key (str | None)

Return type:

LocationInfo

Services

class better_lbnl_os.BuildingAnalyticsService[source]

Bases: object

Service for orchestrating building energy analysis workflows.

analyze_building(building, utility_bills, weather_data)[source]
Parameters:
Return type:

dict

fit_models(building, utility_bills, weather_data)[source]
Parameters:
Return type:

list[ChangePointModelResult]

benchmark_building(building, model_results)[source]
Parameters:
Return type:

BenchmarkResult

estimate_savings(building, benchmark_result, utility_bills)[source]
Parameters:
Return type:

SavingsEstimate

recommend_measures(building, model_results, benchmark_result)[source]
Parameters:
Return type:

list[EEMeasureRecommendation]

class better_lbnl_os.PortfolioBenchmarkService[source]

Bases: object

Service for portfolio-level benchmarking and analysis.

__init__()[source]
add_building(building, benchmark_result)[source]
Parameters:
Return type:

None

calculate_portfolio_metrics()[source]
Return type:

dict

identify_improvement_targets(top_n=10)[source]
Parameters:

top_n (int)

Return type:

list[str]

generate_portfolio_report()[source]
Return type:

dict