Skip to content

Commit

Permalink
BETTER v1.7 updates (#4679)
Browse files Browse the repository at this point in the history
* better v1.7 updates

* Lint

---------

Co-authored-by: Alex Swindler <[email protected]>
  • Loading branch information
kflemin and axelstudios authored Jul 9, 2024
1 parent 9a5d6c3 commit ae130ce
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 43 deletions.
3 changes: 3 additions & 0 deletions seed/analysis_pipelines/better/buildingsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@
"Retail Store": "Retail",
"Senior Care Community": "Health care-Skilled nursing facility",
"Supermarket/Grocery Store": "Food sales-Grocery store",
"Restaurant": "Food service",
"Public Library": "Assembly-Public",
"Other": "Other",
}


# maps SEED Meter types to BuildingSync ResourceUse types
# NOTE: this is semi-redundant with to_energy_type dict in building_sync/mappings.py
SEED_TO_BSYNC_RESOURCE_TYPE = {
Expand Down
88 changes: 49 additions & 39 deletions seed/analysis_pipelines/better/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ def _start_analysis(self, analysis_id):
progress_data = pipeline.set_analysis_status_to_running()
progress_data.step("Sending requests to BETTER service")
analysis = Analysis.objects.get(id=analysis_id)

client = BETTERClient(analysis.organization.better_analysis_api_key)
context = BETTERPipelineContext(analysis, progress_data, client)

Expand All @@ -310,9 +309,7 @@ def _start_analysis(self, analysis_id):
context,
fail_on_error=True,
)

better_building_analyses, better_portfolio_building_analyses = _create_better_buildings(better_portfolio_id, context)

