Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
akarich73 committed Oct 14, 2024
1 parent 024f9e5 commit 5f41928
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 4 deletions.
23 changes: 21 additions & 2 deletions barra2_dl/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,29 @@ class LatLonBBox(TypedDict):
"{var}_AUS-11_ERA5_historical_hres_BOM_BARRA-R2_v1_1hr_{year}{month:02d}-{year}{month:02d}.nc")

# index for barra2 used to join separate files
barra2_index = ['time', 'station', 'latitude[unit="degrees_north"]', 'longitude[unit="degrees_east"]']
barra2_aus11__index = ['time', 'station', 'latitude[unit="degrees_north"]', 'longitude[unit="degrees_east"]']

# BARRA2 wind speed variable pairs
barra2_aus11_wind_all = [('ua10m', 'va10m', '10m[unit="m s-1"]'),
('ua20m', 'va20m', '20m[unit="m s-1"]'),
('ua30m', 'va30m', '30m[unit="m s-1"]'),
('ua50m', 'va50m', '50m[unit="m s-1"]'),
('ua70m', 'va70m', '70m[unit="m s-1"]'),
('ua100m', 'va100m', '100m[unit="m s-1"]'),
('ua150m', 'va150m', '150m[unit="m s-1"]'),
('ua200m', 'va200m', '200m[unit="m s-1"]'),
('ua250m', 'va250m', '250m[unit="m s-1"]'),
('ua300m', 'va300m', '30m[unit="m s-1"]'),
('ua400m', 'va400m', '400m[unit="m s-1"]'),
('ua500m', 'va500m', '500m[unit="m s-1"]'),
('ua600m', 'va600m', '600m[unit="m s-1"]'),
('ua700m', 'va700m', '700m[unit="m s-1"]'),
('ua850m', 'va850m', '850m[unit="m s-1"]'),
('ua925m', 'va925m', '925m[unit="m s-1"]'),
('ua1000m', 'va1000m', '1000m[unit="m s-1"]')]

# set list of BARRA2 variables to download default list is eastward wind (ua*), northward wind (va*), and air temperature at 50m (ta50m)
barra2_var_wind_all = ["ua50m", "va50m", "ua100m", "va100m", "ua150m", "va150m", "ta50m"]
barra2_var_wind_custom = ["ua50m", "va50m", "ua100m", "va100m", "ua150m", "va150m", "ta50m"]

