def processData(self): ds72_13, names, pre = self.get_dataset(self.pth, self.ds_name) lons_np, lats_np = self.makeLatLng() # Processing for i in range(0, len(names)): if "7213" in names[i]: # print "{0} {1} {2}".format(i, names[i], ds72_13[i]) if i == 0 or i == 9: print names[i] # print ds72_13[i] # Shift lons_r = np.roll(lons_np, 200, axis=0) lons_c = add_cyclic_point(lons_r) ds_d0_np = np.array(ds72_13[i]) ds_rolled = np.roll(ds_d0_np, 200, axis=1) cyclic_data = add_cyclic_point(ds_rolled) da = xr.DataArray(cyclic_data, coords=[lats_np, lons_c], dims=['lat', 'lon']) print da self.getPNG(names[i], da, pre)
def vector_data(gdata, species, alt=400, ialt=None): ''' Input: gdata = gitm bin structure species = 'neutral' or 'ion' alt = altitude (default 400 km) ialt = another way to assign the altitude. if None will use alt, else use ialt Output: lat, lt, nwind, ewind *************************************************************************** Note: Lon raries in x direction, lat varies in y direction. This is different with GITM. *************************************************************************** ''' # Find altitude index if ialt == None: altitude = gdata['Altitude'][0, 0, :] ialt = np.argmin(abs(altitude-alt*1000)) # in GITM, unit of alt is m # Find the data lon0 = np.array(gdata['dLon'][2:-2, 0, 0]) lat0 = np.array(gdata['dLat'][0, 2:-2, 0]) if 'neu' in species.lower(): nwind = np.array(gdata['V!Dn!N (north)'][2:-2, 2:-2, ialt]) ewind = np.array(gdata['V!Dn!N (east)'][2:-2, 2:-2, ialt]) elif 'ion' in species.lower(): nwind = np.array(gdata['V!Di!N (north)'][2:-2, 2:-2, ialt]) ewind = np.array(gdata['V!Di!N (east)'][2:-2, 2:-2, ialt]) nwind, lon0 = add_cyclic_point(nwind.T, coord=lon0, axis=1) ewind = add_cyclic_point(ewind.T, axis=1) lon0, lat0 = np.meshgrid(lon0, lat0) return lon0, lat0, ewind, nwind
def add_cyclic_points(self) -> None: press_cyc, lons = add_cyclic_point(self.__press_inter, np.array(self.__press_inter['lon'].values, dtype=int)) d_arr = xr.DataArray(data=press_cyc, dims=['hybrid', 'lat', 'lon'], coords={'hybrid': ('hybrid', self.__press_inter['hybrid']), 'lat': ('lat', self.__press_inter['lat']), 'lon': ('lon', lons)}, attrs=self.__press_inter.attrs) d_set = xr.Dataset({'PRESS': d_arr}, coords={'hybrid': ('hybrid', d_arr['hybrid']), 'lat': ('lat', d_arr['lat']), 'lon': ('lon', lons)}, ) self.__press_inter = d_set.metpy.parse_cf(varname='PRESS') for name, (d_arr, conf) in list(self.var_conf.items()): d_arr_cyc, lons = add_cyclic_point(d_arr.values, np.array(d_arr['lon'].values, dtype=int)) d_arr = xr.DataArray(data=d_arr_cyc, dims=['hybrid', 'lat', 'lon'], coords={'hybrid': ('hybrid', d_arr['hybrid']), 'lat': ('lat', d_arr['lat']), 'lon': ('lon', lons)}, attrs=d_arr.attrs) d_set = xr.Dataset({name: d_arr}, coords={'hybrid': ('hybrid', d_arr['hybrid']), 'lat': ('lat', d_arr['lat']), 'lon': ('lon', lons)}, ) d_arr = d_set.metpy.parse_cf(varname=name) self.var_conf[name] = (d_arr, conf)
def check_zg_pIB(ds,zg="",pIB=""): try: zg = ds[zg] pIB = ds[pIB] string = "data read successfully" except: string = "Error code 2: zg variable and pIB were not found. " +\ "Hint: use read_main() to load data with right attributes." print(ds) print(string) return 2 #____CHECK GEOP HEIGHT____ #ERA5 dataset uses geopotential, not height if zg.values[0,0,0,0] > 10000: zg = zg/9.80665 #creating arrays try: dat1 = zg.loc[:,5e+04,:,:].values dat2 = pIB.loc[:,5e+04,:,:].values except: dat1 = zg.values[:,0,:,:] dat2 = pIB.values[:,0,:,:] #preparing horizontal positions lats = ds.lat.values lons = ds.lon.values #adding an element to longitude direction as needed by cartopy stereographic transforms if lons[len(lons)-1] != lons[0]: lons = np.append(lons,180-10**(-6))#slightly different for avoiding contour bug dat1 = cutil.add_cyclic_point(dat1) dat2 = cutil.add_cyclic_point(dat2) return lons,lats,dat1,dat2
def _cube_manipulation(cube, x, y): """ Optionally transpose the data and make a mesh-grid, taking into account auxilliary coordinates A lot of this logic closely follows that used in iris.qplt. :param Cube cube: An iris Cube :param NDarray x: a numpy array of x points :param NDarray y: a numpy array of y points :return: data, x, and y and as numpy arrays """ import iris.plot as iplt import iris from cartopy.util import add_cyclic_point import numpy as np no_of_dims = len(cube.shape) data = cube.data plot_defn = iplt._get_plot_defn(cube, iris.coords.POINT_MODE, ndims=no_of_dims) if plot_defn.transpose: data = data.T x = x.T y = y.T # Check for auxiliary coordinates. aux_coords = False for coord in cube[0].coords(dim_coords=False): aux_coords = True if no_of_dims == 2: # If we have found some auxiliary coordinates in the data and the shape of x data or y data is the same as # data assume we have a hybrid coordinate (which is two dimensional b nature. Perhaps need a more robust # method for detecting this. if aux_coords and (data.shape == x.shape or data.shape == y.shape): # Work out which set of data needs expanding to match the coordinates of the others. Note there can only # ever be one hybrid coordinate axis. if y.shape == data.shape: if y[:, 0].shape == x.shape: x, _y = np.meshgrid(x, y[0, :]) elif y[0, :].shape == x.shape: x, _y = np.meshgrid(x, y[:, 0]) elif x.shape == data.shape: if x[:, 0].shape == y.shape: y, _x = np.meshgrid(y, x[0, :]) elif x[0, :].shape == y.shape: y, _x = np.meshgrid(y, x[:, 0]) else: if len(x) == data.shape[-1]: try: data, x = add_cyclic_point(data, x) except ValueError as e: logging.warn('Unable to add cyclic data point for x-axis. Error was: ' + e.args[0]) x, y = np.meshgrid(x, y) elif len(y) == data.shape[-1]: try: data, y = add_cyclic_point(data, y) except ValueError as e: logging.warn('Unable to add cyclic data point for y-axis. Error was: ' + e.args[0]) y, x = np.meshgrid(y, x) return data, x, y
def add_esmf_cyclic(metadata_obs, data_onlevel, interpolated): """Add cyclic points to interpolated data.""" data_onlevel_cyc, lon_obs_cyc = add_cyclic_point( data_onlevel, coord=metadata_obs['lon2d'][0, :]) lonc, latc = np.meshgrid(lon_obs_cyc, metadata_obs['lat2d'][:, 0]) interpolated_cyc, lon_obs_cyc = add_cyclic_point( interpolated, coord=metadata_obs['lon2d'][0, :]) return lonc, latc, data_onlevel_cyc, interpolated_cyc
def animate(i): n= 13-i ax.clear() mask, xtf = cutil.add_cyclic_point(np.roll(Z[n],45,axis=1), coord=xt) depth, _ = cutil.add_cyclic_point(np.roll(d_Z[n],45,axis=1), coord=xt) mask_o, xtf_o = cutil.add_cyclic_point(Z_o[n], coord=xt_o) ax.contour(xtf_o,yt_o, mask_o, colors='k', linewidths=0.5) ax.pcolormesh(xtf,yt,mask, cmap='Blues',vmin=0, vmax=2) ax.pcolormesh(xtf,yt, depth, cmap='ocean',vmin=-5000,vmax=0) ax.set_title('Scaled bathymetry: %s Ma years ago' % time[n])
def compare_mean(ds, varname, ens_o, ens_r, method_str, nlevs=24): """ visualize mean value at each grid point for orig and compressed (time-series) assuming FV data and put the weighted mean """ mean_data_o = ds[varname].sel(ensemble=ens_o).mean(dim='time') mean_data_r = ds[varname].sel(ensemble=ens_r).mean(dim='time') #weighted mean gw = ds['gw'].values o_wt_mean = np.average(np.average(mean_data_o, axis=0, weights=gw)) r_wt_mean = np.average(np.average(mean_data_r, axis=0, weights=gw)) lat = ds['lat'] cy_data_o, lon_o = add_cyclic_point(mean_data_o, coord=ds['lon']) cy_data_r, lon_r = add_cyclic_point(mean_data_r, coord=ds['lon']) fig = plt.figure(dpi=300, figsize=(9, 2.5)) mymap = cmocean.cm.thermal # both plots use same contour levels levels = _calc_contour_levels(cy_data_o, cy_data_r, nlevs) ax1 = plt.subplot(1, 2, 1, projection=ccrs.Robinson(central_longitude=0.0)) title = f'orig:{varname} : mean = {o_wt_mean:.2f}' ax1.set_title(title) pc1 = ax1.contourf(lon_o, lat, cy_data_o, transform=ccrs.PlateCarree(), cmap=mymap, levels=levels) ax1.set_global() ax1.coastlines() ax2 = plt.subplot(1, 2, 2, projection=ccrs.Robinson(central_longitude=0.0)) title = f'{method_str}:{varname} : mean = {r_wt_mean:.2f}' ax2.set_title(title) pc2 = ax2.contourf(lon_r, lat, cy_data_r, transform=ccrs.PlateCarree(), cmap=mymap, levels=levels) ax2.set_global() ax2.coastlines() # add colorbar fig.subplots_adjust(left=0.1, right=0.9, bottom=0.05, top=0.95) cax = fig.add_axes([0.1, 0, 0.8, 0.05]) cbar = fig.colorbar(pc1, cax=cax, orientation='horizontal') cbar.ax.tick_params(labelsize=8, rotation=30)
def xr_add_cyclic_longitudes(da, coord): """Utility function to handle the no-shown-data artifact of 0 and 360-degree longitudes. Args: da (:class:`xarray.core.dataarray.DataArray`): Data array that contains one or more coordinates, strictly including the coordinate with the name given with the "coord" parameter. coord (:class:`str`): Name of the longitude coordinate within "da" data array. """ import xarray as xr import cartopy.util as cutil cyclic_data, cyclic_coord = cutil.add_cyclic_point(da.values, coord=da[coord]) coords = da.coords.to_dataset() coords[coord] = cyclic_coord new_da = xr.DataArray(cyclic_data, dims=da.dims, coords=coords.coords, attrs=da.attrs) new_da.encoding = da.encoding return new_da
def plot_AMV_spatial(var,lon,lat,bbox,cmap,cint=[0,],clab=[0,],ax=None): if ax is None: ax = plt.gca() # Add cyclic point to avoid the gap var,lon1 = add_cyclic_point(var,coord=lon) # Set up projections and extent ax = plt.axes(projection=ccrs.PlateCarree()) ax.set_extent(bbox) # Add filled coastline ax.add_feature(cfeature.COASTLINE,facecolor='k') if len(cint) == 1: # Draw contours cs = ax.contourf(lon1,lat,var,cmap=cmap) else: # Draw contours cs = ax.contourf(lon1,lat,var,cint,cmap=cmap) # Negative contours cln = ax.contour(lon1,lat,var, cint[cint<0], linestyles='dashed', colors='k', linewidths=0.5, transform=ccrs.PlateCarree()) # Positive Contours clp = ax.contour(lon1,lat,var, cint[cint>=0], colors='k', linewidths=0.5, transform=ccrs.PlateCarree()) #ax.clabel(cln,colors=None) # Add Gridlines gl = ax.gridlines(draw_labels=True,linewidth=0.75,color='gray',linestyle=':') gl.xlabels_top = gl.ylabels_right = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER if len(clab) == 1: bc = plt.colorbar(cs) else: bc = plt.colorbar(cs,ticks=clab) return ax
def make_plot(vplot, grid, figsize=10, savefig=None, vmax=None): # add a wrap point for smooth plotting vplot_wrap, lon_wrap = add_cyclic_point(vplot, coord=grid.lon[0, :], axis=1) # figure size plt.rcParams["figure.figsize"] = [figsize, figsize] ax = plt.axes(projection=ccrs.Robinson(central_longitude=-90.)) ax.coastlines() #cs = ax.contourf(lon,lat,vplot,transform=ccrs.PlateCarree(),cmap='bwr') if vmax: maxv = vmax else: maxv = np.nanmax(np.abs(vplot)) cs = ax.pcolormesh(lon_wrap, grid.lat[:, 0], vplot_wrap, transform=ccrs.PlateCarree(), cmap='bwr', shading='flat', vmin=-maxv, vmax=maxv) plt.colorbar(cs, extend='both', shrink=0.4) if savefig: plt.title(savefig) plt.savefig(savefig + '.png', dpi=300) plt.show()
def plot_single_member(z, inens, count): print(z.shape) col = int(count % 5) + 1 row = int((count / 5)) + 1 prj = ccrs.NorthPolarStereo() ax = plt.subplot2grid((4, 5), (row - 1, col - 1), projection=prj) #, colspan=1) ax.coastlines() # set bound (such a pain in cartopy...) # has to be done before data to plot added for use_as_clip_path to work llon = -180 ulon = 180 llat = 20 ulat = 90 ax.set_extent([llon, ulon, llat, ulat], ccrs.PlateCarree()) theta = np.linspace(0, 2 * np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes, use_as_clip_path=True) cyclic_z, cyclic_lon = add_cyclic_point(z, coord=zlon) cplot = ax.contourf(cyclic_lon, zlat, cyclic_z, transform=ccrs.PlateCarree(), extend='both', levels=levs, cmap=cols) ax.set_title(str(inens), x=0.08, y=1.02) return (cplot, cticks)
def anom_map(data, bounds, labels, title, cbar_label, out_name=None, show=False): # Make CO2 anom figure fig = plt.figure(figsize=(13,6.2)) plt.rcParams.update({'font.size': 16}) ax = plt.subplot(111, projection=ccrs.PlateCarree()) data_cyc, lons_cyc = add_cyclic_point(data, coord=lons) lons2d_cyc, lats2d = np.meshgrid(lons_cyc, lats) mm = ax.pcolormesh(lons2d_cyc, lats2d, data_cyc, vmin=bounds[0], vmax=bounds[-1], transform=ccrs.PlateCarree(),cmap='RdBu' ) ax.coastlines() plt.title(title) cbar = fig.colorbar(mm, ax=ax, ticks=bounds) cbar.set_ticklabels(labels) cbar.set_label(cbar_label) # fig.subplots_adjust(right=0.85) # # add_axes defines new area with: X_start, Y_start, width, height # cax = fig.add_axes([0.85,0.53,0.03,0.35]) if out_name is not None: plt.savefig(out_dir+out_name+'.png', format='png', dpi=600) plt.savefig(out_dir+out_name+'.eps', format='eps', dpi=600) if show: plt.show()
def addcyclicpoint(data, lon): ''' Wrapps cartopy.util.add_cyclic_point() to xarray. Works only on 1-level data. Parameters ---------- data : xarray DataArray lon : list of longitudes Returns ------- cyclic_da : xarray DataArray ''' import cartopy.util as ccrs_util # Add cyclic import xarray as xr cyclic_data, cyclic_lon = ccrs_util.add_cyclic_point(data.values, lon) try: cyclic_da = xr.DataArray( cyclic_data, coords=[data['time'], data['lat'], cyclic_lon], dims=['time', 'lat', 'lon']) except KeyError: cyclic_da = xr.DataArray( cyclic_data, coords=[data['time'], data['latitude'], cyclic_lon], dims=['time', 'lat', 'lon']) return cyclic_da
def check_field(ds,field=""): try: field_value = ds[field] string = "data read successfully" except: string = "Error code 2: field variable was not found. " +\ "Hint: use read_main() to load data with right attributes." print(ds) print(string) return 2 #____CHECK GEOP HEIGHT____ #ERA5 dataset uses geopotential, not height if field == "zg" and (field_value.values > 10000).any(): field_value = field_value/9.80665 #preparing horizontal positions lats = ds.lat.values lons = ds.lon.values dat1 = field_value.values #adding an element to longitude direction as needed by cartopy stereographic transforms if lons[len(lons)-1] != lons[0]: lons = np.append(lons,180-10**(-6))#slightly different for avoiding contour bug dat1 = cutil.add_cyclic_point(dat1) return lons,lats,dat1
def plot_map(ds, fld, out): if "time" in fld.dims: Xavg = fld.mean(dim="time") else: Xavg = fld ProjName = "Robinson" PlotType = "contourf" proj = getattr(ccrs, ProjName)() # ADD CYCLIC POINT USING CARTOPY lon = Xavg.coords["lon"] lon_idx = Xavg.dims.index("lon") wrap_data, wrap_lon = add_cyclic_point(Xavg.values, coord=lon, axis=lon_idx) fig = plt.figure(figsize=(8, 3)) ax = fig.add_subplot(111, projection=proj, aspect="auto") p = plt.contourf(wrap_lon, Xavg.coords["lat"], wrap_data, transform=ccrs.PlateCarree()) cb = plt.colorbar(p, ax=ax, orientation="vertical") cb.set_label(Xavg.name) ax.set_global() # TODO: Better plot naming mechanism. plt.savefig(os.path.join(out, "_".join([Xavg.name, "diag_map.pdf"]))) plt.clf() # tell matplotlib we are done with that figure.
def contour_data(zkey, gdata, alt=400, ialt=None): ''' Get Latitude, Local Time (or Longitude) and z data for plot Input: zkey = key for z variable (ie 'Vertical TEC') gdata = gitm bin structure alt = altitude (default 400 km) ialt = another way to assign the altitude. if None will use alt, else use ialt Output: Lat, lon, zdata *************************************************************************** Note: Lon raries in x direction, lat varies in y direction. This is different with GITM. *************************************************************************** ''' # Find altitude index if ialt == None: altitude = gdata['Altitude'][0, 0, 2:-2] ialt = np.argmin(abs(altitude-alt*1000))+2 # in GITM, unit of alt is m # Find the data lon0 = np.array(gdata['dLon'][2:-2, 0, 0]) lat0 = np.array(gdata['dLat'][0, 2:-2, 0]) zdata0 = np.array(gdata[zkey][2:-2, 2:-2, ialt]) zdata0, lon0 = add_cyclic_point(zdata0.T, coord=lon0, axis=1) lon0, lat0 = np.meshgrid(lon0, lat0) return lon0, lat0, zdata0
def cyclic_dataarray(da, coord='lon'): """ Add a cyclic coordinate point to a DataArray along a specified named coordinate dimension. >>> from xray import DataArray >>> data = DataArray([[1, 2, 3], [4, 5, 6]], ... coords={'x': [1, 2], 'y': range(3)}, ... dims=['x', 'y']) >>> cd = cyclic_dataarray(data, 'y') >>> print cd.data array([[1, 2, 3, 1], [4, 5, 6, 4]]) """ assert isinstance(da, xray.DataArray) lon_idx = da.dims.index(coord) cyclic_data, cyclic_coord = add_cyclic_point(da.values, coord=da.coords[coord], axis=lon_idx) # Copy and add the cyclic coordinate and data new_coords = dict(da.coords) new_coords[coord] = cyclic_coord new_values = cyclic_data new_da = xray.DataArray(new_values, dims=da.dims, coords=new_coords) # Copy the attributes for the re-constructed data and coords for att, val in da.attrs.items(): new_da.attrs[att] = val for c in da.coords: for att in da.coords[c].attrs: new_da.coords[c].attrs[att] = da.coords[c].attrs[att] return new_da
def cyclic_dataarray(da, coord='lon'): """ Add a cyclic coordinate point to a DataArray along a specified named coordinate dimension. """ assert isinstance(da, xr.DataArray) lon_idx = da.dims.index(coord) cyclic_data, cyclic_coord = add_cyclic_point(da.values, coord=da.coords[coord], axis=lon_idx) # Copy and add the cyclic coordinate and data new_coords = dict(da.coords) new_coords[coord] = cyclic_coord new_values = cyclic_data new_da = xr.DataArray(new_values, dims=da.dims, coords=new_coords) # Copy the attributes for the re-constructed data and coords for att, val in da.attrs.items(): new_da.attrs[att] = val for c in da.coords: for att in da.coords[c].attrs: new_da.coords[c].attrs[att] = da.coords[c].attrs[att] return new_da
def quick_plot(self, lats, lons, var, levels=None, cmap=None, add_cyclic=False): if add_cyclic is True: var, lons = add_cyclic_point(var, coord=lons) if levels is None: levels = 10 if cmap is None: cmap = plt.get_cmap('RdBu_r') cf = self.ax.contourf(lons, lats, var, levels, cmap=cmap, extend='both', transform=self.trans) cbar = self.fig.colorbar(cf, shrink=0.75, extend='both', orientation='horizontal') self.ax.coastlines() self.ax.set_global() plt.show()
def mean_error(ds, varname, ens_o, ens_r, method_str): """ visualize the mean error want to be able to input multiple? """ e = ds[varname].sel(ensemble=ens_o) - ds[varname].sel(ensemble=ens_r) mean_e = e.mean(dim='time') lat = ds['lat'] cy_data, lon = add_cyclic_point(mean_e, coord=ds['lon']) myfig = plt.figure(dpi=300) mymap = plt.get_cmap('coolwarm') nlevs = 24 ax = plt.subplot(1, 1, 1, projection=ccrs.Robinson(central_longitude=0.0)) pc = ax.pcolormesh(lon, lat, cy_data, transform=ccrs.PlateCarree(), cmap=mymap) # pc = ax.contourf(lon, lat, cy_data, transform=ccrs.PlateCarree(), cmap=mymap, levels=nlevs) cb = plt.colorbar(pc, orientation='horizontal', shrink=.95) cb.ax.tick_params(labelsize=8, rotation=30) ax.set_global() ax.coastlines() title = f'{varname} ({method_str}): mean error ' ax.set_title(title)
def getarr(self, timestep=0, cyclic=False, na_values=-999, replace_nan=False): """ get ndarray((y=64,x=128)) Parameters ---------- timestep :int ,default 0 cyclic :boolean, default = True whether make logitude cyclic or not na_values :float, default -999 set value which is treated as missing value replace_nan :boolean, default False whether replace na_valuse into NaN or not Returns ------- arr :numpy.ndarray model data """ arr = self.chunk[timestep]['arr'] #succeed when order='C' not 'F' arr = arr.reshape((self.y, self.x), order='C') if replace_nan: # arr[arr <= na_values] = np.nan arr = np.where(arr == na_values, np.nan, arr) if cyclic: arr = cutil.add_cyclic_point(arr) # print(self.getDate(timestep=timestep)) return arr
def plotContour(mdata, pdata, addTo=None): plotvar = pdata['plotvar'] data, lons = cuti.add_cyclic_point(np.transpose(mdata[plotvar]), mdata['Lon']) if addTo is None: fig, ax = makeMap(maptime=mdata.attrs['time'], projection=pdata['plotprojection']) if pdata['shapes'] is not None: ax.add_geometries(pdata['shapes'], pdata['plotprojection'], edgecolor='black', facecolor='none') #ax.gridlines() ax.set_xticks([-150, -120, -90, -60, -30, 0, 30], crs=ccrs.PlateCarree()) ax.set_yticks([35, 45, 55, 65, 75], crs=ccrs.PlateCarree()) ax.set_title('{0}[{1}]\n{2}'.format(plotvar, mdata[plotvar].attrs['units'], mdata.attrs['time'].isoformat())) else: ax = addTo cax = ax.contourf(lons, mdata['Lat'], np.array(data), [pdata['thresh'], data.max()], transform=pdata['dataprojection'], colors=pdata['ccolor'], alpha=0.75) return ax
def plot(lonGrid, latGrid, data, show=False, out_file='', title='', **kwargs): plt.close('all') plt.figure() # adding cyclic point # provided the values are given as lat x lon lons = lonGrid[0,:] lats = latGrid[:,0] new_data, new_lons = add_cyclic_point(data, coord=lons) new_lonGrid, new_latGrid = np.meshgrid(new_lons, lats) ax = plt.axes(projection=cartopy.crs.PlateCarree()) ax.coastlines() # getting rid of the line due to lack of continuity _ = plt.contourf(new_lonGrid, new_latGrid, new_data, cmap='jet', **kwargs) cb = plt.colorbar(ax=ax, shrink=0.5) cb.ax.set_ylabel(r'$\tilde{V}^{st}_{850}$ [m/s]') if (len(title) > 0): plt.title(title) if (show): plt.show() if (len(out_file) > 0): if (out_file.endswith('.ps')): plt.savefig(out_file, format='eps', dpi=300.) plt.close('all') elif (out_file.endswith('.png')): plt.savefig(out_file, format='png', dpi=300.) plt.close('all')
def fix_data(da: xr.DataArray, psst=False): # lon 0:360 -> -180:180 # https://stackoverflow.com/a/53471670 da['_lon'] = xr.where(da['lon'] > 180, da['lon'] - 360, da['lon']) da = (da.swap_dims({ 'lon': '_lon' }).sel(**{ '_lon': sorted(da._lon) }).drop('lon')) da = da.rename({'_lon': 'lon'}) da = da.reindex(lat=da.lat[::-1]) lat = da.coords['lat'].values # add cyclic point lon lon = da.coords['lon'].values lon_idx = da.dims.index('lon') arr, lon = add_cyclic_point(da.values, coord=lon, axis=lon_idx) return arr, lat, lon
def getarr(self, timestep=0, cyclic=False, na_values=-999, replace_nan=False): """ return model data as array Parameters ---------- timestep :int, default 0 model timestep cyclic :boolean, default False whether make logitude cyclic or not na_values :float, default -999 set value which is treated as missing value replace_nan :boolean, default False whether replace na_valuse into NaN or not Returns ------- arr :numpy.ndarray, default (x,y,z)=(128,64,36) model data """ arr = self.chunk[timestep]['arr'] arr = arr.reshape((self.z, self.y, self.x), order='C') if replace_nan: arr = np.where(arr == na_values, np.nan, arr) # arr[arr <= na_values] = np.nan if cyclic: arr = cutil.add_cyclic_point(arr) # print(self.getDate(timestep=timestep)) return arr
def cyclic_dataarray(da, coord='lon'): """ Add a cyclic coordinate point to a DataArray along a specified named coordinate dimension. >>> from xray import DataArray >>> data = DataArray([[1, 2, 3], [4, 5, 6]], ... coords={'x': [1, 2], 'y': range(3)}, ... dims=['x', 'y']) >>> cd = cyclic_dataarray(data, 'y') >>> print cd.data array([[1, 2, 3, 1], [4, 5, 6, 4]]) """ assert isinstance(da, xr.DataArray) lon_idx = da.dims.index(coord) cyclic_data, cyclic_coord = add_cyclic_point(da.values, coord=da.coords[coord], axis=lon_idx) # Copy and add the cyclic coordinate and data new_coords = dict(da.coords) new_coords[coord] = cyclic_coord new_values = cyclic_data new_da = xr.DataArray(new_values, dims=da.dims, coords=new_coords) # Copy the attributes for the re-constructed data and coords for att, val in da.attrs.items(): new_da.attrs[att] = val for c in da.coords: for att in da.coords[c].attrs: new_da.coords[c].attrs[att] = da.coords[c].attrs[att] return new_da
def main(): # data URL url = 'https://www.ncei.noaa.gov/thredds/dodsC/OisstBase/NetCDF/V2.1/AVHRR/202012/oisst-avhrr-v02r01.20201210_preliminary.nc' # access data ds = xr.open_dataset(url) ### Plotting ##### proj = ccrs.Orthographic(central_longitude=-40., central_latitude=20.) # resolve longitude wrap-around sst_cyc, lon_cyc = add_cyclic_point(ds.sst, coord=ds.lon) ice_cyc, _ = add_cyclic_point(ds.ice.fillna(-.1), coord=ds.lon) # create figure fig, (ax1, ax2), = plt.subplots(1, 2, figsize=(15, 7.5), subplot_kw={'projection': proj}) ax1.remove() ax2.set_global() ax2.background_patch.set_facecolor('k') ax2.contourf(lon_cyc, ds.lat, sst_cyc.squeeze(), levels=np.linspace(-2, 26, 29), cmap=cmo.thermal, extend='both', transform=ccrs.PlateCarree()) ax2.contourf(lon_cyc, ds.lat, ice_cyc.squeeze(), levels=np.linspace(0, 1, 255), cmap=cmo.ice, transform=ccrs.PlateCarree(), zorder=1) ax2.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m'), edgecolor='none', facecolor='k') # save figure fig.canvas.draw() fig.tight_layout() fig.savefig('static/media/headers/header_background.png', dpi=300)
def read_var(datapath, lonname, latname, varname): datanc = nc.Dataset(datapath) latout = datanc.variables[latname][:] lons = datanc.variables[lonname][:] data = datanc.variables[varname][0, ...] dataout, lonout = cutil.add_cyclic_point(data, coord=lons) datanc.close() return dataout, lonout, latout
def plot_single_lat_lon(z, zlat, zlon, title, outname, lim, by, cbarlim, cbarby, clabel, zsig=0, colorscale='BlueRed'): fig = plt.figure(figsize=(6, 6), dpi=300) # some plot parameters levs = np.arange(-lim,lim+by,by) cbarticks = np.arange(-cbarlim,cbarlim+cbarby,cbarby) cols = color_defs.custom(colorscale) # set up map prj = ccrs.NorthPolarStereo() ax = fig.add_axes([0.05, 0.05, 0.9, 0.90], projection=prj) # left, bottom, width, height ax.coastlines() # has to be done before data to plot added for use_as_clip_path to work llon=-180 ulon=180 llat=20 ulat=90 ax.set_extent([llon, ulon, llat, ulat], ccrs.PlateCarree()) theta = np.linspace(0, 2*np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes, use_as_clip_path=True) # add data # add cyclic point to wrap around in longitude (cartopy function); outputs as np array # if using pyplot: ibase,ilon = user_addcyclic(z,np.array(lon)) cyclic_z, cyclic_lon = add_cyclic_point(z, coord=zlon) cplot = ax.contourf(cyclic_lon, zlat, cyclic_z, transform=ccrs.PlateCarree(), extend='both', levels=levs, cmap=cols) plt.title(title, fontsize=18) # shade OUT non-significance if type(zsig) is int: # default, no significance shown zsig = np.zeros([len(zlat),len(zlon)]) cyclic_zsig, cyclic_tlon = add_cyclic_point(zsig, coord=zlon) cplot_t = ax.contourf(cyclic_lon, zlat, cyclic_zsig, transform=ccrs.PlateCarree(),levels=[-1,0,1],hatches=[None,'..'],colors='none') # colorbar cbar=plt.colorbar(cplot, orientation='vertical', ticks=cbarticks) cbar.set_label(clabel, size=14) cbar.ax.tick_params(labelsize=14) plt.savefig(outname) plt.close()
def compare_std(ds, varname, ens_o, ens_r, method_str, nlevs=24): """ TODO: visualize std dev at each grid point for orig and compressed (time-series) assuming FV mean """ std_data_o = ds[varname].sel(ensemble=ens_o).std(dim='time', ddof=1) std_data_r = ds[varname].sel(ensemble=ens_r).std(dim='time', ddof=1) lat = ds['lat'] cy_data_o, lon_o = add_cyclic_point(std_data_o, coord=ds['lon']) cy_data_r, lon_r = add_cyclic_point(std_data_r, coord=ds['lon']) fig = plt.figure(dpi=300, figsize=(9, 2.5)) mymap = plt.get_cmap('coolwarm') # both plots use same contour levels levels = _calc_contour_levels(cy_data_o, cy_data_r, nlevs) ax1 = plt.subplot(1, 2, 1, projection=ccrs.Robinson(central_longitude=0.0)) title = f'orig:{varname}: std' ax1.set_title(title) pc1 = ax1.contourf(lon_o, lat, cy_data_o, transform=ccrs.PlateCarree(), cmap=mymap, levels=levels) ax1.set_global() ax1.coastlines() ax2 = plt.subplot(1, 2, 2, projection=ccrs.Robinson(central_longitude=0.0)) title = f'{method_str}:{varname}: std' ax2.set_title(title) pc2 = ax2.contourf(lon_r, lat, cy_data_r, transform=ccrs.PlateCarree(), cmap=mymap, levels=levels) ax2.set_global() ax2.coastlines() # add colorbar fig.subplots_adjust(left=0.1, right=0.9, bottom=0.05, top=0.95) cax = fig.add_axes([0.1, 0, 0.8, 0.05]) cbar = fig.colorbar(pc1, cax=cax, orientation='horizontal') cbar.ax.tick_params(labelsize=8, rotation=30)
def main(): month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] # Set plot parameters mpl.rcParams['font.size'] = 20 mpl.rcParams['font.family'] = ['sans-serif'] mpl.rcParams['font.sans-serif'] = ['Avant Garde'] mpl.rcParams['figure.facecolor'] = 'k' mpl.rcParams['axes.edgecolor'] = 'w' mpl.rcParams['axes.labelcolor'] = 'w' mpl.rcParams['text.color'] = 'w' mpl.rcParams['xtick.major.size'] = 0 mpl.rcParams['xtick.minor.size'] = 0 mpl.rcParams['xtick.color'] = 'w' mpl.rcParams['ytick.major.size'] = 0 mpl.rcParams['ytick.minor.size'] = 0 mpl.rcParams['savefig.facecolor'] = 'k' mpl.rcParams['text.usetex'] = False # Import data filepath = sys.argv[1] ds = xr.open_dataset(filepath) ds = ds['sst'] latest_month = len(ds.time) - (2018 - 1891) * 12 ds['time'] = pd.date_range('1891-01', '2018-0' + str(latest_month + 1), freq='M') # Create anomalies clim = ds.sel(time=slice('1951-01', '1980-12')).groupby('time.month') \ .mean('time') anom = ds.groupby('time.month') - clim data = anom.sel(time='2018-0' + str(latest_month)).squeeze() cyclic_data, cyclic_lons = add_cyclic_point(data.values, coord=data.lon.values) # Plot f, ax = et.vis.make_cartopy(grid_lines=False, frameon=True) p = ax.contourf(cyclic_lons, ds.lat, cyclic_data, np.arange(-4, 4.5, 0.5), transform=ccrs.PlateCarree(), cmap=cm.balance) plt.colorbar(p, orientation='horizontal',pad=0.05,fraction=0.05, label='Degrees Celsius') # Text Annotation plt.text(0.5, 1.10, month_names[latest_month - 1] + ' 2018 Sea Surface Temperature Anomalies', horizontalalignment='center', verticalalignment='center', transform=ax.transAxes, fontsize=24) plt.text(0.5, 1.03, '(Deviation from 1951-1980 Mean)', horizontalalignment='center', verticalalignment='center', transform=ax.transAxes, fontsize=16) bottom_left = ('@rileyxbrady' + '\n' + 'Data: JRA COBE-SST' + '\n' + 'Code: https://git.io/fNfYQ') plt.text(0, -0.2, bottom_left, horizontalalignment='left', verticalalignment='center', transform = ax.transAxes, fontsize=12) file_out = month_names[latest_month - 1] + '.2018.COBE-SST.anomalies' et.vis.savefig('figs/' + file_out, dpi=300, transparent=False)
def _add_cyclic_to_field(self, lon, lat, z): """ add an additional column to a dataset to avoid plotting problems around the 0degree longitude Parameters ---------- lon : ndarray VECTOR of unique longitudes. Note that this needs to be a vector! lat : ndarray 2D array of latitudes with same geometry than the data field Z z : ndarray 2D array of values Returns ------- lon : ndarray 2D lat : ndarray 2D Z : ndarray 2D References ---------- [1] https://github.com/SciTools/cartopy/issues/393 [2] http://stackoverflow.com/questions/21864512/cartopy-behavior-when-plotting-projected-data [3] https://github.com/SciTools/cartopy/pull/394 """ try: from cartopy import util as ut except: print( 'Longitude shift can not be performed as most recent CARTOPY version seems not to be installed') return None, None, None assert lon.ndim == 1 assert lat.shape == z.shape lat_out, lon1 = ut.add_cyclic_point(lat, coord=lon) z_out, lon1 = ut.add_cyclic_point(z, coord=lon) lon_out = np.ones_like(lat_out) * lon1 return lon_out, lat_out, z_out
def processData(self): dataset, names, pre = self.get_dataset(self.pth, self.ds_name) #print pre lons_np, lats_np = self.makeLatLng() # Processing for j in range(0, len(names)): for i in range(0, len(names[j])): ds_np = np.array(dataset[j][i]) cyclic_data, cyclic_lon = add_cyclic_point(ds_np, coord=lons_np) da = xr.DataArray(cyclic_data, coords=[lats_np, cyclic_lon], dims=['lat', 'lon']) print pre[j], names[j][i], da self.getPNG(names[j][i], da, pre[j])
def test_data_and_coord_with_axis(self): c_data, c_lons = add_cyclic_point(self.data4d, coord=self.lons, axis=1) r_data = np.concatenate((self.data4d, self.data4d[:, :1]), axis=1) r_lons = np.concatenate((self.lons, np.array([360.]))) assert_array_equal(c_data, r_data) assert_array_equal(c_lons, r_lons)
def test_masked_data(self): new_data = ma.masked_less(self.data2d, 3) c_data = add_cyclic_point(new_data) r_data = ma.concatenate((self.data2d, self.data2d[:, :1]), axis=1) assert_array_equal(c_data, r_data)
def test_invalid_coord_dimensionality(self): lons2d = np.repeat(self.lons[np.newaxis], 3, axis=0) with pytest.raises(ValueError): c_data, c_lons = add_cyclic_point(self.data2d, coord=lons2d)
def test_data_only_with_axis(self): c_data = add_cyclic_point(self.data4d, axis=1) r_data = np.concatenate((self.data4d, self.data4d[:, :1]), axis=1) assert_array_equal(c_data, r_data)
def test_invalid_axis(self): c_data = add_cyclic_point(self.data2d, axis=-3)
lats, uwnd, vwnd = order_latdim(lats, uwnd, vwnd) # Create a VectorWind instance to handle the computation of streamfunction and # velocity potential. w = VectorWind(uwnd, vwnd) # Compute the streamfunction and velocity potential. Also use the bundled # tools to re-shape the outputs to the 4D shape of the wind components as they # were read off files. sf, vp = w.sfvp() sf = recover_data(sf, uwnd_info) vp = recover_data(vp, uwnd_info) # Pick out the field for December and add a cyclic point (the cyclic point is # for plotting purposes). sf_dec, lons_c = add_cyclic_point(sf[11], lons) vp_dec, lons_c = add_cyclic_point(vp[11], lons) # Plot streamfunction. ax1 = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) clevs = [-120, -100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100, 120] sf_fill = ax1.contourf(lons_c, lats, sf_dec * 1e-06, clevs, transform=ccrs.PlateCarree(), cmap=plt.cm.RdBu_r, extend='both') ax1.coastlines() ax1.gridlines() ax1.set_xticks([0, 60, 120, 180, 240, 300, 359.99], crs=ccrs.PlateCarree()) ax1.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True, number_format='.0f') lat_formatter = LatitudeFormatter()
from netCDF4 import Dataset import numpy as np import matplotlib.pyplot as plt from cartopy.util import add_cyclic_point import cartopy.crs as ccrs # Read test data nc_fid = Dataset('test_data.nc','r') lat = nc_fid.variables['lat'][:] lon = nc_fid.variables['lon'][:] var = nc_fid.variables['LWCF(test - reference)'][:] cyclic_data, cyclic_lons = add_cyclic_point(var, coord=lon) # Plot it fig = plt.figure() ax = fig.add_axes() # These contour levels work fine... #levels =[-35, -30, -25, -20, -15, -10, 0, 10, 15, 20, 25, 30, 35] # ...but slightly tweaking them results in a failure: levels =[-35, -30, -25, -20, -15, -10, -5, -2, 2, 5, 10, 15, 20, 25, 30, 35] proj = ccrs.PlateCarree(central_longitude=180) ax = plt.axes(projection= proj) p1 = ax.contourf(cyclic_lons, lat, cyclic_data, transform=ccrs.PlateCarree(), norm=None, levels=levels, cmap='bwr', extend='both', )
def unpack_data_object(data_object, x_variable, y_variable, x_wrap_start): """ :param data_object A cube or an UngriddedData object :return: A dictionary containing x, y and data as numpy arrays """ from iris.cube import Cube import iris.plot as iplt from iris.exceptions import CoordinateNotFoundError import iris import logging from cartopy.util import add_cyclic_point no_of_dims = len(data_object.shape) data = data_object.data # ndarray x = get_coord(data_object, x_variable, data) if hasattr(x, 'points'): x = x.points try: coord = data_object.coord(x_variable) x_axis_name = guess_coord_axis(coord) except CoordinateNotFoundError: x_axis_name = None y = get_coord(data_object, y_variable, data) if hasattr(y, 'points'): y = y.points # Must use special function to check equality of array here, so NaNs are returned as equal and False is returned if # arrays have a different shape if array_equal_including_nan(y, data) or array_equal_including_nan(y, x): y = None if array_equal_including_nan(x, data): data = y y = None if isinstance(data_object, Cube): plot_defn = iplt._get_plot_defn(data_object, iris.coords.POINT_MODE, ndims=no_of_dims) if plot_defn.transpose: data = data.T x = x.T y = y.T # Check for auxiliary coordinates. aux_coords = False for coord in data_object[0].coords(dim_coords=False): aux_coords = True if no_of_dims == 2: # If we have found some auxiliary coordinates in the data and the shape of x data or y data is the same as # data assume we have a hybrid coordinate (which is two dimensional b nature. Perhaps need a more robust # method for detecting this. if aux_coords and (data.shape == x.shape or data.shape == y.shape): # Work out which set of data needs expanding to match the coordinates of the others. Note there can only # ever be one hybrid coordinate axis. if y.shape == data.shape: if y[:, 0].shape == x.shape: x, _y = np.meshgrid(x, y[0, :]) elif y[0, :].shape == x.shape: x, _y = np.meshgrid(x, y[:, 0]) elif x.shape == data.shape: if x[:, 0].shape == y.shape: y, _x = np.meshgrid(y, x[0, :]) elif x[0, :].shape == y.shape: y, _x = np.meshgrid(y, x[:, 0]) else: if len(x) == data.shape[-1]: try: data, x = add_cyclic_point(data, x) except ValueError as e: logging.warn('Unable to add cyclic data point for {}. Error was: '.format(x_variable) + e.args[0]) x, y = np.meshgrid(x, y) elif len(y) == data.shape[-1]: try: data, y = add_cyclic_point(data, y) except ValueError as e: logging.warn('Unable to add cyclic data point for {}. Error was: '.format(y_variable) + e.args[0]) y, x = np.meshgrid(y, x) elif x_axis_name == 'X' and x_wrap_start is not None: x = fix_longitude_range(x, x_wrap_start) logging.debug("Shape of x: " + str(x.shape)) if y is not None: logging.debug("Shape of y: " + str(y.shape)) logging.debug("Shape of data: " + str(data.shape)) return {"data": data, "x": x, "y": y}
def test_invalid_axis(self): with pytest.raises(ValueError): c_data = add_cyclic_point(self.data2d, axis=-3)
import matplotlib.pyplot as plt import gitm_divergence_new as gd alt=400 g1 = gitm.GitmBin('/home/guod/simulation_output/momentum_analysis/' 'run_shrink_iondrift_3_continue/data/3DALL_t030322_013000.bin') alt_ind = np.argmin(np.abs(g1['Altitude'][0,0,:]-alt*1000)) lons, lats, alts = (g1[k] for k in ['Longitude', 'Latitude', 'Altitude']) veln = g1['V!Dn!N (north)'] vele = g1['V!Dn!N (east)']+(2*np.pi)/(24*3600)*(6371*1000+alts)*np.cos(lats) velu = g1['V!Dn!N (up)'] rho = g1['Rho'] zdata1 = calc_div_vert(alts, rho*velu)+calc_div_hozt(lons, lats, alts, rho*veln,rho*vele) dglat = np.array(g1['dLat'][0,2:-2,0]) dglon = np.array(g1['dLon'][2:-2,0,0]) zdata1, dglon = add_cyclic_point(zdata1[2:-2,2:-2,alt_ind].T, coord=dglon, axis=1) g2 = gitm.GitmBin('/home/guod/simulation_output/momentum_analysis/' 'run_no_shrink_iondrift_3/data/3DALL_t030322_013000.bin') lons, lats, alts = (g2[k] for k in ['Longitude', 'Latitude', 'Altitude']) veln = g2['V!Dn!N (north)'] vele = g2['V!Dn!N (east)']+(2*np.pi)/(24*3600)*(6371*1000+alts)*np.cos(lats) velu = g2['V!Dn!N (up)'] rho = g2['Rho'] zdata2 = calc_rusanov_lats(lats,alts,veln) - np.tan(lats)*veln/(6371*1000+alts) zdata22 = gd.calc_divergence_north(g2,veln) # zdata2 = calc_rusanov_lons(lons,lats,alts,vele) # zdata22 = gd.calc_divergence_east(g2,vele) #zdata2 = calc_div_hozt(lons, lats, alts, veln, vele) #zdata22 = gd.calc_divergence_north(g2,veln)+gd.calc_divergence_east(g2,vele) dglat = np.array(g2['dLat'][0,2:-2,0])
def test_invalid_coord_size(self): c_data, c_lons = add_cyclic_point(self.data2d, coord=self.lons[:-1])
def test_invalid_coord_size(self): with pytest.raises(ValueError): c_data, c_lons = add_cyclic_point(self.data2d, coord=self.lons[:-1])
def map_ensembleRobustness(signal, high_agreement_mask, low_agreement_mask, variable, cmap='seismic', title=None): """ generating a graphic for the output of the ensembleRobustness process for a lat/long file. :param signal: netCDF file containing the signal differnce over time :param highagreement: :param lowagreement: :param variable: :param cmap: default='seismic', :param title: default='Modelagreement of Signal' """ try: import matplotlib.pyplot as plt plt.switch_backend('agg') # dont use x-server from cartopy import config from cartopy.util import add_cyclic_point import cartopy.crs as ccrs logger.info('libraries loaded') except Exception as e: msg = 'failed to load libraries' logger.exception(msg) raise Exception(msg) try: # get the path of the file. It can be found in the repo data directory. ds_signal = Dataset(signal,mode='r') ds_lagree = Dataset(low_agreement_mask,mode='r') ds_hagree = Dataset(high_agreement_mask,mode='r') var_signal = np.squeeze(ds_signal.variables[variable]) mask_l = np.squeeze(ds_lagree.variables[variable]) mask_h = np.squeeze(ds_hagree.variables[variable]) mask_l[mask_l==0]=np.nan mask_h[mask_h==0]=np.nan logger.info('data loaded') lons = np.squeeze(ds_signal.variables['lon'][:]) lats = np.squeeze(ds_signal.variables['lat'][:]) cyclic_var, cyclic_lons = add_cyclic_point(var_signal, coord=lons) mask_l, cyclic_lons = add_cyclic_point(mask_l, coord=lons) mask_h, cyclic_lons = add_cyclic_point(mask_h, coord=lons) lons = cyclic_lons.data var_signal = cyclic_var logger.info('lat lon loaded') minval = round(np.nanmin(var_signal)) maxval = round(np.nanmax(var_signal)+.5) logger.info('prepared data for plotting') except Exception as e: msg = 'failed to get data for plotting' logger.exception(msg) raise Exception(msg) try: fig = plt.figure(figsize=(20,10), dpi=600, facecolor='w', edgecolor='k') ax = plt.axes(projection=ccrs.Robinson(central_longitude=0)) norm = MidpointNormalize(midpoint=0) cs = plt.contourf(lons, lats, var_signal, 60, norm=norm, transform=ccrs.PlateCarree(), cmap=cmap, interpolation='nearest') cl = plt.contourf(lons, lats, mask_l, 60, transform=ccrs.PlateCarree(), colors='none', hatches=['//']) ch = plt.contourf(lons, lats, mask_h, 60, transform=ccrs.PlateCarree(), colors='none', hatches=['.']) # plt.clim(minval,maxval) ax.coastlines() ax.set_global() if title == None: plt.title('%s with Agreement' % variable) else: plt.title(title) plt.colorbar(cs) plt.annotate('// = low model ensemble agreement', (0,0), (0, -10), xycoords='axes fraction', textcoords='offset points', va='top') plt.annotate('.. = high model ensemble agreement', (0,0), (0, -20), xycoords='axes fraction', textcoords='offset points', va='top') graphic = 'modelAgreement.png' fig.savefig(graphic) plt.close() logger.info('Plot created and figure saved') except Exception as e: msg = 'failed to plot graphic' logger.exception(msg) raise Exception(msg) return graphic
# Compute components of rossby wave source: absolute vorticity, divergence, # irrotational (divergent) wind components, gradients of absolute vorticity. eta = w.absolutevorticity() div = w.divergence() uchi, vchi = w.irrotationalcomponent() etax, etay = w.gradient(eta) # Combine the components to form the Rossby wave source term. Re-shape the # Rossby wave source array to the 4D shape of the wind components as they were # read off files. S = -eta * div - (uchi * etax + vchi * etay) S = recover_data(S, uwnd_info) # Pick out the field for December and add a cyclic point (the cyclic point is # for plotting purposes). S_dec, lons_c = add_cyclic_point(S[11], lons) # Plot Rossby wave source. ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180)) clevs = [-30, -25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30] fill = ax.contourf(lons_c, lats, S_dec * 1e11, clevs, cmap=plt.cm.RdBu_r, transform=ccrs.PlateCarree(), extend="both") ax.coastlines() ax.gridlines() ax.set_xticks([0, 60, 120, 180, 240, 300, 359.99], crs=ccrs.PlateCarree()) ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True, number_format=".0f") lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) plt.colorbar(fill, orientation="horizontal") plt.title("Rossby Wave Source ($10^{-11}$s$^{-1}$)", fontsize=16)
def test_invalid_coord_dimensionality(self): lons2d = np.repeat(self.lons[np.newaxis], 3, axis=0) c_data, c_lons = add_cyclic_point(self.data2d, coord=lons2d)