diff --git a/bpeng/reports/cbra_diag.py b/bpeng/reports/cbra_diag.py index 6d4c3412abbedbd652925e4e9d1610d8ea4a793c..844970a951a8e84c38e34c72478f5fd87b4d75e4 100644 --- a/bpeng/reports/cbra_diag.py +++ b/bpeng/reports/cbra_diag.py @@ -15,7 +15,11 @@ from pptx.enum.chart import ( XL_LEGEND_POSITION, XL_TICK_LABEL_POSITION ) -from pptx.enum.text import MSO_AUTO_SIZE, PP_ALIGN +from pptx.enum.text import ( + MSO_AUTO_SIZE, + MSO_ANCHOR, + PP_ALIGN +) from pptx.util import Inches, Pt @@ -30,12 +34,12 @@ class CbraDiagnostic: Generate powerpoint file Args: - - input_file (str): The path of the report content + template_file (str): pptx template stored on S3 and Drive + sheet_input (pandas dataframe): engineering calculation output dataframe Returns: - - Presentation: the presenation generated + str: the address of the project, street name and building number only + object: presentation file of the diagnostic report """ @@ -95,8 +99,8 @@ class CbraDiagnostic: exec_energy_savings_line = exec_results_box.text_frame.add_paragraph() exec_energy_savings_run = exec_energy_savings_line.add_run() - exec_energy_savings_run.text = '{}\N{PERCENT SIGN} decrease in energy ' \ - 'consumption'.format(annual_energy_percent) + exec_energy_savings_run.text = '{}\N{PERCENT SIGN} decrease in utility ' \ + 'costs'.format(annual_energy_percent) exec_results_box.text_frame.paragraphs[4].alignment = PP_ALIGN.LEFT exec_energy_savings_run.font.name = 'Arial' @@ -106,8 +110,10 @@ class CbraDiagnostic: exec_dollar_savings_line = exec_results_box.text_frame.add_paragraph() exec_dollar_savings_run = exec_dollar_savings_line.add_run() - exec_dollar_savings_run.text = 'Estimated annual savings of ' \ - '\N{DOLLAR SIGN}{}'.format(annual_dollar_save) + + exec_dollar_savings_run.text = '\N{DOLLAR SIGN}{} estimated annual' \ + 'savings'.format(annual_dollar_save) + exec_results_box.text_frame.paragraphs[6].alignment = PP_ALIGN.LEFT exec_dollar_savings_run.font.name = 'Arial' exec_dollar_savings_run.font.size = Pt(14) @@ -141,18 +147,35 @@ class CbraDiagnostic: # 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 {}\N{PERCENT SIGN} less efficient than buildings of ' \ - 'similar age, size, and type.'.format(blocmaps_est) + eab_run.text = 'Your building is ' + blocmap_comp = energy_analyze_box.text_frame.paragraphs[0].add_run() + blocmap_comp.text = '{}\N{PERCENT SIGN} '.format(blocmaps_est) + eab_run_end = energy_analyze_box.text_frame.paragraphs[0].add_run() + eab_run_end.text = 'less efficient than buildings of similar age,' \ + ' size, and type.' eab_run.font.name = 'Arial' eab_run.font.size = Pt(14) eab_run.font.color.rgb = RGBColor(0xff, 0xff, 0xff) + blocmap_comp.font.name = 'Arial' + blocmap_comp.font.bold = True + blocmap_comp.font.size = Pt(14) + blocmap_comp.font.color.rgb = RGBColor(0xff, 0xff, 0xff) + eab_run_end.font.name = 'Arial' + 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[9:15] - heat_loss_val = input_values[9:15] + 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 = [hl_frac/total_heat_loss for hl_frac in heat_loss_val] + heat_loss_break = heat_loss_val.divide(total_heat_loss) + + heat_loss_data = pd.concat([heat_loss_cat, heat_loss_break], axis=1) + heat_loss_data = heat_loss_data[heat_loss_data[1] > 0.01] + + heat_loss_cat = heat_loss_data[0] + heat_loss_break = heat_loss_data[1] heat_load_pie_data = ChartData() heat_load_pie_data.categories = heat_loss_cat @@ -161,9 +184,13 @@ class CbraDiagnostic: # Set chart location and formatting chart_horz_pos, chart_vert_pos = Inches(4.2), Inches(1.3) chart_width, chart_height = Inches(5.27), Inches(3.47) - heat_load_pie = heat_load_slide.shapes.add_chart(XL_CHART_TYPE.PIE, chart_horz_pos, - chart_vert_pos, chart_width, chart_height, - heat_load_pie_data).chart + heat_load_pie = heat_load_slide.shapes.add_chart(XL_CHART_TYPE.PIE, + chart_horz_pos, + chart_vert_pos, + chart_width, + chart_height, + heat_load_pie_data + ).chart heat_load_pie.has_legend = True heat_load_pie.legend.include_in_layout = False @@ -172,11 +199,12 @@ class CbraDiagnostic: heat_loss_labels = heat_load_pie.plots[0].data_labels heat_loss_labels.number_format = '0%' heat_loss_labels.font.size = Pt(22) + heat_loss_labels.font.bold = True # Slide 4: Potential Savings, includes utility expenses stacked bar charts for # pre+post-retrofit, ECM table w/ names, savings for elec and gas, and total savings - # Slide 4: Utility breakdown (chart is in bottom right corner) + # Slide 4: Utility breakdown utility_projection_slide = diag_rep.slides[3] # Define stacked bar chart data @@ -189,11 +217,17 @@ class CbraDiagnostic: util_break_data = ChartData() util_break_data.categories = util_cat - util_break_data.add_series("Space Heating", util_break_sh) - util_break_data.add_series("DHW", util_break_dhw) - util_break_data.add_series("Lighting", util_break_light) - util_break_data.add_series("Plug Load", util_break_plug) - util_break_data.add_series("Water", util_break_h2o) + + if util_break_sh.iloc[0] != 0: + util_break_data.add_series("Space Heating", util_break_sh) + if util_break_dhw.iloc[0] != 0: + util_break_data.add_series("DHW", util_break_dhw) + if util_break_light.iloc[0] != 0: + util_break_data.add_series("Lighting", util_break_light) + if util_break_plug.iloc[0] != 0: + util_break_data.add_series("Plug Load", util_break_plug) + if util_break_h2o.iloc[0] != 0: + util_break_data.add_series("Water", util_break_h2o) # Set chart location and formatting chart_horz_pos, chart_vert_pos = Inches(0.05), Inches(2.4) @@ -212,41 +246,54 @@ class CbraDiagnostic: util_break_chart.has_legend = True util_break_chart.legend.include_in_layout = False util_break_chart.legend.position = XL_LEGEND_POSITION.LEFT - util_break_chart.legend.font.size = Pt(11) + util_break_chart.legend.font.size = Pt(10) + util_break_chart.legend.font.bold = True util_break_chart.legend.font.color.rgb = RGBColor(0xff, 0xff, 0xff) # Data Labels util_break_chart.plots[0].has_data_labels = True util_labels = util_break_chart.plots[0].data_labels util_labels.number_format = '$0' - util_labels.font.size = Pt(8) + util_labels.font.size = Pt(10) + util_labels.font.bold = True util_labels.font.color.rgb = RGBColor(0xff, 0xff, 0xff) # Axis util_break_chart.has_axis = True util_break_chart.has_axis_title = True - util_break_chart.category_axis.tick_labels.font.size = Pt(11) + util_break_chart.category_axis.tick_labels.font.size = Pt(10) + util_break_chart.category_axis.tick_labels.font.bold = True util_break_chart.category_axis.tick_labels.font.color.rgb = RGBColor(0xff, 0xff, 0xff) util_break_chart.value_axis.has_major_gridlines = False 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_table_head = ['Energy Conservation Measure', + "Heating Savings*", + "Electricity Savings*", + "Water Savings*" + ] ecm_table = utility_projection_slide.shapes.add_table( ecm_count + 2, - 3, - Inches(3.81), - Inches(0.25), - Inches(5.83), - Inches(3.76) + len(ecm_table_head), + Inches(3.62), + Inches(0.08), + Inches(6.12), + Inches(4.9) ) ecm_table.last_row = True ecm_table.horz_banding = False - ecm_table_head = ['ECM', "Heating Savings *", "Electricity Savings *"] + ecm_table.table.columns[0].width = Inches(3.12) + ecm_table.table.columns[1].width = Inches(1) + ecm_table.table.columns[2].width = Inches(1) + ecm_table.table.columns[3].width = Inches(1) for j in range(len(ecm_table_head)): - ecm_table.table.cell(0, j).text_frame.paragraphs[0].font.size = Pt(12) ecm_table.table.cell(0, j).text = ecm_table_head[j] + 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 = [] @@ -257,14 +304,26 @@ class CbraDiagnostic: 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 ecm_table.table.cell(j+1, 1).text_frame.paragraphs[0].font.size = Pt(10) - ecm_table.table.cell(j+1, 1).text = str(ecm_heat_save[j]) + ecm_table.table.cell(j+1, 1).text = str(int(ecm_heat_save[j])) + '\N{PERCENT SIGN}' + ecm_table.table.cell(j+1, 1).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER + ecm_table.table.cell(j+1, 1).text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE ecm_table.table.cell(j+1, 2).text_frame.paragraphs[0].font.size = Pt(10) - ecm_table.table.cell(j+1, 2).text = str(ecm_elec_save[j]) + ecm_table.table.cell(j+1, 2).text = str(int(ecm_elec_save[j])) + '\N{PERCENT SIGN}' + ecm_table.table.cell(j+1, 2).text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER + ecm_table.table.cell(j+1, 2).text_frame.vertical_anchor = MSO_ANCHOR.MIDDLE + + ecm_table.table.cell(ecm_count+1, 0).text_frame.paragraphs[0].font.size = Pt(12) + ecm_table.table.cell(ecm_count+1, 0).text_frame.paragraphs[0].font.bold = True + ecm_table.table.cell(ecm_count+1, 0).text = 'Total' + + ecm_table.table.cell(ecm_count+1, 2).text_frame.paragraphs[0].font.size = Pt(12) + ecm_table.table.cell(ecm_count+1, 2).text_frame.paragraphs[0].font.bold = True + 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