def test_is_regular_pass(self): """ Test is_regular function. """ coord = np.array([[1, 2], [4.4, 5.4], [4, 5]]) self.assertFalse(grid_is_regular(coord)) coord = np.array([[1, 2], [4.4, 5], [4, 5]]) self.assertFalse(grid_is_regular(coord)) coord = np.array([[1, 2], [4, 5]]) self.assertFalse(grid_is_regular(coord)) coord = np.array([[1, 2], [4, 5], [1, 5], [4, 3]]) self.assertFalse(grid_is_regular(coord)) coord = np.array([[1, 2], [4, 5], [1, 5], [4, 2]]) self.assertTrue(grid_is_regular(coord)) grid_x, grid_y = np.mgrid[10:100:complex(0, 5), 0:10:complex(0, 5)] grid_x = grid_x.reshape(-1, ) grid_y = grid_y.reshape(-1, ) coord = np.array([grid_x, grid_y]).transpose() self.assertTrue(grid_is_regular(coord)) grid_x, grid_y = np.mgrid[10:100:complex(0, 4), 0:10:complex(0, 5)] grid_x = grid_x.reshape(-1, ) grid_y = grid_y.reshape(-1, ) coord = np.array([grid_x, grid_y]).transpose() self.assertTrue(grid_is_regular(coord))
def resolution(self): """ Returns a tuple of the resolution in the same unit as the coords. """ if self._resolution is None: assert grid_is_regular(self.coord), 'Centroids not a regular grid' lats = np.unique(self.lat) lons = np.unique(self.lon) res_lat = lats[1] - lats[0] res_lon = lons[1] - lons[0] self._resolution = (res_lat, res_lon) return self._resolution
def test_is_regular_pass(self): """ Test is_regular function. """ coord = np.array([[1, 2], [4.4, 5.4], [4, 5]]) reg, hei, wid = grid_is_regular(coord) self.assertFalse(reg) self.assertEqual(hei, 1) self.assertEqual(wid, 1) coord = np.array([[1, 2], [4.4, 5], [4, 5]]) reg, hei, wid = grid_is_regular(coord) self.assertFalse(reg) self.assertEqual(hei, 1) self.assertEqual(wid, 1) coord = np.array([[1, 2], [4, 5]]) reg, hei, wid = grid_is_regular(coord) self.assertFalse(reg) self.assertEqual(hei, 1) self.assertEqual(wid, 1) coord = np.array([[1, 2], [4, 5], [1, 5], [4, 3]]) reg, hei, wid = grid_is_regular(coord) self.assertFalse(reg) self.assertEqual(hei, 2) self.assertEqual(wid, 1) coord = np.array([[1, 2], [4, 5], [1, 5], [4, 2]]) reg, hei, wid = grid_is_regular(coord) self.assertTrue(reg) self.assertEqual(hei, 2) self.assertEqual(wid, 2) grid_x, grid_y = np.mgrid[10 : 100 : complex(0, 5), 0 : 10 : complex(0, 5)] grid_x = grid_x.reshape(-1,) grid_y = grid_y.reshape(-1,) coord = np.array([grid_x, grid_y]).transpose() reg, hei, wid = grid_is_regular(coord) self.assertTrue(reg) self.assertEqual(hei, 5) self.assertEqual(wid, 5) grid_x, grid_y = np.mgrid[10 : 100 : complex(0, 4), 0 : 10 : complex(0, 5)] grid_x = grid_x.reshape(-1,) grid_y = grid_y.reshape(-1,) coord = np.array([grid_x, grid_y]).transpose() reg, hei, wid = grid_is_regular(coord) self.assertTrue(reg) self.assertEqual(hei, 5) self.assertEqual(wid, 4)
def geo_im_from_array(array_sub, geo_coord, var_name, title, proj=ccrs.PlateCarree(), smooth=True, axes=None, **kwargs): """Image(s) plot defined in array(s) over input coordinates. Parameters: array_sub (np.array(1d or 2d) or list(np.array)): Each array (in a row or in the list) are values at each point in corresponding geo_coord that are ploted in one subplot. geo_coord (2d np.array or list(2d np.array)): (lat, lon) for each point in a row. If one provided, the same grid is used for all subplots. Otherwise provide as many as subplots in array_sub. var_name (str or list(str)): label to be shown in the colorbar. If one provided, the same is used for all subplots. Otherwise provide as many as subplots in array_sub. title (str or list(str)): subplot title. If one provided, the same is used for all subplots. Otherwise provide as many as subplots in array_sub. proj (ccrs): coordinate reference system used in coordinates smooth (bool, optional): smooth plot to RESOLUTIONxRESOLUTION. Default: True. kwargs (optional): arguments for pcolormesh matplotlib function. Returns: cartopy.mpl.geoaxes.GeoAxesSubplot Raises: ValueError """ # Generate array of values used in each subplot num_im, list_arr = _get_collection_arrays(array_sub) list_tit = to_list(num_im, title, 'title') list_name = to_list(num_im, var_name, 'var_name') list_coord = to_list(num_im, geo_coord, 'geo_coord') if 'vmin' not in kwargs: kwargs['vmin'] = np.min(array_sub) if 'vmax' not in kwargs: kwargs['vmax'] = np.max(array_sub) if axes is None: _, axes = make_map(num_im, proj=proj) axes_iter = axes if not isinstance(axes, np.ndarray): axes_iter = np.array([[axes]]) # Generate each subplot for array_im, axis, tit, name, coord in \ zip(list_arr, axes_iter.flatten(), list_tit, list_name, list_coord): if coord.shape[0] != array_im.size: raise ValueError("Size mismatch in input array: %s != %s." % \ (coord.shape[0], array_im.size)) is_reg, height, width = grid_is_regular(coord) extent = _get_borders(coord, proj=proj) if smooth or not is_reg: # Create regular grid where to interpolate the array grid_x, grid_y = np.mgrid[ extent[0] : extent[1] : complex(0, RESOLUTION), extent[2] : extent[3] : complex(0, RESOLUTION)] grid_im = griddata((coord[:, 1], coord[:, 0]), array_im, \ (grid_x, grid_y)) else: grid_x = coord[:, 1].reshape((width, height)).transpose() grid_y = coord[:, 0].reshape((width, height)).transpose() grid_im = np.array(array_im.reshape((width, height)).transpose()) if grid_y[0, 0] > grid_y[0, -1]: grid_y = np.flip(grid_y) grid_im = np.flip(grid_im, 1) grid_im = np.resize(grid_im, (height, width, 1)) # Add coastline to axis axis.set_extent((extent), proj) add_shapes(axis) # Create colormesh, colorbar and labels in axis cbax = make_axes_locatable(axis).append_axes('right', size="6.5%", \ pad=0.1, axes_class=plt.Axes) cbar = plt.colorbar(axis.pcolormesh(grid_x, grid_y, np.squeeze(grid_im), \ transform=proj, **kwargs), cax=cbax, orientation='vertical') cbar.set_label(name) axis.set_title(tit) return axes
def geo_im_from_array(array_sub, coord, var_name, title, proj=None, smooth=True, axes=None, figsize=(9, 13), adapt_fontsize=True, **kwargs): """Image(s) plot defined in array(s) over input coordinates. Parameters ---------- array_sub : np.array(1d or 2d) or list(np.array) Each array (in a row or in the list) are values at each point in corresponding geo_coord that are ploted in one subplot. coord : 2d np.array (lat, lon) for each point in a row. The same grid is used for all subplots. var_name : str or list(str) label to be shown in the colorbar. If one provided, the same is used for all subplots. Otherwise provide as many as subplots in array_sub. title : str or list(str) subplot title. If one provided, the same is used for all subplots. Otherwise provide as many as subplots in array_sub. proj : ccrs, optional coordinate reference system used in coordinates, by default None smooth : bool, optional smooth plot to RESOLUTIONxRESOLUTION, by default True axes : Axes or ndarray(Axes), optional by default None figsize : tuple, optional figure size for plt.subplots, by default (9, 13) adapt_fontsize : bool, optional If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise the default matplotlib font size is used. Default is True. **kwargs arbitrary keyword arguments for pcolormesh matplotlib function Returns ------- cartopy.mpl.geoaxes.GeoAxesSubplot Raises ------ ValueError """ # Generate array of values used in each subplot num_im, list_arr = _get_collection_arrays(array_sub) list_tit = to_list(num_im, title, 'title') list_name = to_list(num_im, var_name, 'var_name') list_coord = to_list(num_im, coord, 'geo_coord') is_reg, height, width = u_coord.grid_is_regular(coord) extent = _get_borders(coord, proj_limits=(-360, 360, -90, 90)) mid_lon = 0 if not proj: mid_lon = 0.5 * sum(extent[:2]) proj = ccrs.PlateCarree(central_longitude=mid_lon) if 'vmin' not in kwargs: kwargs['vmin'] = np.nanmin(array_sub) if 'vmax' not in kwargs: kwargs['vmax'] = np.nanmax(array_sub) if axes is None: if isinstance(proj, ccrs.PlateCarree): # use different projections for plot and data to shift the central lon in the plot xmin, xmax = u_coord.lon_bounds( np.concatenate([c[:, 1] for c in list_coord])) proj_plot = ccrs.PlateCarree(central_longitude=0.5 * (xmin + xmax)) _, axes, fontsize = make_map(num_im, proj=proj_plot, figsize=figsize, adapt_fontsize=adapt_fontsize) else: fontsize = None axes_iter = axes if not isinstance(axes, np.ndarray): axes_iter = np.array([[axes]]) if 'cmap' not in kwargs: kwargs['cmap'] = CMAP_RASTER # Generate each subplot for array_im, axis, tit, name in zip(list_arr, axes_iter.flatten(), list_tit, list_name): if coord.shape[0] != array_im.size: raise ValueError("Size mismatch in input array: %s != %s." % (coord.shape[0], array_im.size)) if smooth or not is_reg: # Create regular grid where to interpolate the array grid_x, grid_y = np.mgrid[ extent[0]:extent[1]:complex(0, RESOLUTION), extent[2]:extent[3]:complex(0, RESOLUTION)] grid_im = griddata((coord[:, 1], coord[:, 0]), array_im, (grid_x, grid_y)) else: grid_x = coord[:, 1].reshape((width, height)).transpose() grid_y = coord[:, 0].reshape((width, height)).transpose() grid_im = np.array(array_im.reshape((width, height)).transpose()) if grid_y[0, 0] > grid_y[0, -1]: grid_y = np.flip(grid_y) grid_im = np.flip(grid_im, 1) grid_im = np.resize(grid_im, (height, width, 1)) axis.set_extent( (extent[0] - mid_lon, extent[1] - mid_lon, extent[2], extent[3]), crs=proj) # Add coastline to axis add_shapes(axis) # Create colormesh, colorbar and labels in axis cbax = make_axes_locatable(axis).append_axes('right', size="6.5%", pad=0.1, axes_class=plt.Axes) img = axis.pcolormesh(grid_x - mid_lon, grid_y, np.squeeze(grid_im), transform=proj, **kwargs) cbar = plt.colorbar(img, cax=cbax, orientation='vertical') cbar.set_label(name) axis.set_title("\n".join(wrap(tit))) if fontsize: cbar.ax.tick_params(labelsize=fontsize) cbar.ax.yaxis.get_offset_text().set_fontsize(fontsize) for item in [axis.title, cbar.ax.xaxis.label, cbar.ax.yaxis.label]: item.set_fontsize(fontsize) plt.tight_layout() return axes
def shape_grid(self): """If the centroids lie on a regular grid, return its shape as a tuple of the form (n_lat, n_lon), that is, (height, width) """ assert grid_is_regular(self.coord), 'Coords are not on a regular grid' return (np.unique(self.lat).size, np.unique(self.lon).size)