|
| 1 | +def cmap_zerocent_scale(plot,scale_factor): |
| 2 | + """ |
| 3 | + Center colormap at zero and scale relative to existing |maximum| value, |
| 4 | + given plot object and scale_factor, a number of type float. |
| 5 | + Returns new colormap limits as new_clim. |
| 6 | + """ |
| 7 | + curr_clim = plot.get_clim() |
| 8 | + new_clim = (scale_factor*np.max(np.abs(curr_clim)))*np.array([-1,1]) |
| 9 | + plot.set_clim(new_clim) |
| 10 | + return new_clim |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +def plot_mask(*args,ax=None,color): |
| 15 | + """ |
| 16 | + Plot mask, given input parameters: |
| 17 | + - X, Y: (optional) coordinates as 1-D or 2-D NumPy arrays or xarray DataArrays |
| 18 | + - mask: 2-D array of boolean values (True/False or 1/0), NumPy or xarray |
| 19 | + - axes: axes to plot on, defaults to current axes |
| 20 | + - color: a string indicating a color in Matplotlib, or a 3-element tuple or NumPy array indicating RGB color values |
| 21 | + |
| 22 | + Returns plot_obj, the plot object of the mask |
| 23 | + """ |
| 24 | + if len(args) == 1: |
| 25 | + mask = args[0] |
| 26 | + else: |
| 27 | + X = args[0] |
| 28 | + Y = args[1] |
| 29 | + mask = args[2] |
| 30 | + # set alpha values to 1 where mask is plotted, 0 otherwise |
| 31 | + if str(type(mask))[0:5] == 'xarray': |
| 32 | + mask = mask.values |
| 33 | + # get color for mask |
| 34 | + if isinstance(color,str): |
| 35 | + import matplotlib.colors as mcolors |
| 36 | + color_rgb = mcolors.to_rgb(color) |
| 37 | + elif (isinstance(color,tuple)) and (len(color) == 3): |
| 38 | + color_rgb = np.asarray(color) |
| 39 | + elif (isinstance(color,np.ndarray)) and (len(color) == 3): |
| 40 | + color_rgb = color |
| 41 | + else: |
| 42 | + raise TypeError("input parameter 'color' has incorrect type or number of elements") |
| 43 | + # create a colormap using a 2x4 array with two RGBA entries |
| 44 | + # the RGB entries are the same in each row |
| 45 | + # in the 1st row alpha=0, in the 2nd row alpha=1 |
| 46 | + cmap_array = np.hstack((np.tile(color_rgb,(2,1)),np.array([[0],[1]]))) |
| 47 | + from matplotlib.colors import ListedColormap |
| 48 | + colormap = ListedColormap(cmap_array) |
| 49 | + # get axis limits of existing plot |
| 50 | + if ax is None: |
| 51 | + ax = plt.gca() |
| 52 | + existing_xlim = ax.get_xlim() |
| 53 | + existing_ylim = ax.get_ylim() |
| 54 | + # plot mask using colormap just created, with alpha=1 where mask=1 or True |
| 55 | + if len(args) == 1: |
| 56 | + plot_obj = ax.pcolormesh(mask,cmap=colormap,vmin=0.,vmax=1.,zorder=50) |
| 57 | + else: |
| 58 | + plot_obj = ax.pcolormesh(X,Y,mask,cmap=colormap,vmin=0.,vmax=1.,zorder=50) |
| 59 | + # set axis limits of mask to axis limits of existing plot |
| 60 | + ax.set_xlim(existing_xlim) |
| 61 | + ax.set_ylim(existing_ylim) |
| 62 | + |
| 63 | + return plot_obj |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +def geos_vel_compute(dens_press_filename,grid_filename="~/Downloads/ECCO_V4r4_PODAAC/ECCO_L4_GEOMETRY_LLC0090GRID_V4R4/GRID_GEOMETRY_ECCO_V4r4_native_llc0090.nc",fc_filename="llc_13tile_fc.txt"): |
| 68 | + """ |
| 69 | + This routine computes geostrophic velocities from an input netCDF file containing ECCO v4r4 density and pressure anomalies on the native llc90 grid. |
| 70 | + |
| 71 | + Parameters |
| 72 | + ---------- |
| 73 | + dens_press_filename: the name (including path if not in current directory) of the netCDF file containing the density and pressure anomalies |
| 74 | + |
| 75 | + grid_filename: the name (including path if not in current directory) of the netCDF file containing the latitudes ('YC') and grid parameters ('dxC','dyC') needed to compute horizontal derivatives |
| 76 | + |
| 77 | + fc_filename: text file containing a Python dictionary specifying the tile/face connections in the ECCO llc90 grid |
| 78 | + """ |
| 79 | + |
| 80 | + import numpy as np |
| 81 | + import xarray as xr |
| 82 | + import json |
| 83 | + import xgcm |
| 84 | + |
| 85 | + # load file into workspace |
| 86 | + ds_denspress = xr.open_dataset(dens_press_filename, data_vars='minimal',\ |
| 87 | + coords='minimal', compat='override') |
| 88 | + |
| 89 | + densanom = ds_denspress.RHOAnoma |
| 90 | + |
| 91 | + rhoConst = 1029. |
| 92 | + dens = rhoConst + densanom |
| 93 | + |
| 94 | + pressanom = ds_denspress.PHIHYDcR |
| 95 | + |
| 96 | + |
| 97 | + # load grid parameters file |
| 98 | + ds_grid = xr.open_dataset(grid_filename) |
| 99 | + |
| 100 | + |
| 101 | + # load face_connections dictionary |
| 102 | + |
| 103 | + # read in as string |
| 104 | + with open(fc_filename) as fc: |
| 105 | + data = fc.read() |
| 106 | + # convert string to dictionary |
| 107 | + face_connections = json.loads(data) |
| 108 | + |
| 109 | + |
| 110 | + # create xgcm Grid object |
| 111 | + grid = xgcm.Grid(ds_grid,periodic=False,face_connections=face_connections) |
| 112 | + |
| 113 | + # compute derivatives of pressure in x and y |
| 114 | + d_press_dx = (grid.diff(rhoConst*pressanom,axis="X",boundary='extend'))/ds_grid.dxC |
| 115 | + d_press_dy = (grid.diff(rhoConst*pressanom,axis="Y",boundary='extend'))/ds_grid.dyC |
| 116 | + |
| 117 | + # interpolate (vector) gradient values to center of grid cells |
| 118 | + press_grads_interp = grid.interp_2d_vector({'X':d_press_dx,'Y':d_press_dy},boundary='extend') |
| 119 | + dp_dx = press_grads_interp['X'] |
| 120 | + dp_dy = press_grads_interp['Y'] |
| 121 | + |
| 122 | + # compute f from latitude of grid cell centers |
| 123 | + lat = ds_grid.YC |
| 124 | + Omega = (2*np.pi)/86164 |
| 125 | + lat_rad = (np.pi/180)*lat # convert latitude from degrees to radians |
| 126 | + f = 2*Omega*np.sin(lat_rad) |
| 127 | + |
| 128 | + # compute geostrophic velocities |
| 129 | + v_g = dp_dx/(f*dens) |
| 130 | + u_g = -dp_dy/(f*dens) |
| 131 | + |
| 132 | + # assign attributes to DataArrays (names) and units |
| 133 | + u_g.name = 'u_g' |
| 134 | + u_g.attrs.update({'long_name': 'Geostrophic velocity in model-x direction',\ |
| 135 | + 'units': 'm s-1'}) |
| 136 | + v_g.name = 'v_g' |
| 137 | + v_g.attrs.update({'long_name': 'Geostrophic velocity in model-y direction',\ |
| 138 | + 'units': 'm s-1'}) |
| 139 | + |
| 140 | + # create xarray Dataset containing geostrophic velocities |
| 141 | + ds_geos_vel = u_g.to_dataset(name='u_g',promote_attrs=True) |
| 142 | + ds_geos_vel['v_g'] = v_g |
| 143 | + |
| 144 | + return ds_geos_vel |
0 commit comments