if better_portfolio_id is not None:
better_portfolio_building_analyses = _run_better_portfolio_analysis(
better_portfolio_id,
Expand Down Expand Up @@ -350,38 +347,44 @@ def _process_results(self, analysis_id):
"""Store results from the analysis in the original PropertyState"""
pipeline = BETTERPipeline(analysis_id)
analysis = Analysis.objects.get(id=analysis_id)

progress_data = pipeline.get_progress_data(analysis)
progress_data.step("Processing results")

# store all measure recommendations
#
# Updated measure list 10/21/2023. There were several added and 4 removed/renamed which include removal of:
# 'Check Fossil Baseload', 'Decrease Ventilation', 'Eliminate Electric Heating', 'Upgrade Windows',
# The data will still exist in the database for historic reason, but new runs will not include those.
# store all (LEVEL 1) measure recommendations

# Updated measure list 05/20/2024 - BETTER workflow has changed in v1.7: The json data returned from the BA and PBA
# endpoints used to have a ee_measures key in the "assessments" dictionary with a dictionary of true / false values
# for every measure. Now, that same ee_measures key points to a list with the tokens for each measure that applies.
# There is no need to check for true or false...if the measure is in the list, it applies.

# switch to a list of "Level 1 measure" tokens here. Tokens can be found here (grab the top level "token" in each dictionary):
# https://better-lbnl-development.herokuapp.com/api/v1/measures/
# updating this list to a list of dictionary to keep the column names as close to the existing ones as possible
ee_measure_names = [
"Add/Fix Economizers",
"Add Wall/Ceiling/Roof Insulation",
"Decrease Heating Setpoints",
"Decrease Infiltration",
"Ensure Adequate Ventilation Rate",
"Increase Cooling Setpoints",
"Increase Cooling System Efficiency",
"Increase Heating System Efficiency",
"Reduce Equipment Schedules",
"Reduce Lighting Load",
"Reduce Plug Loads",
"Upgrade Windows to Improve Thermal Efficiency",
"Upgrade Windows to Reduce Solar Heat Gain",
"Upgrade to Sustainable Resources for Water Heating",
"Use High Efficiency Heat Pump for Heating",
{"token": "REDUCE_EQUIPMENT_SCHEDULES", "name": "Reduce Equipment Schedules"},
{"token": "REDUCE_LIGHTING_LOAD", "name": "Reduce Lighting Load"},
{"token": "REDUCE_PLUG_LOADS", "name": "Reduce Plug Loads"},
{"token": "INCREASE_COOLING_SYSTEM_EFFICIENCY", "name": "Increase Cooling System Efficiency"},
{"token": "DECREASE_HEATING_SETPOINTS", "name": "Decrease Heating Setpoints"},
{"token": "ENSURE_ADEQUATE_VENTILATION_RATE", "name": "Ensure Adequate Ventilation Rate"},
{"token": "DECREASE_INFILTRATION", "name": "Decrease Infiltration"},
{"token": "INCREASE_HEATING_SYSTEM_EFFICIENCY", "name": "Increase Heating System Efficiency"},
{"token": "ADD_WALL_CEILING_ROOF_INSULATION", "name": "Add Wall/Ceiling/Roof Insulation"},
{"token": "UPGRADE_TO_SUSTAINABLE_RESOURCES_FOR_WATER_HEATING", "name": "Upgrade to Sustainable Resources for Water Heating"},
{"token": "UPGRADE_WINDOWS_TO_REDUCE_SOLAR_HEAT_GAIN", "name": "Upgrade Windows to Reduce Solar Heat Gain"},
{"token": "USE_HIGH_EFFICIENCY_HEAT_PUMP_FOR_HEATING", "name": "Use High Efficiency Heat Pump for Heating"},
{"token": "INCREASE_COOLING_SETPOINTS", "name": "Increase Cooling Setpoints"},
{"token": "ADD_FIX_ECONOMIZERS", "name": "Add/Fix Economizers"},
{"token": "UPGRADE_WINDOWS_TO_IMPROVE_THERMAL_EFFICIENCY", "name": "Upgrade Windows to Improve Thermal Efficiency"},
{"token": "OTHER_AREAS", "name": "Other Areas"},
]

ee_measure_column_data_paths = [
ExtraDataColumnPath(
f'better_recommendation_{ee_measure_name.lower().replace(" ", "_")}',
f"BETTER Recommendation: {ee_measure_name}",
f'better_recommendation_{ee_measure_name["name"].lower().replace(" ", "_")}',
f'BETTER Recommendation: {ee_measure_name["name"]}',
1,
f"assessment.ee_measures.{ee_measure_name}",
f'assessment.ee_measures.{ee_measure_name["token"]}',
)
for ee_measure_name in ee_measure_names
]
Expand All @@ -393,64 +396,71 @@ def _process_results(self, analysis_id):
# if user is at root level and has role member or owner, columns can be created
# otherwise set the 'missing_columns' flag for later
missing_columns = False

column_data_paths = [
# Combined Savings
ExtraDataColumnPath(
"better_cost_savings_combined",
"BETTER Potential Cost Savings (USD)",
1,
"assessment.assessment_energy_use.cost_savings_combined",
"assessment.assessment_results.assessment_energy_use.cost_savings_combined",
),
ExtraDataColumnPath(
"better_energy_savings_combined",
"BETTER Potential Energy Savings (kWh)",
1,
"assessment.assessment_energy_use.energy_savings_combined",
"assessment.assessment_results.assessment_energy_use.energy_savings_combined",
),
ExtraDataColumnPath(
"better_ghg_reductions_combined",
"BETTER Potential GHG Emissions Reduction (MtCO2e)",
0.001,
"assessment.assessment_energy_use.ghg_reductions_combined",
"assessment.assessment_results.assessment_energy_use.ghg_reductions_combined",
),
# Energy-specific Savings
ExtraDataColumnPath(
BETTER_VALID_MODEL_E_COL, "BETTER Valid Electricity Model", 1, "assessment.assessment_energy_use.valid_model_e"
BETTER_VALID_MODEL_E_COL,
"BETTER Valid Electricity Model",
1,
"assessment.assessment_results.assessment_energy_use.valid_model_e",
),
ExtraDataColumnPath(
BETTER_VALID_MODEL_F_COL, "BETTER Valid Fuel Model", 1, "assessment.assessment_results.assessment_energy_use.valid_model_f"
),
ExtraDataColumnPath(BETTER_VALID_MODEL_F_COL, "BETTER Valid Fuel Model", 1, "assessment.assessment_energy_use.valid_model_f"),
ExtraDataColumnPath(
"better_cost_savings_electricity",
"BETTER Potential Electricity Cost Savings (USD)",
1,
"assessment.assessment_energy_use.cost_savings_e",
"assessment.assessment_results.assessment_energy_use.cost_savings_e",
),
ExtraDataColumnPath(
"better_cost_savings_fuel", "BETTER Potential Fuel Cost Savings (USD)", 1, "assessment.assessment_energy_use.cost_savings_f"
"better_cost_savings_fuel",
"BETTER Potential Fuel Cost Savings (USD)",
1,
"assessment.assessment_results.assessment_energy_use.cost_savings_f",
),
ExtraDataColumnPath(
"better_energy_savings_electricity",
"BETTER Potential Electricity Energy Savings (kWh)",
1,
"assessment.assessment_energy_use.energy_savings_e",
"assessment.assessment_results.assessment_energy_use.energy_savings_e",
),
ExtraDataColumnPath(
"better_energy_savings_fuel",
"BETTER Potential Fuel Energy Savings (kWh)",
1,
"assessment.assessment_energy_use.energy_savings_f",
"assessment.assessment_results.assessment_energy_use.energy_savings_f",
),
ExtraDataColumnPath(
"better_ghg_reductions_electricity",
"BETTER Potential Electricity GHG Emissions Reduction (MtCO2e)",
0.001,
"assessment.assessment_energy_use.ghg_reductions_e",
"assessment.assessment_results.assessment_energy_use.ghg_reductions_e",
),
ExtraDataColumnPath(
"better_ghg_reductions_fuel",
"BETTER Potential Fuel GHG Emissions Reduction (MtCO2e)",
0.001,
"assessment.assessment_energy_use.ghg_reductions_f",
"assessment.assessment_results.assessment_energy_use.ghg_reductions_f",
),
ExtraDataColumnPath(
# we will manually add this to the data later (it's not part of BETTER's results)
Expand Down
14 changes: 12 additions & 2 deletions seed/analysis_pipelines/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,18 @@ def get_json_path(json_path, data):
json_path = json_path.split(".")
result = data
for key in json_path:
result = result.get(key, {})

if isinstance(result, dict):
result = result.get(key, {})
elif isinstance(result, list):
# check if it's just a list of strings or a list of objects
if any(isinstance(val, dict) for val in result):
# it's a list of dicts, keep as before
result = result.get(key, {})
# it's a list of values, modify (mostly for new ee_measures syntax)
elif key in result:
result = 1
else:
result = 0
if isinstance(result, dict) and not result:
# path was probably not valid in the data...
return None
Expand Down
4 changes: 2 additions & 2 deletions seed/models/analyses.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ def get_highlights(self, property_id=None):
{
"name": ["Potential Cost Savings (USD)"],
"value_template": ["${json_value:,.2f}"],
"json_path": ["assessment.assessment_energy_use.cost_savings_combined"],
"json_path": ["assessment.assessment_results.assessment_energy_use.cost_savings_combined"],
},
{
"name": ["Potential Energy Savings"],
"value_template": ["{json_value:,.2f} kWh"],
"json_path": ["assessment.assessment_energy_use.energy_savings_combined"],
"json_path": ["assessment.assessment_results.assessment_energy_use.energy_savings_combined"],
},
{
"name": ["BETTER Inverse Model R^2 (Electricity", "Fossil Fuel)"],
Expand Down

0 comments on commit ae130ce

Please sign in to comment.