-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reverted Matt's changes for regridding model output (temporarily). An…
…d created a new file that contains that work as a reference (#13)
- Loading branch information
Showing
2 changed files
with
152 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
151 changes: 151 additions & 0 deletions
151
...ls/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py.new-matt-work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import xarray as xr | ||
import numpy as np | ||
from datetime import timedelta, datetime | ||
import xesmf as xe #Function for regridding not sure how easy it is to add to pipenv | ||
from cli.transform.depth_functions import z_levels | ||
|
||
# All dates in the CROCO output are represented | ||
# in seconds from 1 Jan 2000 (i.e. the reference date) | ||
REFERENCE_DATE = datetime(2000, 1, 1, 0, 0, 0) | ||
|
||
# Rounds to nearest hour by adding a timedelta hour if minute >= 30 | ||
def hour_rounder(t): | ||
return (t.replace(second=0, microsecond=0, minute=0, hour=t.hour) + timedelta(hours=t.minute//30)) | ||
|
||
# Converts the v current component to the correct (rho) grid | ||
def v2rho_4d(var_v): | ||
[T,D,M,Lp]=var_v.shape | ||
var_rho=np.zeros((T,D,M+1,Lp)) | ||
var_rho[:,:,1:M-1,:]=0.5*np.squeeze([var_v[:,:,0:M-2,:]+var_v[:,:,1:M-1,:]]) | ||
var_rho[:,:,0,:]=var_rho[:,:,1,:] | ||
var_rho[:,:,M,:]=var_rho[:,:,M-1,:] | ||
return var_rho | ||
|
||
# Converts the u current component to the correct (rho) grid | ||
def u2rho_4d(var_u): | ||
[T,D,Mp,L]=var_u.shape | ||
var_rho=np.zeros((T,D,Mp,L+1)) | ||
var_rho[:,:,:,1:L-1]=0.5*np.squeeze([var_u[:,:,:,0:L-2]+var_u[:,:,:,1:L-1]]) | ||
var_rho[:,:,:,0]=var_rho[:,:,:,1] | ||
var_rho[:,:,:,L]=var_rho[:,:,:,L-1] | ||
return var_rho | ||
|
||
# Model variables use the dimensions time (time from reference date), | ||
# eta_rho (lat) and xi_rho (lon). We are changing eta_rho and xi_rho | ||
# from grid points to real lat and lon data. | ||
def transform(options, arguments): | ||
#Setting the paths using the bash input | ||
nc_output_path = options.nc_output_path | ||
nc_input_path = options.nc_input_path | ||
grid_input_path = options.grid_input_path | ||
|
||
print('== Running Algoa Bay Forecast post-processing ==') | ||
print('nc-input-path', options.nc_input_path) | ||
print('grid-input-path', options.grid_input_path) | ||
print('nc-output-path', options.nc_output_path) | ||
|
||
data = xr.open_dataset(nc_input_path) | ||
data_grid = xr.open_dataset(grid_input_path) | ||
|
||
# Dimensions that need to be transformed | ||
time = data.time.values | ||
lon_rho = data.lon_rho.values | ||
lat_rho = data.lat_rho.values | ||
s_rho = data.s_rho.values | ||
|
||
# Convert time to human readable | ||
dates = [] | ||
for t in time: | ||
date_now = REFERENCE_DATE + timedelta(seconds=np.float64(t)) | ||
date_round = hour_rounder(date_now) | ||
dates.append(date_round) | ||
|
||
# Variables used in the visualisations | ||
temperature = data.temp.values | ||
salt = data.salt.values | ||
ssh = data.zeta.values | ||
u = data.u.values | ||
v = data.v.values | ||
|
||
#Variables used to calculate depth levels | ||
theta_s = data.theta_s | ||
theta_b = data.theta_b | ||
|
||
#Variables used to calculate depth levels from grid (bathymetry) | ||
h = data_grid.h.values | ||
|
||
# Convert u and v current components to the rho grid | ||
# use the function u2rho_4d and v2rho_4d | ||
u_rho = u2rho_4d(u) | ||
v_rho = v2rho_4d(v) | ||
|
||
# Replace temperatures = 0 celsius with nan | ||
# In this dataset a temperature of 0 is representative | ||
# of a grid location that is not water (over land) | ||
temperature[np.where(temperature == 0)] = np.nan | ||
salt[np.where(salt == 0)] = np.nan | ||
u[np.where(u == 0)] = np.nan | ||
v[np.where(v == 0)] = np.nan | ||
|
||
# Variables hard coded set during model configuration | ||
# Relative to each model | ||
hc = 200 | ||
N = np.shape(data.s_rho)[0] | ||
type_coordinate = 'rho' | ||
vtransform = 2 | ||
|
||
# m_rho refers to the depth level in meters | ||
m_rho = np.zeros(np.shape(temperature)) | ||
|
||
for x in np.arange(np.size(temperature,0)): | ||
depth_temp = z_levels(h,ssh[x,:,:],theta_s,theta_b,hc,N,type_coordinate,vtransform) | ||
m_rho[x,::] = depth_temp | ||
|
||
# Create new xarray dataset with selected variables | ||
data_out = xr.Dataset( | ||
data_vars=dict( | ||
temperature=(["time","depth","lat", "lon"], temperature[:,:,:,:]), | ||
salt=(["time","depth","lat", "lon"], salt[:,:,:,:]), | ||
u=(["time","depth","lat", "lon"], u_rho[:,:,:,:]), | ||
v=(["time","depth","lat", "lon"], v_rho[:,:,:,:]), | ||
m_rho= (["time","depth","lat","lon"],m_rho) | ||
|
||
), | ||
coords=dict( | ||
lon_rho=(["lat", "lon"], lon_rho), | ||
lat_rho=(["lat", "lon"], lat_rho), | ||
depth=s_rho, | ||
time=dates, | ||
), | ||
attrs=dict(description="CROCO output from algoa Bay model transformed lon/lat/depth/time"), | ||
) | ||
|
||
# Getting max lon and lat to define corners of new regular grid | ||
lonmax = np.nanmax(lon_rho) | ||
lonmin = np.nanmin(lon_rho) | ||
latmax = np.nanmax(lat_rho) | ||
latmin = np.nanmin(lat_rho) | ||
|
||
#Step size of new grid ~1km | ||
stepsize = 0.01 | ||
|
||
# Creating output grid in the form of a dataset | ||
ds_out = xr.Dataset( | ||
data_vars=dict( | ||
), | ||
coords=dict( | ||
time=dates, | ||
depth=s_rho, | ||
longitude=(["longitude"], np.arange(lonmin,lonmax,stepsize)), | ||
latitude=(["latitude"], np.arange(latmin,latmax,stepsize)), | ||
), | ||
attrs=dict(description="CROCO output from algoa Bay model transformed lon/lat/depth/time"), | ||
) | ||
|
||
# Perform gridding from data_out to new dataset dr_out using the ds_out grid | ||
regridder = xe.Regridder(data_out, ds_out, "bilinear") | ||
dr_out = regridder(data_out) | ||
|
||
#Print output | ||
dr_out.to_netcdf(nc_output_path) | ||
print('Complete! If you don\'t see this message there was a problem') |