From dff9207bd4d570b68c4bdde7966d01a45ba339c2 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Fri, 8 Jul 2022 08:08:50 +0200 Subject: [PATCH] Reverted Matt's changes for regridding model output (temporarily). And created a new file that contains that work as a reference (#13) --- .../src/cli/transform/__init__.py | 29 +--- .../cli/transform/__init__.py.new-matt-work | 151 ++++++++++++++++++ 2 files changed, 152 insertions(+), 28 deletions(-) create mode 100644 models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py.new-matt-work diff --git a/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py b/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py index 44b4cd4e..f80386e8 100644 --- a/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py +++ b/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py @@ -1,7 +1,6 @@ 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 @@ -120,32 +119,6 @@ def transform(options, arguments): 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) + data_out.to_netcdf(nc_output_path) print('Complete! If you don\'t see this message there was a problem') \ No newline at end of file diff --git a/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py.new-matt-work b/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py.new-matt-work new file mode 100644 index 00000000..44b4cd4e --- /dev/null +++ b/models/algoa-bay-forecast/toolkit/post-processing/src/cli/transform/__init__.py.new-matt-work @@ -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') \ No newline at end of file