fire2a.meteo
👋🌎 Some functions related to kitral weather scenario creation.
1#!python3 2"""👋🌎 3Some functions related to kitral weather scenario creation. 4""" 5__author__ = "Caro" 6__revision__ = "$Format:%H$" 7 8from datetime import datetime, timedelta 9from pathlib import Path 10 11import numpy as np 12import pandas as pd 13 14# debug aqui = Path() 15aqui = Path(__file__).parent 16# Ruta a los datos de estaciones 17ruta_data = aqui / "DB_DMC" 18 19 20def file_name(i, numsims): 21 if numsims > 1: 22 return f"Weather{i+1}.csv" 23 return "Weather.csv" 24 25 26def scenario_name(i, numsims): 27 if numsims > 1: 28 return f"DMC_{i+1}" 29 return "DMC" 30 31 32def distancia(fila, y_i, x_i): 33 if y_i == fila["lat"] and x_i == fila["lon"]: 34 return 0 35 return np.sqrt((fila["lat"] - x_i) ** 2 + (fila["lon"] - y_i) ** 2) 36 37 38def meteo_to_c2f(alfa): 39 if alfa >= 0 and alfa < 180: 40 return round(alfa + 180, 2) 41 elif alfa >= 180 and alfa <= 360: 42 return round(alfa - 180, 2) 43 return np.nan 44 45 46def barlo_sota(a): 47 return round((a + 180) % 360, 2) 48 49 50def generate(x, y, start_datetime, rowres, numrows, numsims, outdir): 51 """dummy generator function 52 Args: 53 x (float): x-coordinate of the ignition point, EPSG 4326 54 y (float): y-coordinate of the ignition point, EPSG 4326 55 start_datetime (datetime): starting time of the weather scenario 56 rowres (int): time resolution in minutes (not implemented yet) 57 numrows (int): number of hours in the weather scenario 58 numsims (int): number of weather scenarios 59 outdir (Path): output directory 60 Return: 61 retval (int): 0 if successful, 1 otherwise, 2... 62 outdict (dict): output dictionary at least 'filelist': list of filenames created 63 """ 64 filelist = [] 65 try: 66 67 if not outdir.is_dir(): 68 outdir.mkdir() 69 70 dn = 3 71 list_stn = pd.read_csv(ruta_data / "Estaciones.csv") 72 list_stn["Distancia"] = list_stn.apply(distancia, args=(y, x), axis=1) # calculo distancia 73 stn = list_stn.sort_values(by=["Distancia"]).head(dn)["nombre"].tolist() 74 75 meteos = pd.DataFrame() 76 for st in stn: 77 df = pd.read_csv(ruta_data / f"{st}.csv", sep=",") 78 df["station"] = st 79 meteos = pd.concat([meteos, df], ignore_index=True) 80 meteos["datetime"] = pd.to_datetime(meteos["datetime"], errors="coerce") 81 # available days by stations 82 days = meteos.groupby(meteos.datetime.dt.date).first()["station"] 83 84 for i in range(numsims): 85 # draw station and day 86 cd = 0 87 ch = 0 88 while True: 89 station = np.random.choice(stn) 90 chosen_days = days[days == station] 91 if chosen_days.empty: 92 if cd > 10: 93 # print("Not enough data days", cd, ch) 94 return 1, {"filelist": [], "exception": "No data in closest stations"} 95 cd += 1 96 continue 97 day = np.random.choice(chosen_days.index) 98 start = datetime.combine(day - timedelta(days=ch), start_datetime.time()) 99 chosen_meteo = meteos[(meteos["datetime"] >= start) & (meteos["station"] == station)] 100 if len(chosen_meteo) < numrows: 101 if ch > len(meteos): 102 # print("Not enough data hours", cd, ch) 103 return 1, {"filelist": [], "exception": "Not enough data"} 104 ch += 1 105 continue 106 break 107 # take rows 108 chosen_meteo = chosen_meteo.head(numrows) 109 # drop station 110 chosen_meteo = chosen_meteo.drop(columns=["station"]) 111 # wind direction 112 chosen_meteo.loc[:, "WD"] = chosen_meteo["WD"].apply(barlo_sota) 113 # scenario name 114 chosen_meteo.loc[:, "Scenario"] = scenario_name(i, numsims) 115 # datetime format 116 chosen_meteo.loc[:, "datetime"] = chosen_meteo["datetime"].dt.strftime("%Y-%m-%dT%H:%M:%S") 117 # reorder 118 chosen_meteo = chosen_meteo[["Scenario", "datetime", "WS", "WD", "TMP", "RH"]] 119 # write 120 # print("head", chosen_meteo.head()) 121 tmpfile = outdir / file_name(i, numsims) 122 filelist += [tmpfile.name] 123 chosen_meteo.to_csv(tmpfile, header=True, index=False) 124 return 0, {"filelist": filelist} 125 126 except Exception as e: 127 return 1, {"filelist": filelist, "exception": e}
aqui =
PosixPath('/__w/fire2a-lib/fire2a-lib/src/fire2a')
ruta_data =
PosixPath('/__w/fire2a-lib/fire2a-lib/src/fire2a/DB_DMC')
def
file_name(i, numsims):
def
scenario_name(i, numsims):
def
distancia(fila, y_i, x_i):
def
meteo_to_c2f(alfa):
def
barlo_sota(a):
def
generate(x, y, start_datetime, rowres, numrows, numsims, outdir):
51def generate(x, y, start_datetime, rowres, numrows, numsims, outdir): 52 """dummy generator function 53 Args: 54 x (float): x-coordinate of the ignition point, EPSG 4326 55 y (float): y-coordinate of the ignition point, EPSG 4326 56 start_datetime (datetime): starting time of the weather scenario 57 rowres (int): time resolution in minutes (not implemented yet) 58 numrows (int): number of hours in the weather scenario 59 numsims (int): number of weather scenarios 60 outdir (Path): output directory 61 Return: 62 retval (int): 0 if successful, 1 otherwise, 2... 63 outdict (dict): output dictionary at least 'filelist': list of filenames created 64 """ 65 filelist = [] 66 try: 67 68 if not outdir.is_dir(): 69 outdir.mkdir() 70 71 dn = 3 72 list_stn = pd.read_csv(ruta_data / "Estaciones.csv") 73 list_stn["Distancia"] = list_stn.apply(distancia, args=(y, x), axis=1) # calculo distancia 74 stn = list_stn.sort_values(by=["Distancia"]).head(dn)["nombre"].tolist() 75 76 meteos = pd.DataFrame() 77 for st in stn: 78 df = pd.read_csv(ruta_data / f"{st}.csv", sep=",") 79 df["station"] = st 80 meteos = pd.concat([meteos, df], ignore_index=True) 81 meteos["datetime"] = pd.to_datetime(meteos["datetime"], errors="coerce") 82 # available days by stations 83 days = meteos.groupby(meteos.datetime.dt.date).first()["station"] 84 85 for i in range(numsims): 86 # draw station and day 87 cd = 0 88 ch = 0 89 while True: 90 station = np.random.choice(stn) 91 chosen_days = days[days == station] 92 if chosen_days.empty: 93 if cd > 10: 94 # print("Not enough data days", cd, ch) 95 return 1, {"filelist": [], "exception": "No data in closest stations"} 96 cd += 1 97 continue 98 day = np.random.choice(chosen_days.index) 99 start = datetime.combine(day - timedelta(days=ch), start_datetime.time()) 100 chosen_meteo = meteos[(meteos["datetime"] >= start) & (meteos["station"] == station)] 101 if len(chosen_meteo) < numrows: 102 if ch > len(meteos): 103 # print("Not enough data hours", cd, ch) 104 return 1, {"filelist": [], "exception": "Not enough data"} 105 ch += 1 106 continue 107 break 108 # take rows 109 chosen_meteo = chosen_meteo.head(numrows) 110 # drop station 111 chosen_meteo = chosen_meteo.drop(columns=["station"]) 112 # wind direction 113 chosen_meteo.loc[:, "WD"] = chosen_meteo["WD"].apply(barlo_sota) 114 # scenario name 115 chosen_meteo.loc[:, "Scenario"] = scenario_name(i, numsims) 116 # datetime format 117 chosen_meteo.loc[:, "datetime"] = chosen_meteo["datetime"].dt.strftime("%Y-%m-%dT%H:%M:%S") 118 # reorder 119 chosen_meteo = chosen_meteo[["Scenario", "datetime", "WS", "WD", "TMP", "RH"]] 120 # write 121 # print("head", chosen_meteo.head()) 122 tmpfile = outdir / file_name(i, numsims) 123 filelist += [tmpfile.name] 124 chosen_meteo.to_csv(tmpfile, header=True, index=False) 125 return 0, {"filelist": filelist} 126 127 except Exception as e: 128 return 1, {"filelist": filelist, "exception": e}
dummy generator function Args: x (float): x-coordinate of the ignition point, EPSG 4326 y (float): y-coordinate of the ignition point, EPSG 4326 start_datetime (datetime): starting time of the weather scenario rowres (int): time resolution in minutes (not implemented yet) numrows (int): number of hours in the weather scenario numsims (int): number of weather scenarios outdir (Path): output directory Return: retval (int): 0 if successful, 1 otherwise, 2... outdict (dict): output dictionary at least 'filelist': list of filenames created