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) | |