import io import os import pandas as pd import streamlit as st from openpyxl import Workbook from openpyxl.utils.dataframe import dataframe_to_rows from streamlit_extras.stylable_container import stylable_container from WattFieldsCommon.constants import PATH_APP_FOLDER, PATH_IMG_FOLDER from WattFieldsCommon.optim_analytics import ( generate_df_block_temporal_analysis, generate_df_spatial_analysis, generate_df_temporal_analysis, generate_run_df_summary, generate_df_gstd_block ) def setup_st_config_with_navbar(page_title, add_navbar=True): PATH_LOGO = os.path.join(PATH_IMG_FOLDER, "logo.png") st.logo(PATH_LOGO, icon_image=PATH_LOGO, size="large") st.set_page_config(layout="wide", page_title=page_title) st.markdown( """ """, unsafe_allow_html=True, ) if add_navbar: with stylable_container( "green", css_styles=""" button { width: 100%; box-shadow: transparent 0 0 0 5px,rgba(18, 18, 18, .1) 0 6px 20px; color: #121212; line-height: 0.2; align-items: center; padding: 1rem 1.4rem; text-align: center; transition: box-shadow .2s,-webkit-box-shadow .2s; }""", ): col1, col2, col3 = st.columns(3) if col2.button("Revenir à la carte des sites"): st.switch_page(os.path.join(PATH_APP_FOLDER, "pages", "carte_sites.py")) def get_first_end_index_anti_tracking(df_weekly_blocks): df_weekly_blocks_at = df_weekly_blocks[ df_weekly_blocks["weekly_strategy_choice"] == "anti-tracking" ] return list(df_weekly_blocks_at["block_first_time_index"]), list( df_weekly_blocks_at["block_last_time_index"] ) @st.cache_data def generate_dfs_and_excel_file(run, simu_config, ref_agri_run, ref_pv_run): # Generate all metrics / data associated to a specific run, cache them to gain some time ref_agri_yield = ref_agri_run["general_metrics"]["average_agri_yield"] ref_pv_energy = ref_pv_run["general_metrics"]["average_pv_energy"] PV_PNOM = simu_config["SolarFarmBifacial"]["panel_peak_power"] df_summary = generate_run_df_summary( dict_run=run, ref_agri_yield=ref_agri_yield, ref_pv_energy=ref_pv_energy, surface_panel=simu_config["SolarFarmBifacial"]["panel_surface"], pv_module_pnom=PV_PNOM, planting_date=simu_config["WeatherData"]["planting_date"], ) df_temporal_analysis = generate_df_temporal_analysis( dict_run=run, dict_ref_agri_run=ref_agri_run ) df_spatial_analysis = generate_df_spatial_analysis(dict_run=run, dict_ref_agri_run=ref_agri_run) df_block_temporal_analysis = generate_df_block_temporal_analysis( dict_run=run, ref_pv_run=ref_pv_run, pv_module_pnom=PV_PNOM ) df_block_temporal_analysis["weekly_collected_ac_energy_per_peak_power"] = ( df_block_temporal_analysis["weekly_collected_ac_energy"] / PV_PNOM ) df_block_temporal_analysis_for_excel = df_block_temporal_analysis.copy() df_block_temporal_analysis_for_excel["block_first_time_index"] = ( df_block_temporal_analysis_for_excel["block_first_time_index"].dt.tz_localize(None) ) df_block_temporal_analysis_for_excel["block_middle_time_index"] = ( df_block_temporal_analysis_for_excel["block_middle_time_index"].dt.tz_localize(None) ) df_block_temporal_analysis_for_excel["block_last_time_index"] = ( df_block_temporal_analysis_for_excel["block_last_time_index"].dt.tz_localize(None) ) df_summary_for_excel = df_summary.copy() df_summary_for_excel.loc["ref_agri_average_yield"] = ref_agri_run["general_metrics"][ "average_agri_yield" ] df_summary_for_excel.loc["ref_pv_average_energy_per_peak"] = round( ref_pv_run["general_metrics"]["average_pv_energy"] / (simu_config["SolarFarmBifacial"]["panel_peak_power"] / 1000), 2, ) df_summary_for_excel.loc["PV"] = "- - - - - - - - - - - - - - - - - - - -" df_summary_for_excel.loc["AGRI"] = "- - - - - - - - - - - - - - - - - - - -" df_summary_for_excel.loc["AUTRES"] = "- - - - - - - - - - - - - - - - - - - -" df_summary_for_excel = df_summary_for_excel.loc[ [ff for ff in df_summary_for_excel.index if ff not in ["collected_ac_energy"]] ] df_summary_for_excel = df_summary_for_excel.reset_index() df_gstd_blocks = generate_df_gstd_block(run, df_temporal_analysis = df_temporal_analysis, dict_ref_agri_run = ref_agri_run) description = { "PV": " - - - - - - - - - - - - - - - - - - - - - -", "normalized_collected_ac_energy": "Rendement agricole du run / Rendement agricole du run de reference (en %)", "collected_ac_energy_per_meter2": "Energie totale recoltee pour un metre carre de surface pv (en KWh / m2)", "collected_ac_energy_per_peak_power": "Energie totale recoltee divisee par la puissance crete du panneau (en kWh/kW-Crete)", "ref_pv_average_energy_per_peak": "REFERENCE PV : Energie AC recoltee pour un panneau avec une strategie full-backtracking (en kWh/kW-Crete)", "AGRI": " - - - - - - - - - - - - - - - - - - - - - -", "agri_average_yield": "Rendement moyen agricole (en Tonnes/Hectare)", "normalized_agri_average_yield": "Rendement agricole du run / Rendement agricole du run de reference (en %)", "ref_agri_average_yield": "REFERENCE AGRI : Rendement agricole de la simulation de reference (sans panneaux PV) (en Tonnes/Hectare)", "AUTRES": " - - - - - - - - - - - - - - - - - - - - - -", "run_duration": "Duree totale du run (= duree DSSAT la plus longue sur toutes les rangees) (en jours)", "nb_block_anti-tracking": "Nombre de semaines avec une strategie d'anti-tracking pour le panneau (en nombre de semaines)", } df_description = pd.Series(description).to_frame().reset_index() df_merged = df_description.merge(df_summary_for_excel, how="outer", on="index") right_order = list(description.keys()) df_merged = df_merged.rename( columns={"index": "Nom de la variable", "0_x": "Description", "0_y": "Valeur"} ) df_merged = df_merged.set_index("Nom de la variable").loc[right_order].reset_index() df_hourly_tracker_angle = run['df_hourly_orientation_planning'] df_hourly_tracker_angle.fillna(0, inplace=True) df_hourly_tracker_angle_for_excel = df_hourly_tracker_angle.copy() df_hourly_tracker_angle_for_excel['REF_BACKTRACKING_tracker_theta'] = ref_pv_run['df_hourly_orientation_planning']['tracker_theta'] df_hourly_tracker_angle_for_excel.index = df_hourly_tracker_angle_for_excel.index.strftime('%Y-%m-%dT%H:%M:%S') wb = Workbook() sheet1 = wb.active sheet1.title = "RECAP" for r in dataframe_to_rows(df_merged, index=True, header=True): sheet1.append(r) sheet2 = wb.create_sheet("ANALYSE_SPATIALE") for r in dataframe_to_rows(df_spatial_analysis, index=True, header=True): sheet2.append(r) sheet3 = wb.create_sheet("ANALYSE_TEMPORELLE") for r in dataframe_to_rows(df_temporal_analysis, index=True, header=True): sheet3.append(r) sheet4 = wb.create_sheet("PRODUCTION_ELECTRIQUE") for r in dataframe_to_rows(df_block_temporal_analysis_for_excel, index=False, header=True): sheet4.append(r) sheet5 = wb.create_sheet("ANGLE DU TRACKER") for r in dataframe_to_rows(df_hourly_tracker_angle_for_excel, index=True, header=True): sheet5.append(r) sheet6 = wb.create_sheet("GSTD BLOCKS") for r in dataframe_to_rows(df_gstd_blocks, index=True, header=True): sheet6.append(r) excel_file = io.BytesIO() wb.save(excel_file) excel_file.seek(0) return ( excel_file, df_summary, df_temporal_analysis, df_spatial_analysis, df_block_temporal_analysis, df_hourly_tracker_angle )