diff --git a/bpeng/__init__.py b/bpeng/__init__.py index 76ce1c00636a1f47a842b3ab8eced04e317fbdd8..e9a954aa7a687d1b9fda3030ac2b652388f86c8d 100644 --- a/bpeng/__init__.py +++ b/bpeng/__init__.py @@ -1,2 +1,3 @@ from .heatloss.heatloss import HeatLoss from .dimensions.parse_dimensions import ParseDimensions +from .reports.cbra_diag import CbraDiagnostic diff --git a/bpeng/reports/cbra_diag.py b/bpeng/reports/cbra_diag.py index 844970a951a8e84c38e34c72478f5fd87b4d75e4..d5e56916d5c6d6529b360557cbd09870e93efb92 100644 --- a/bpeng/reports/cbra_diag.py +++ b/bpeng/reports/cbra_diag.py @@ -29,22 +29,51 @@ class CbraDiagnostic: """ @staticmethod - def _generate_report(template_file, sheet_input): + def _generate_report( + template_file, + project_summary_data, + util_break_data, + heat_loss_data, + ecm_data, + ): """ Generate powerpoint file Args: template_file (str): pptx template stored on S3 and Drive - sheet_input (pandas dataframe): engineering calculation output dataframe + project_summmary_data + util_break_data + heat_loss_data + ecm_data + Returns: str: the address of the project, street name and building number only object: presentation file of the diagnostic report """ - - input_list = sheet_input[0] - input_values = sheet_input[1] + # Put all of the arguments into variables + client_name = project_summary_data['client_name'] + project_address = project_summary_data['project_address'] + annual_energy_percent = project_summary_data['annual_energy_percent'] + annual_dollar_save = project_summary_data['annual_dollar_save'] + co2_tonnage = project_summary_data['co2_tonnage'] + jobs_created = project_summary_data['jobs_created'] + blocmaps_est = project_summary_data['blocmaps_est'] + + util_break_sh = util_break_data['util_break_sh'] + util_break_dhw = util_break_data['util_break_dhw'] + util_break_light = util_break_data['util_break_light'] + util_break_plug = util_break_data['util_break_plug'] + util_break_h2o = util_break_data['util_break_h2o'] + + heat_loss_cat = heat_loss_data['heat_loss_cat'] + heat_loss_val = heat_loss_data['heat_loss_val'] + + ecm_list = ecm_data['ecm_list'] + ecm_delete_list = ecm_data['ecm_delete_list'] + ecm_heat_save = ecm_data['ecm_heat_save'] + ecm_elec_save = ecm_data['ecm_elec_save'] # Define presentation to edit as the finished template diag_rep = Presentation(template_file) @@ -55,8 +84,6 @@ class CbraDiagnostic: cover_title = cover_slide.shapes.title cover_subtitle = cover_slide.placeholders[1] - client_name = sheet_input.loc[1, 1] - project_address = sheet_input.loc[2, 1] cover_title.text = "{} - {}".format(client_name, project_address) cover_subtitle.text = "Energy Efficiency Diagnostic Report" @@ -91,11 +118,6 @@ class CbraDiagnostic: crnyc_intro_run.font.size = Pt(14) exec_results_box.text_frame.add_paragraph() - annual_energy_percent = int(sheet_input.loc[3, 1]) - annual_dollar_save = int(sheet_input.loc[4, 1]) - co2_tonnage = int(sheet_input.loc[5, 1]) - jobs_created = int(sheet_input.loc[6, 1]) - exec_energy_savings_line = exec_results_box.text_frame.add_paragraph() exec_energy_savings_run = exec_energy_savings_line.add_run() @@ -145,7 +167,6 @@ class CbraDiagnostic: energy_analyze_box = heat_load_slide.shapes[3] # BlocMaps Efficiency Comparison - blocmaps_est = sheet_input.loc[7, 1] eab_run = energy_analyze_box.text_frame.paragraphs[0].add_run() eab_run.text = 'Your building is ' blocmap_comp = energy_analyze_box.text_frame.paragraphs[0].add_run() @@ -164,10 +185,6 @@ class CbraDiagnostic: eab_run_end.font.size = Pt(14) eab_run_end.font.color.rgb = RGBColor(0xff, 0xff, 0xff) - # For using w/ input file - heat_loss_cat = input_list.loc[9:14] - heat_loss_val = input_values.loc[9:14] - total_heat_loss = sum(heat_loss_val) heat_loss_break = heat_loss_val.divide(total_heat_loss) @@ -209,11 +226,6 @@ class CbraDiagnostic: # Define stacked bar chart data util_cat = ["Existing", "Projected"] - util_break_sh = sheet_input.loc[16:17, 1] - util_break_dhw = sheet_input.loc[16:17, 2] - util_break_light = sheet_input.loc[16:17, 3] - util_break_plug = sheet_input.loc[16:17, 4] - util_break_h2o = sheet_input.loc[16:17, 5] util_break_data = ChartData() util_break_data.categories = util_cat @@ -268,8 +280,8 @@ class CbraDiagnostic: util_break_chart.value_axis.tick_label_position = XL_TICK_LABEL_POSITION.NONE # Create ECM summary table - # TODO: adjust widths on heat, elec, and water savings columns to 1in each - ecm_count = input_values.str.contains('Y').sum() + + ecm_count = len(ecm_list) ecm_table_head = ['Energy Conservation Measure', "Heating Savings*", "Electricity Savings*", @@ -295,16 +307,6 @@ class CbraDiagnostic: ecm_table.table.cell(0, j).text_frame.paragraphs[0].font.size = Pt(12) ecm_table.table.cell(0, j).text_frame.paragraphs[0].font.bold = True - ecm_list = [] - ecm_heat_save = [] - ecm_elec_save = [] - - for j in range(len(input_values)): - if input_values[j] == 'Y': - ecm_list.append(input_list[j]) - ecm_heat_save.append(input_values[j+1]) - ecm_elec_save.append(input_values[j+2]) - # TODO: format percentage to be integers for k, j in zip(ecm_list, range(len(ecm_list))): ecm_table.table.cell(j+1, 0).text_frame.paragraphs[0].font.size = Pt(10) ecm_table.table.cell(j+1, 0).text = k @@ -326,12 +328,14 @@ class CbraDiagnostic: ecm_table.table.cell(ecm_count+1, 2).text = str(annual_energy_percent) + '\N{PERCENT SIGN}' # Slides 5-end: removing slides based on recommendations - counter = 0 - for j in range(len(input_values)): - if input_values[j] == 'N': - slide_idx = int(((j-6)/3) - counter) - diag_rep.slides.delete_slide(diag_rep, slide_idx) - counter = counter + 1 + deleted_slide_counter = 0 + NUM_NON_ECM_SLIDES = 4 + for ecm_index in ecm_delete_list: + diag_rep.slides.delete_slide( + diag_rep, + ecm_index + NUM_NON_ECM_SLIDES - deleted_slide_counter, + ) + deleted_slide_counter += 1 return project_address, diag_rep @@ -344,9 +348,90 @@ class CbraDiagnostic: file_name = input('Enter File Name (with .xlsx extension): ') file_input = pd.ExcelFile(file_name) sheet_input = file_input.parse("Inputs", header=None) - project_address, diag_rep = CbraDiagnostic._generate_report(template_file, sheet_input) + ( + project_summary_data, + util_break_data, + heat_loss_data, + ecm_data + ) = CbraDiagnostic.parse_arguments(sheet_input) + project_address, diag_rep = CbraDiagnostic._generate_report( + template_file, + project_summary_data, + util_break_data, + heat_loss_data, + ecm_data, + ) diag_rep.save('EEDR {}.pptx'.format(project_address)) + @staticmethod + def parse_arguments(sheet_input): + """ + Parse an excel file to generate arguments for the _generate_report function + + Args: + sheet_input (dataframe): The sheet where the data is located + + Returns: + project_summary_data (dict): + A dictionary containing all of the project summary data + util_break_data (dict): + A dictionary containing all of the utility breakdown data + heat_loss_data (dict): + A dictionary containing all of the heat loss data + ecm_data (dict): + A dictionary containing all of the ECM data + """ + + project_summary_data = { + 'client_name': sheet_input.loc[1, 1], + 'project_address': sheet_input.loc[2, 1], + 'annual_energy_percent': int(sheet_input.loc[3, 1]), + 'annual_dollar_save': int(sheet_input.loc[4, 1]), + 'co2_tonnage': int(sheet_input.loc[5, 1]), + 'jobs_created': int(sheet_input.loc[6, 1]), + 'blocmaps_est': sheet_input.loc[7, 1], + } + + util_break_data = { + 'util_break_sh': sheet_input.loc[16:17, 1], + 'util_break_dhw': sheet_input.loc[16:17, 2], + 'util_break_light': sheet_input.loc[16:17, 3], + 'util_break_plug': sheet_input.loc[16:17, 4], + 'util_break_h2o': sheet_input.loc[16:17, 5], + } + + + input_list = sheet_input[0] + input_values = sheet_input[1] + + heat_loss_data = { + 'heat_loss_cat': input_list[9:15], + 'heat_loss_val': input_values[9:15], + } + + ecm_list = [] + ecm_delete_list = [] + ecm_heat_save = [] + ecm_elec_save = [] + for j in range(len(input_values)): + if input_values[j] == 'Y': + ecm_list.append(input_list[j]) + ecm_heat_save.append(input_values[j+1]) + ecm_elec_save.append(input_values[j+2]) + + if input_values[j] == 'N': + ecm_index = int((j-20)/3) + ecm_delete_list.append(ecm_index) + + ecm_data = { + 'ecm_list': ecm_list, + 'ecm_delete_list': ecm_delete_list, + 'ecm_heat_save': ecm_heat_save, + 'ecm_elec_save': ecm_elec_save, + } + + return project_summary_data, util_break_data, heat_loss_data, ecm_data + @staticmethod def cbra_multi_rep(): """ diff --git a/bpeng/tests/data/test_reports.xlsx b/bpeng/tests/data/test_reports.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e425486b87c7241958ae5f72c2e050d04a6b218f Binary files /dev/null and b/bpeng/tests/data/test_reports.xlsx differ diff --git a/bpeng/tests/test_reports.py b/bpeng/tests/test_reports.py new file mode 100644 index 0000000000000000000000000000000000000000..c2a2bbc30848f0216119a33cfc8c0f40b8763a7c --- /dev/null +++ b/bpeng/tests/test_reports.py @@ -0,0 +1,53 @@ +"""Test report generator""" +import os +import pandas as pd +from bpeng import CbraDiagnostic + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + +class TestReports: + + def test_arg_parse(self): + with open(os.path.join(BASE_DIR, 'data/test_reports.xlsx'), 'r+b') as f: + file_input = pd.ExcelFile(f) + sheet_input = file_input.parse("Inputs", header=None) + ( + project_summary_data, + util_break_data, + heat_loss_data, + ecm_data + ) = CbraDiagnostic.parse_arguments(sheet_input) + + # Test return values for project_summary_data + assert project_summary_data['co2_tonnage'] == 8 + assert project_summary_data['annual_dollar_save'] == 3905 + + assert util_break_data['util_break_sh'][16] == 3500 + assert util_break_data['util_break_dhw'][17] == 975 + + assert heat_loss_data['heat_loss_cat'][10] == 'Wall' + assert heat_loss_data['heat_loss_val'][12] == 18.44 + + assert len(ecm_data['ecm_list']) == 16 + assert ecm_data['ecm_list'][1] == 'Replace Windows' + +# def test_report_generator(self): +# with open(os.path.join(BASE_DIR, 'data/test_reports.xlsx'), 'r+b') as f: +# file_input = pd.ExcelFile(f) +# sheet_input = file_input.parse("Inputs", header=None) +# ( +# project_summary_data, +# util_break_data, +# heat_loss_data, +# ecm_data +# ) = CbraDiagnostic.parse_arguments(sheet_input) +# +# +# project_address, diag_rep = CbraDiagnostic._generate_report( +# 'bpeng/tests/data/cbra_template.pptx', +# project_summary_data, +# util_break_data, +# heat_loss_data, +# ecm_data, +# ) +# diag_rep.save('EEDR_test.pptx')