Skip to content

Commit

Permalink
Merge pull request #37 from NREL/upgrades_analyzer_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
rajeee authored Dec 21, 2023
2 parents 13144cd + 0a32cf4 commit e1fc201
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 37 deletions.
27 changes: 27 additions & 0 deletions buildstock_query/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import pickle
import os
import pandas as pd
from pathlib import Path
import json
from typing import Literal, TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -151,3 +153,28 @@ def read_csv(csv_file_path, **kwargs) -> pd.DataFrame:
default_na_values = pd._libs.parsers.STR_NA_VALUES
df = pd.read_csv(csv_file_path, na_values=list(default_na_values - {"None"}), keep_default_na=False, **kwargs)
return df


def load_script_defaults(defaults_name):
"""
Load the default input for script from cache
"""
cache_folder = Path(".bsq_cache")
cache_folder.mkdir(exist_ok=True)
defaults_cache = cache_folder / f"{defaults_name}_defaults.json"
defaults = {}
if defaults_cache.exists():
with open(defaults_cache) as f:
defaults = json.load(f)
return defaults


def save_script_defaults(defaults_name, defaults):
"""
Save the current input for script to cache as the default for next run
"""
cache_folder = Path(".bsq_cache")
cache_folder.mkdir(exist_ok=True)
defaults_cache = cache_folder / f"{defaults_name}_defaults.json"
with open(defaults_cache, "w") as f:
json.dump(defaults, f)
51 changes: 24 additions & 27 deletions buildstock_query/tools/upgrades_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
from typing import Optional
from collections import defaultdict
from pathlib import Path
from .logic_parser import LogicParser
from buildstock_query.tools.logic_parser import LogicParser
from tabulate import tabulate
from buildstock_query.helpers import read_csv
from buildstock_query.helpers import read_csv, load_script_defaults, save_script_defaults

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -353,7 +353,7 @@ def _normalize_lists(logic, parent=None):
else:
return logic

def _get_options_application_count_report(self, logic_dict) -> Optional[pd.DataFrame]:
def _get_options_application_count_report(self, logic_dict) -> pd.DataFrame:
"""
For a given logic dictionary, this method will return a report df of options application.
Example report below:
Expand All @@ -369,10 +369,6 @@ def _get_options_application_count_report(self, logic_dict) -> Optional[pd.DataF
5 1, 6, 8, 13, 14 42 (0.0%) 296 (0.3%) 2959 (3.0%)
"""

n_options = len(logic_dict)
if n_options < 2:
return None

