def test_list_wrong_length_fail(self): """When input is list of neither expected size nor one, fail.""" num_exp = 3 values = ['1', '2'] val_name = 'values' with self.assertRaises(ValueError) as cm: to_list(num_exp, values, val_name) self.assertIn("Provide one or 3 values.", str(cm.exception))
def test_list_wrong_length_fail(self): """When input is list of neither expected size nor one, fail.""" num_exp = 3 values = ['1', '2'] val_name = 'values' with self.assertLogs('climada.util.files_handler', level='ERROR') as cm: to_list(num_exp, values, val_name) self.assertIn("Provide one or 3 values.", cm.output[0])
def test_one_to_list(self): """When input is a string or list with one element, it returns a list with the expected number of elments repeated""" num_exp = 3 values = 'hi' val_name = 'values' out = to_list(num_exp, values, val_name) self.assertEqual(['hi', 'hi', 'hi'], out) values = ['ha'] out = to_list(num_exp, values, val_name) self.assertEqual(['ha', 'ha', 'ha'], out)
def test_identity_pass(self): """Returns the same list if its length is correct.""" num_exp = 3 values = ['hi', 'ho', 'ha'] val_name = 'values' out = to_list(num_exp, values, val_name) self.assertEqual(values, out)
def read(self, files, descriptions='', var_names=None): """ Read and check centroids. Parameters: files (str or list(str)): absolute file name(s) or folder name containing the files to read descriptions (str or list(str), optional): one description of the data or a description of each data file var_names (dict or list(dict), default): name of the variables in the file (default: check def_source_vars() function) Raises: TypeError, ValueError """ all_files = get_file_names(files) desc_list = to_list(len(all_files), descriptions, 'descriptions') var_list = to_list(len(all_files), var_names, 'var_names') self.clear() for file, desc, var in zip(all_files, desc_list, var_list): self.append(Centroids._read_one(file, desc, var))
def geo_bin_from_array(array_sub, geo_coord, var_name, title, pop_name=True,\ buffer=BUFFER, extend='neither', \ proj=ccrs.PlateCarree(), axes=None, **kwargs): """Plot array values binned 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 binned 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. pop_name (bool, optional): add names of the populated places. buffer (float, optional): border to add to coordinates extend (str, optional): extend border colorbar with arrows. [ 'neither' | 'both' | 'min' | 'max' ] proj (ccrs): coordinate reference system used in coordinates kwargs (optional): arguments for hexbin 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 'cmap' not in kwargs: kwargs['cmap'] = 'Wistia' if axes is None: _, axes = make_map(num_im, proj=proj) 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)) # Binned image with coastlines extent = _get_borders(coord, buffer, proj) axis.set_extent((extent), proj) add_shapes(axis) if pop_name: add_populated_places(axis, extent, proj) if 'gridsize' not in kwargs: kwargs['gridsize'] = min(int(array_im.size/2), MAX_BINS) hex_bin = axis.hexbin(coord[:, 1], coord[:, 0], C=array_im, \ transform=proj, **kwargs) # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes('right', size="6.5%", \ pad=0.1, axes_class=plt.Axes) cbar = plt.colorbar(hex_bin, cax=cbax, orientation='vertical', extend=extend) cbar.set_label(name) axis.set_title(tit) return axes
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 _plot_scattered_data(method, array_sub, geo_coord, var_name, title, pop_name=False, buffer=BUFFER, extend='neither', proj=ccrs.PlateCarree(), shapes=True, axes=None, figsize=(9, 13), adapt_fontsize=True, **kwargs): """Function for internal use in `geo_scatter_from_array` (when called with method="scatter") and `geo_bin_from_array` (when called with method="hexbin"). See the docstrings of the respective functions for more information on the parameters.""" # 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 'cmap' not in kwargs: kwargs['cmap'] = CMAP_EXPOSURES if axes is None: proj_plot = proj 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]]) # 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)) # Binned image with coastlines if isinstance(proj, ccrs.PlateCarree): xmin, ymin, xmax, ymax = u_coord.latlon_bounds(coord[:, 0], coord[:, 1], buffer=buffer) extent = (xmin, xmax, ymin, ymax) else: extent = _get_borders(coord, buffer=buffer, proj_limits=proj.x_limits + proj.y_limits) axis.set_extent((extent), proj) if shapes: add_shapes(axis) if pop_name: add_populated_places(axis, extent, proj, fontsize) if method == "hexbin": if 'gridsize' not in kwargs: kwargs['gridsize'] = min(int(array_im.size / 2), MAX_BINS) mappable = axis.hexbin(coord[:, 1], coord[:, 0], C=array_im, transform=proj, **kwargs) else: mappable = axis.scatter(coord[:, 1], coord[:, 0], c=array_im, transform=proj, **kwargs) # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes('right', size="6.5%", pad=0.1, axes_class=plt.Axes) cbar = plt.colorbar(mappable, cax=cbax, orientation='vertical', extend=extend) 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 _plot_exc_prob( self, run_datetime, threshold, title, cbar_label, proj=ccrs.PlateCarree(), polygon_file=None, polygon_file_crs="epsg:4326", mask=None, figsize=(9, 13), adapt_fontsize=True, ): """plot the probability of reaching a threshold""" # select hazard with run_datetime # pylint: disable=protected-access if run_datetime is None: run_datetime = self.run_datetime[0] haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0] extend = "neither" value = np.squeeze( np.asarray( (self._impact[haz_ind].imp_mat > threshold).sum(axis=0) / self._impact[haz_ind].event_id.size)) if mask is not None: value[np.invert(mask)] = np.nan coord = self._impact[haz_ind].coord_exp # Generate array of values used in each subplot array_sub = value shapes = True if not polygon_file: shapes = False var_name = cbar_label geo_coord = coord num_im, list_arr = u_plot._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") kwargs = dict() kwargs["cmap"] = CMAP_WARNPROB kwargs["s"] = 5 kwargs["marker"] = "," kwargs["norm"] = BoundaryNorm(np.linspace(0, 1, 11), CMAP_WARNPROB.N, clip=True) # Generate each subplot fig, axis_sub, _fontsize = u_plot.make_map( num_im, proj=proj, figsize=figsize, adapt_fontsize=adapt_fontsize) if not isinstance(axis_sub, np.ndarray): axis_sub = np.array([[axis_sub]]) fig.set_size_inches(9, 8) for array_im, axis, tit, name, coord in zip(list_arr, axis_sub.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)) hex_bin = axis.scatter(coord[:, 1], coord[:, 0], c=array_im, transform=ccrs.PlateCarree(), **kwargs) if shapes: # add warning regions shp = shapereader.Reader(polygon_file) transformer = pyproj.Transformer.from_crs( polygon_file_crs, self._impact[haz_ind].crs, always_xy=True) for geometry, _ in zip(shp.geometries(), shp.records()): geom2 = shapely.ops.transform(transformer.transform, geometry) axis.add_geometries( [geom2], crs=ccrs.PlateCarree(), facecolor="none", edgecolor="gray", ) # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes("bottom", size="6.5%", pad=0.3, axes_class=plt.Axes) cbar = plt.colorbar(hex_bin, cax=cbax, orientation="horizontal", extend=extend) cbar.set_label(name) title_position = { "model_text": [0.02, 0.94], "explain_text": [0.02, 0.9], "event_day": [0.98, 0.94], "run_start": [0.98, 0.9], } left_right = { "model_text": "left", "explain_text": "left", "event_day": "right", "run_start": "right", } color = { "model_text": "k", "explain_text": "k", "event_day": "r", "run_start": "k", } for t_i in tit: plt.figtext( title_position[t_i][0], title_position[t_i][1], tit[t_i], fontsize="xx-large", color=color[t_i], ha=left_right[t_i], ) extent = u_plot._get_borders(coord) axis.set_extent((extent), ccrs.PlateCarree()) fig.tight_layout() return fig, axis_sub
def _plot_imp_map( self, run_datetime, title, cbar_label, polygon_file=None, polygon_file_crs="epsg:4326", proj=ccrs.PlateCarree(), figsize=(9, 13), adapt_fontsize=True, ): # select hazard with run_datetime # pylint: disable=protected-access if run_datetime is None: run_datetime = self.run_datetime[0] haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0] # tryout new plot with right projection extend = "neither" value = self._impact[haz_ind].eai_exp # value[np.invert(mask)] = np.nan coord = self._impact[haz_ind].coord_exp # Generate array of values used in each subplot array_sub = value shapes = True if not polygon_file: shapes = False var_name = cbar_label geo_coord = coord num_im, list_arr = u_plot._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") kwargs = dict() kwargs["cmap"] = CMAP_IMPACT kwargs["s"] = 5 kwargs["marker"] = "," kwargs["norm"] = BoundaryNorm( np.append( np.append([0], [10**x for x in np.arange(0, 2.9, 2.9 / 9)]), [10**x for x in np.arange(3, 7, 4 / 90)], ), CMAP_IMPACT.N, clip=True, ) # Generate each subplot fig, axis_sub, _fontsize = u_plot.make_map( num_im, proj=proj, figsize=figsize, adapt_fontsize=adapt_fontsize) if not isinstance(axis_sub, np.ndarray): axis_sub = np.array([[axis_sub]]) fig.set_size_inches(9, 8) for array_im, axis, tit, name, coord in zip(list_arr, axis_sub.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)) # Binned image with coastlines extent = u_plot._get_borders(coord) axis.set_extent((extent), ccrs.PlateCarree()) hex_bin = axis.scatter(coord[:, 1], coord[:, 0], c=array_im, transform=ccrs.PlateCarree(), **kwargs) if shapes: # add warning regions shp = shapereader.Reader(polygon_file) transformer = pyproj.Transformer.from_crs( polygon_file_crs, self._impact[haz_ind].crs, always_xy=True) for geometry, _ in zip(shp.geometries(), shp.records()): geom2 = shapely.ops.transform(transformer.transform, geometry) axis.add_geometries( [geom2], crs=ccrs.PlateCarree(), facecolor="none", edgecolor="gray", ) else: # add country boundaries u_plot.add_shapes(axis) # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes("bottom", size="6.5%", pad=0.3, axes_class=plt.Axes) cbar = plt.colorbar(hex_bin, cax=cbax, orientation="horizontal", extend=extend) cbar.set_label(name) cbar.formatter.set_scientific(False) cbar.set_ticks([0, 1000, 10000, 100000, 1000000]) cbar.set_ticklabels( ["0", "1 000", "10 000", "100 000", "1 000 000"]) title_position = { "model_text": [0.02, 0.85], "explain_text": [0.02, 0.81], "event_day": [0.98, 0.85], "run_start": [0.98, 0.81], } left_right = { "model_text": "left", "explain_text": "left", "event_day": "right", "run_start": "right", } color = { "model_text": "k", "explain_text": "k", "event_day": "r", "run_start": "k", } for t_i in tit: plt.figtext( title_position[t_i][0], title_position[t_i][1], tit[t_i], fontsize="xx-large", color=color[t_i], ha=left_right[t_i], ) fig.tight_layout() fig.subplots_adjust(top=0.8) return fig, axis_sub
def _plot_exc_prob(self, run_datetime, threshold, title, cbar_label, proj=ccrs.PlateCarree(), polygon_file=None, polygon_file_crs='epsg:4326', mask=None, figsize=(9, 13)): """ plot the probability of reaching a threshold """ # select hazard with run_datetime if run_datetime is None: run_datetime = self.run_datetime[0] haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0] extend = 'neither' value = np.squeeze( np.asarray( (self._impact[haz_ind].imp_mat > threshold).sum(axis=0) / self._impact[haz_ind].event_id.size)) if mask is not None: value[np.invert(mask)] = np.nan coord = self._impact[haz_ind].coord_exp # Generate array of values used in each subplot array_sub = value shapes = True if not polygon_file: shapes = False var_name = cbar_label geo_coord = coord num_im, list_arr = u_plot._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') kwargs = dict() kwargs['cmap'] = CMAP_WARNPROB kwargs['s'] = 5 kwargs['marker'] = ',' kwargs['norm'] = BoundaryNorm(np.linspace(0, 1, 11), CMAP_WARNPROB.N, clip=True) # Generate each subplot fig, axis_sub = u_plot.make_map(num_im, proj=proj, figsize=figsize) if not isinstance(axis_sub, np.ndarray): axis_sub = np.array([[axis_sub]]) fig.set_size_inches(9, 8) for array_im, axis, tit, name, coord in zip(list_arr, axis_sub.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)) hex_bin = axis.scatter(coord[:, 1], coord[:, 0], c=array_im, \ transform=ccrs.PlateCarree(), **kwargs) if shapes: # add warning regions shp = shapereader.Reader(polygon_file) transformer = pyproj.Transformer.from_crs( polygon_file_crs, self._impact[haz_ind].crs, always_xy=True) for geometry, _ in zip(shp.geometries(), shp.records()): geom2 = shapely.ops.transform(transformer.transform, geometry) axis.add_geometries([geom2], crs=ccrs.PlateCarree(), facecolor='', \ edgecolor='gray') # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes('bottom', size="6.5%", \ pad=0.3, axes_class=plt.Axes) cbar = plt.colorbar(hex_bin, cax=cbax, orientation='horizontal', extend=extend) cbar.set_label(name) title_position = { 'model_text': [0.02, 0.94], 'explain_text': [0.02, 0.9], 'event_day': [0.98, 0.94], 'run_start': [0.98, 0.9] } left_right = { 'model_text': 'left', 'explain_text': 'left', 'event_day': 'right', 'run_start': 'right' } color = { 'model_text': 'k', 'explain_text': 'k', 'event_day': 'r', 'run_start': 'k' } for t_i in tit: plt.figtext(title_position[t_i][0], title_position[t_i][1], tit[t_i], fontsize='xx-large', color=color[t_i], ha=left_right[t_i]) extent = u_plot._get_borders(coord) axis.set_extent((extent), ccrs.PlateCarree()) return fig, axis_sub
def geo_bin_from_array(array_sub, geo_coord, var_name, title, pop_name=True, buffer=BUFFER, extend='neither', proj=ccrs.PlateCarree(), axes=None, figsize=(9, 13), **kwargs): """Plot array values binned 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 binned 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. pop_name : bool, optional add names of the populated places, by default True buffer : float, optional border to add to coordinates, by default BUFFER extend : str, optional extend border colorbar with arrows. [ 'neither' | 'both' | 'min' | 'max' ], by default 'neither' proj : ccrs, optional coordinate reference system of the given data, by default ccrs.PlateCarree() axes : Axes or ndarray(Axes), optional by default None figsize : tuple, optional figure size for plt.subplots, by default (9, 13) **kwargs arbitrary keyword arguments for hexbin 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 'cmap' not in kwargs: kwargs['cmap'] = 'Wistia' if axes is None: proj_plot = proj 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 = make_map(num_im, proj=proj_plot, figsize=figsize) 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)) # Binned image with coastlines if isinstance(proj, ccrs.PlateCarree): xmin, ymin, xmax, ymax = u_coord.latlon_bounds(coord[:, 0], coord[:, 1], buffer=buffer) extent = (xmin, xmax, ymin, ymax) else: extent = _get_borders(coord, buffer=buffer, proj_limits=proj.x_limits + proj.y_limits) axis.set_extent((extent), proj) add_shapes(axis) if pop_name: add_populated_places(axis, extent, proj) if 'gridsize' not in kwargs: kwargs['gridsize'] = min(int(array_im.size / 2), MAX_BINS) hex_bin = axis.hexbin(coord[:, 1], coord[:, 0], C=array_im, transform=proj, **kwargs) # Create colorbar in this axis cbax = make_axes_locatable(axis).append_axes('right', size="6.5%", pad=0.1, axes_class=plt.Axes) cbar = plt.colorbar(hex_bin, cax=cbax, orientation='vertical', extend=extend) cbar.set_label(name) axis.set_title(tit) return axes