"""
Open Boundary condition Forcing preprocessings
"""
import logging
import os
import numpy as np
from ...log import LoggingLevelContext
import pandas as pd
import glob
with LoggingLevelContext(logging.WARNING):
import xarray as xr
from xoa.filter import erode_mask
from pathlib import Path
from ...times import convert_to_julian_day
from ...interp import interp_time, Regridder
from ...phys import (
windstress,
radiativeflux,
celsius2kelvin,
watervapormixingratio,
)
from ...filters import erode_mask_vec
from .__init__ import CROCO_PARAM
from ...io import read_config
LOGGER = logging.getLogger(__name__)
[docs]def rename_vars(ds, mod):
"""Rename variables as expected by Extract"""
LOGGER.info("Rename obc variables as expected by Extract program")
obc_names = mod["varnames"]
list_nc_vars = list(ds.variables.keys())
list_nc_dims = list(ds.dims.keys())
for variable in list_nc_vars:
for key, value in obc_names.items():
if variable == value and value != key:
ds = ds.rename_vars({variable: key})
if variable in list_nc_dims:
print("variable also a dim")
ds = ds.rename_dims({variable: key})
# remove unused variables
for dsi in list(ds.variables.keys()):
if dsi not in obc_names:
ds = ds.drop(dsi)
return ds
[docs]def reset_validminmax(fname):
"""reset valid min and max for a dataset"""
LOGGER.info("reset valid min & max")
ds = xr.open_mfdataset(fname)
ds2 = ds.copy()
ds.close()
for var in list(ds2.variables.keys()):
if var not in list(ds2.dims.keys()):
set_validminmax(ds2[var])
os.remove(fname)
ds2.to_netcdf(fname, mode="w")
[docs]def set_validminmax(data):
"""set valid min & max of data variable"""
vmin = float(data.min().to_numpy())
vmax = float(data.max().to_numpy())
data.attrs.update(valid_min=vmin, valid_max=vmax)
return data
[docs]def get_dates_from_file(fname, tname="time"):
"""get the start and end dates from a file"""
print("open", fname)
ds = xr.open_mfdataset(fname)
time = ds.indexes[tname]
d1 = time[0].strftime("%Y%m%dT%H%M")
d2 = time[-1].strftime("%Y%m%dT%H%M")
return d1, d2
[docs]def build_obc_list(date1, date2, model):
"""Build obc list of files from OGCM model"""
LOGGER.info("Get list of obc files")
# retrieve params of meteo model
mod = read_config(model)
rac = mod["prefix"]
data_dir = mod["data_dir"]
suff = mod["suff"]
# build list of date
dates_list = pd.date_range(start=date1, end=date2, freq=mod["freq"])
# build list of names
inst_list = [f"{rac}{date.strftime('%Y%m%d')}" for date in dates_list]
# finally build list of files
# inst_list = [glob.glob(f"{data_dir}/*/*/{file}*.nc")[0] for file in inst_list]
inst_list = [
glob.glob(f"{data_dir}/**/{file}*.nc", recursive=True)[0] for file in inst_list
]
return inst_list
[docs]def read_obc_data(inst_list, lon_bnds, lat_bnds):
"""Read the list of obc files and reduce it to the area of interest"""
from functools import partial
def _preprocess(x, lon_bnds, lat_bnds):
return x.sel(longitude=slice(*lon_bnds), latitude=slice(*lat_bnds))
partial_func = partial(_preprocess, lon_bnds=lon_bnds, lat_bnds=lat_bnds)
ds_inst = xr.open_mfdataset(
inst_list, concat_dim="time", combine="nested", preprocess=partial_func
)
return ds_inst