# optional limited variables to test
barra2_var_wind_50m = ["ua50m", "va50m", "ta50m"]
Expand Down
131 changes: 129 additions & 2 deletions barra2_dl/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
This module contains helper functions.
"""

from pathlib import Path
import pandas as pd
import numpy as np
import fnmatch
from pathlib import Path
from typing import List
from typing import List, Union


def list_months(start_datetime: str, end_datetime: str, freq: str ='MS', **kwargs) -> list:
Expand Down Expand Up @@ -162,3 +163,129 @@ def get_timestamp_range_list(dataframe: pd.DataFrame, timestamp_column: str) ->
last_timestamp = dataframe[timestamp_column].iloc[-1]

return [first_timestamp, last_timestamp]

# todo draft function to combine csv files on index need to check and add tests
def combine_csv_files(file_paths: list[str | Path], output_file: str | Path, index_col: str) -> None:
"""
Combine multiple CSV files with a common index column into a single CSV file.
Args:
file_paths (list[str | Path]): A list of file paths to the CSV files to be combined.
output_file (str | Path): The path where the combined CSV file should be saved.
index_col (str): The name of the column to be used as the index for combining the CSV files.
Returns:
None
"""
combined_df = None

for file_path in file_paths:
# Read the current CSV file
df = pd.read_csv(file_path, index_col=index_col)

if combined_df is None:
combined_df = df
else:
combined_df = combined_df.join(df, how='outer')

# Save the combined DataFrame to the output file
combined_df.to_csv(output_file)

return

# todo draft function to process csvs
def process_csvs:
# process barra2 variables to wind speed and direction todo split into modules

# initiate DataFrame for adding new columns
df_processed = df_combined

# loop through df_combined to df_processed
for tup in barra2_wind_speeds:
mask_wind_speed_h = tup[0][2:]
mask_ua = df_combined.columns.str.contains(tup[0]) # selects column header
mask_va = df_combined.columns.str.contains(tup[1]) # selects column header

if np.any(mask_ua == True) and np.any(mask_va == True):
df_processed_ua = df_combined.loc[:, mask_ua] # selects mask
df_processed_va = df_combined.loc[:, mask_va] # selects mask

print('Converted: ' + tup.__str__())

df_processed_v = pd.DataFrame(np.sqrt(df_processed_ua.iloc[:, 0] ** 2 + df_processed_va.iloc[:, 0] ** 2))
df_processed_v.columns = ['v' + mask_wind_speed_h + '[unit="m s-1"]']

df_processed_phi_met = pd.DataFrame()

for index, row in df_combined.iterrows():
if (df_processed_ua.iloc[index, 0] == 0) and (df_processed_va.iloc[index, 0] == 0):
df_processed_phi_met.loc[index, 'v' + mask_wind_speed_h + '_' + 'phi_met[unit="degrees"]'] = 0.0
else:
df_processed_phi_met.loc[index, 'v' + mask_wind_speed_h + '_' + 'phi_met[unit="degrees"]'] = (
np.mod(180 + np.rad2deg(
np.arctan2(df_processed_ua.iloc[index, 0], df_processed_va.iloc[index, 0])), 360))

# Merge the current variable DataFrame with the combined DataFrame
df_processed = df_processed.join(df_processed_v)
df_processed = df_processed.join(df_processed_phi_met)

# export combined to csv
df_processed.to_csv(
os.path.join(output_dir,
f"{output_filename_prefix}_processed_{start_date_time.strftime("%Y%m%d")}_{end_date_time.strftime("%Y%m%d")}.csv"))

return


# todo add tests
def calculate_wind_speed(ua: Union[float, int, List[float], List[int]], va: Union[float, int, List[float], List[int]]) -> Union[float, List[float]]:
"""
Convert wind components ua and va to wind speed v.
Args:
ua (Union[float, int, List[float], List[int]]): The u-component of the wind.
va (Union[float, int, List[float], List[int]]): The v-component of the wind.
Returns:
float or List[float]: The calculated wind speed.
Raises:
ValueError: If the input types do not match or if they are neither List[float] nor float.
"""
if isinstance(ua, (float, int)) and isinstance(va, (float, int)):
if ua == 0 and va == 0:
return 0.0
return np.sqrt(ua ** 2 + va ** 2)
elif isinstance(ua, list) and isinstance(va, list):
if not all(isinstance(num, (float, int)) for num in ua + va):
raise ValueError("All elements in both lists must be either float or int.")
if len(ua) != len(va):
raise ValueError("Both lists must be of the same length.")
return [0.0 if u == 0 and v == 0 else np.sqrt(u ** 2 + v ** 2) for u, v in zip(ua, va)]
else:
raise ValueError("Both arguments must be either both float/int or both lists of float/int.")


# todo add tests
def calculate_wind_direction(ua: Union[float, int, List[float], List[int]], va: Union[float, int, List[float], List[int]]) -> Union[float, List[float]]:
"""
Convert wind components ua and va to wind direction phi.
Args:
ua (Union[float, int, List[float], List[int]]): The u-component of the wind.
va (Union[float, int, List[float], List[int]]): The v-component of the wind.
Returns:
float or List[float]: The calculated wind speed.
Raises:
ValueError: If the input types and incorrect or do not match or if lists of different lengths are provided.
"""

if isinstance(ua, (float, int)) and isinstance(va, (float, int)):
if ua == 0 and va == 0:
return 0.0
return np.mod(180 + np.rad2deg(np.arctan2(ua, va)), 360)
elif isinstance(ua, list) and isinstance(va, list):
if not all(isinstance(num, (float, int)) for num in ua + va):
raise ValueError("All elements in both lists must be either float or int.")
if len(ua) != len(va):
raise ValueError("Both lists must be of the same length.")
return [0.0 if u == 0 and v == 0 else np.mod(180 + np.rad2deg(np.arctan2(u, v)), 360) for u, v in zip(ua, va)]
else:
raise ValueError("Both arguments must be either both float/int or both lists of float/int.")

0 comments on commit 5f41928

Please sign in to comment.