Spaces:
Runtime error
Runtime error
| import numpy as np | |
| import pandas as pd | |
| from matplotlib import pyplot as plt | |
| from forecast import get_forecast_data | |
| from retrieve_coefs_max_yield import get_coefs_Kc_Ky_and_max_yield | |
| from utils.soil_utils import get_soil_properties | |
| def calculate_ETx(Kc, ETo): | |
| """ | |
| Calculate the maximum evapotranspiration (ETx) using the crop coefficient (Kc) and reference evapotranspiration (ETo). | |
| Parameters: | |
| Kc (float): Crop coefficient | |
| ETo (float): Reference evapotranspiration (mm) | |
| Returns: | |
| float: Maximum evapotranspiration (ETx) in mm | |
| """ | |
| ETx = Kc * ETo | |
| return ETx | |
| def calculate_ETa(ETx, soil_moisture, field_capacity, wilting_point, water_deficit, ETo): | |
| """ | |
| Calculate the actual evapotranspiration (ETa) using the maximum evapotranspiration (ETx), soil moisture, field capacity, and wilting point. | |
| Parameters: | |
| ETx (float): Maximum evapotranspiration (mm) | |
| soil_moisture (Series): Current soil moisture content (%) | |
| field_capacity (float): Field capacity of the soil (%) | |
| wilting_point (float): Wilting point of the soil (%) | |
| Returns: | |
| float: Actual evapotranspiration (ETa) in mm | |
| """ | |
| Ks = 1 - (water_deficit / ETo) # coef de stress hydrique = precipitation / et0 | |
| Ks = Ks.clip(lower=0, upper=1) | |
| ETa = ETx * Ks | |
| ETa.loc[soil_moisture > field_capacity] = ETx.loc[soil_moisture > field_capacity] | |
| ETa.loc[soil_moisture < wilting_point] = 0 | |
| return ETa | |
| def calculate_yield_projection(Yx, ETx, ETa, Ky): | |
| """ | |
| Calculate the agricultural yield projection using the FAO water production function. | |
| Parameters: | |
| Yx (float): Maximum yield (quintal/ha) | |
| ETx (float): Maximum evapotranspiration (mm) | |
| ETa (float): Actual evapotranspiration (mm) | |
| Ky (float): Yield response factor | |
| Returns: | |
| float: Projected yield (quintal/ha) | |
| """ | |
| Ya = Yx * (1 - Ky * (1 - ETa / ETx)) | |
| Ya.loc[ETx == 0] = 0 | |
| return round(Ya, 2) | |
| def add_cultural_coefs(monthly_forecast: pd.DataFrame, cultural_coefs: pd.DataFrame) -> pd.DataFrame: | |
| monthly_forecast["Kc"] = 0 | |
| monthly_forecast["Ky"] = 0 | |
| for month in range(1, 13): | |
| Kc = cultural_coefs["Kc"][cultural_coefs.Mois == month].iloc[0] | |
| Ky = cultural_coefs["Ky"][cultural_coefs.Mois == month].iloc[0] | |
| monthly_forecast.loc[(monthly_forecast.month==month).to_numpy(), "Kc"] = Kc | |
| monthly_forecast.loc[(monthly_forecast.month==month).to_numpy(), "Ky"] = Ky | |
| return monthly_forecast | |
| def compute_yield_forecast( | |
| latitude: float, | |
| longitude: float, | |
| culture: str = "Colza d'hiver", | |
| region: str = "Bourgogne-Franche-Comté", | |
| scenario: str = "pessimist", | |
| shading_coef: float = 0., | |
| ): | |
| monthly_forecast = get_forecast_data(latitude, longitude, scenario=scenario, shading_coef=shading_coef) | |
| cultural_coefs, max_yield = get_coefs_Kc_Ky_and_max_yield(culture, region) | |
| monthly_forecast = add_cultural_coefs(monthly_forecast, cultural_coefs) | |
| Kc = monthly_forecast["Kc"] | |
| Ky = monthly_forecast["Ky"] | |
| soil_properties = get_soil_properties(latitude, longitude) | |
| ETo = monthly_forecast["Evaporation (mm/day)"] | |
| ETx = calculate_ETx(Kc, ETo) | |
| ETa = calculate_ETa( | |
| ETx, | |
| monthly_forecast["Moisture in Upper Portion of Soil Column (kg m-2)"], | |
| soil_properties["field_capacity"], | |
| soil_properties["wilting_point"], | |
| water_deficit=monthly_forecast["Water Deficit (mm/day)"], | |
| ETo=ETo, | |
| ) | |
| projected_yield = calculate_yield_projection( | |
| Yx=max_yield, | |
| ETx=ETx, | |
| ETa=ETa, | |
| Ky=Ky) | |
| monthly_forecast["Estimated yield (quintal/ha)"] = projected_yield | |
| return monthly_forecast | |
| def get_annual_yield(monthly_forecast: pd.DataFrame) -> pd.Series: | |
| yield_forecast = pd.Series( | |
| index=monthly_forecast["time"], | |
| data=monthly_forecast["Estimated yield (quintal/ha)"].to_numpy(), | |
| ) | |
| yield_forecast = yield_forecast.resample("1YE").mean() | |
| return yield_forecast | |
| def plot_yield( | |
| latitude: float, | |
| longitude: float, | |
| culture: str = "Colza d'hiver", | |
| region: str = "Bourgogne-Franche-Comté", | |
| scenario: str = "pessimist", | |
| shading_coef: float = 0.2, | |
| ) -> plt.Figure: | |
| monthly_forecast = compute_yield_forecast( | |
| latitude=latitude, | |
| longitude=longitude, | |
| culture=culture, | |
| scenario=scenario, | |
| shading_coef=0., | |
| ) | |
| yield_forecast = get_annual_yield(monthly_forecast) | |
| n_years = 10 | |
| years = 2025 + np.arange(len(yield_forecast)) | |
| aggregated_years = years[years % n_years == 0] | |
| aggregated_forecasts = yield_forecast.rolling(n_years).sum()[years % n_years == 0] | |
| width = 3 # the width of the bars | |
| fig, ax = plt.subplots(layout='constrained') | |
| _ = ax.bar(aggregated_years, aggregated_forecasts, width, label="No shading") | |
| if shading_coef > 0: | |
| monthly_forecast_with_shading = compute_yield_forecast( | |
| latitude=latitude, | |
| longitude=longitude, | |
| culture=culture, | |
| scenario=scenario, | |
| shading_coef=shading_coef, | |
| ) | |
| yield_forecast_with_shading = get_annual_yield(monthly_forecast_with_shading) | |
| aggregated_forecasts_with_shading = yield_forecast_with_shading.rolling(n_years).sum()[years % n_years == 0] | |
| _ = ax.bar(aggregated_years + width, aggregated_forecasts_with_shading, width, label="20% shading") | |
| ax.legend() | |
| ax.set_xlabel("Année") | |
| ax.set_ylabel(f"Production agricole de {culture} estimée (quintal / ha)") | |
| ax.set_ylim(150) | |
| return fig | |
| if __name__ == '__main__': | |
| latitude = 47 | |
| longitude = 5 | |
| cultures = ["Colza d'hiver", "Blé tendre d'hiver", "Orge d'hiver"] | |
| dfs = [] | |
| for culture in cultures: | |
| scenario = "pessimist" | |
| shading_coef = 0.2 | |
| monthly_forecast = compute_yield_forecast( | |
| latitude=47, | |
| longitude=5, | |
| culture=culture, | |
| scenario=scenario, | |
| shading_coef=0., | |
| ) | |
| monthly_forecast_with_shading = compute_yield_forecast( | |
| latitude=47, | |
| longitude=5, | |
| culture=culture, | |
| scenario=scenario, | |
| shading_coef=shading_coef, | |
| ) | |
| fig = plot_yield(latitude, longitude, culture, scenario="pessimist", shading_coef=shading_coef) | |
| plt.show() | |
| # yield_forecast = get_annual_yield(monthly_forecast) | |
| # yield_forecast_df = yield_forecast.reset_index() | |
| # yield_forecast_df.columns = ["time", "yield_simple_forecast"] | |
| # yield_forecast_df["year"] = yield_forecast_df["time"].dt.year | |
| # yield_forecast_with_shading = get_annual_yield(monthly_forecast_with_shading) | |
| # yield_forecast_with_shading_df = yield_forecast_with_shading.reset_index() | |
| # yield_forecast_with_shading_df.columns = ["time", "yield_with_shading_forecast"] | |
| # yield_forecast_with_shading_df["year"] = yield_forecast_with_shading_df["time"].dt.year | |
| # final_df = pd.merge(yield_forecast_df[["year", "yield_simple_forecast"]], yield_forecast_with_shading_df[["year", "yield_with_shading_forecast"]], on="year") | |
| # final_df["culture"] = culture | |
| # dfs.append(final_df) | |
| # result = pd.concat(dfs, axis=0) | |
| # result.to_csv("data/data_yield/rendement_forecast.csv", index=False) | |