logic_df = pd.DataFrame(logic_dict)
nbldgs = len(logic_df)
opts2count = logic_df.apply(lambda row: tuple(indx+1 for indx, val in enumerate(row) if val),
Expand All @@ -396,10 +392,7 @@ def _get_options_application_count_report(self, logic_dict) -> Optional[pd.DataF
application_report_rows.append(record)

assert cum_count_all <= nbldgs, "Cumulative count of options applied is more than total number of buildings."
if application_report_rows:
application_report_df = pd.DataFrame(application_report_rows).set_index("Number of options")
return application_report_df
return None
return pd.DataFrame(application_report_rows).set_index("Number of options")

def _get_left_out_report_all(self, upgrade_num):
cfg = self.get_cfg()
Expand Down Expand Up @@ -564,20 +557,18 @@ def _get_detailed_report_all(self, upgrade_num, normalize_logic: bool = False):
report_str += f"Any of the options (or-ing) were applied to: {or_count} ({self._to_pct(or_count)}%)" + "\n"

option_app_report = self._get_options_application_count_report(grouped_conds_dict)
if option_app_report is not None:
report_str += "-" * 80 + "\n"
report_str += f"Report of how the {len(grouped_conds_dict)} options were applied to the buildings." + "\n"
report_str += tabulate(option_app_report, headers='keys', tablefmt='grid', maxcolwidths=50) + "\n"
report_str += "-" * 80 + "\n"
report_str += f"Report of how the {len(grouped_conds_dict)} options were applied to the buildings." + "\n"
report_str += tabulate(option_app_report, headers='keys', tablefmt='grid', maxcolwidths=50) + "\n"

detailed_app_report_df = self._get_options_application_count_report(conds_dict)
if detailed_app_report_df is not None:
report_str += "-" * 80 + "\n"
if len(detailed_app_report_df) > 100:
report_str += "Detailed report is skipped because of too many rows. " + "\n"
report_str += "Ask the developer if this is useful to see" + "\n"
else:
report_str += f"Detailed report of how the {n_options} options were applied to the buildings." + "\n"
report_str += tabulate(option_app_report, headers='keys', tablefmt='grid', maxcolwidths=50) + "\n"
report_str += "-" * 80 + "\n"
if len(detailed_app_report_df) > 100:
report_str += "Detailed report is skipped because of too many rows. " + "\n"
report_str += "Ask the developer if this is useful to see" + "\n"
else:
report_str += f"Detailed report of how the {n_options} options were applied to the buildings." + "\n"
report_str += tabulate(detailed_app_report_df, headers='keys', tablefmt='grid', maxcolwidths=50) + "\n"
return or_array, report_str

def _to_pct(self, count, total=None):
Expand Down Expand Up @@ -647,24 +638,30 @@ def save_detailed_report_all(self, file_path: str, logic_transform=None):


def main():
defaults = load_script_defaults("project_info")
yaml_file = inquirer.filepath(
message="Project configuration file (EUSS-project-file.yml):",
message="Project configuration file (the yaml file):",
default=defaults.get("yaml_file", ""),
validate=PathValidator(),
filter=lambda x: x or "EUSS-project-file.yml",
).execute()
buildstock_file = inquirer.filepath(
message="Project sample file (buildstock.csv):",
default=defaults.get("buildstock_file", ""),
validate=PathValidator(),
filter=lambda x: x or "buildstock.csv",
).execute()
opt_sat_file = inquirer.filepath(
message="Path to option_saturation.csv file",
default=defaults.get("opt_sat_file", ""),
validate=PathValidator()
).execute()
output_prefix = inquirer.text(
message="output file name prefix:",
filter=lambda x: "" if x is None else f"{x}_",
default=defaults.get("output_prefix", ""),
filter=lambda x: "" if x is None else f"{x}",
).execute()
defaults.update({"yaml_file": yaml_file, "buildstock_file": buildstock_file, "opt_sat_file": opt_sat_file,
"output_prefix": output_prefix})
save_script_defaults("project_info", defaults)
ua = UpgradesAnalyzer(yaml_file, buildstock_file, opt_sat_file)
report_df = ua.get_report()
folder_path = Path.cwd()
Expand Down
24 changes: 14 additions & 10 deletions buildstock_query/tools/upgrades_visualizer/upgrades_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from buildstock_query.tools.upgrades_visualizer.viz_data import VizData
from buildstock_query.tools.upgrades_visualizer.plot_utils import PlotParams, ValueTypes, SavingsTypes
from buildstock_query.tools.upgrades_visualizer.figure import UpgradesPlot
from buildstock_query.helpers import load_script_defaults, save_script_defaults
import polars as pl

# os.chdir("/Users/radhikar/Documents/eulpda/EULP-data-analysis/eulpda/smart_query/")
Expand Down Expand Up @@ -811,25 +812,28 @@ def update_figure(view_tab, grp_by, fuel, enduse, graph_type, savings_type, chng

def main():
print("Welcome to Upgrades Visualizer.")
yaml_path = inquirer.text(message="Please enter path to the buildstock configuration yml file: ",
default="").execute()
opt_sat_path = inquirer.text(message="Please enter path to the options saturation csv file: ",
default="").execute()
defaults = load_script_defaults("project_info")
yaml_file = inquirer.text(message="Please enter path to the buildstock configuration yml file: ",
default=defaults.get("yaml_file", "")).execute()
opt_sat_file = inquirer.text(message="Please enter path to the options saturation csv file: ",
default=defaults.get("opt_sat_file", "")).execute()
workgroup = inquirer.text(message="Please Athena workgroup name: ",
default="rescore").execute()
default=defaults.get("workgroup", "")).execute()
db_name = inquirer.text(message="Please enter database_name "
"(found in postprocessing:aws:athena in the buildstock configuration file): ",
default='').execute()
default=defaults.get("db_name", "")).execute()
table_name = inquirer.text(message="Please enter table name (same as output folder name; found under "
"output_directory in the buildstock configuration file). [Enter two names "
"separated by comma if baseline and upgrades are in different run] :",
default=""
default=defaults.get("table_name", "")
).execute()

defaults.update({"yaml_file": yaml_file, "opt_sat_file": opt_sat_file, "workgroup": workgroup,
"db_name": db_name, "table_name": table_name})
save_script_defaults("project_info", defaults)
if ',' in table_name:
table_name = table_name.split(',')
app = _get_app(yaml_path=yaml_path,
opt_sat_path=opt_sat_path,
app = _get_app(yaml_path=yaml_file,
opt_sat_path=opt_sat_file,
workgroup=workgroup,
db_name=db_name,
table_name=table_name)
Expand Down

0 comments on commit e1fc201

Please sign in to comment.