def xr_errorbar(da_mean, da_std, huedim=None, xerr=None, label=None, capsize=3): """ Generates an error bar plot from xarray datarrays assumes da_mean and da_std are the same shape if huedim is unspecified the datarrays should be 1D if huedim is specified then datarrays should be 2D and the other dimension will be the xaxis """ fig, axes = plt.subplots(1, 1) if huedim == None: plotdim = list(da_mean.coords)[0] axes.errorbar(da_mean.coords[plotdim], da_mean.values, da_std.values, xerr=xerr, capsize=capsize, marker='o', label=label) else: plotdim = list(da_mean.isel({huedim: 0}).drop(huedim).coords)[0] for coord in da_mean.coords[huedim]: axes.errorbar(da_mean.sel({ huedim: coord }).dropna(plotdim, 'all').coords[plotdim], da_mean.sel({ huedim: coord }).dropna(plotdim, 'all').values, yerr=da_std.sel({ huedim: coord }).dropna(plotdim, 'all').values, xerr=xerr, capsize=capsize, marker='o', label=coord.item()) axes.legend(title=label_from_attrs(da_mean.coords[huedim])) axes.set_ylabel(label_from_attrs(da_mean)) axes.set_xlabel(label_from_attrs(da_mean.coords[plotdim])) return fig, axes
def hist( darray, figsize=None, size=None, aspect=None, ax=None, xincrease=None, yincrease=None, xscale=None, yscale=None, xticks=None, yticks=None, xlim=None, ylim=None, **kwargs, ): """ Histogram of DataArray Wraps :func:`matplotlib:matplotlib.pyplot.hist` Plots N dimensional arrays by first flattening the array. Parameters ---------- darray : DataArray Can be any dimension figsize : tuple, optional A tuple (width, height) of the figure in inches. Mutually exclusive with ``size`` and ``ax``. aspect : scalar, optional Aspect ratio of plot, so that ``aspect * size`` gives the width in inches. Only used if a ``size`` is provided. size : scalar, optional If provided, create a new figure for the plot with the given size. Height (in inches) of each plot. See also: ``aspect``. ax : matplotlib axes object, optional Axis on which to plot this figure. By default, use the current axis. Mutually exclusive with ``size`` and ``figsize``. **kwargs : optional Additional keyword arguments to matplotlib.pyplot.hist """ ax = get_axis(figsize, size, aspect, ax) no_nan = np.ravel(darray.values) no_nan = no_nan[pd.notnull(no_nan)] primitive = ax.hist(no_nan, **kwargs) ax.set_title("Histogram") ax.set_xlabel(label_from_attrs(darray)) _update_axes(ax, xincrease, yincrease, xscale, yscale, xticks, yticks, xlim, ylim) return primitive
def newplotfunc( darray, x=None, y=None, projection="polar", show_radius_label=True, show_direction_label=False, as_period=False, as_log10=True, figsize=None, size=None, aspect=None, ax=None, row=None, col=None, col_wrap=None, xincrease=True, yincrease=True, add_colorbar=None, add_labels=True, vmin=None, vmax=None, cmap=None, center=None, robust=False, extend=None, levels=None, infer_intervals=None, colors=None, subplot_kws=None, cbar_ax=None, cbar_kwargs=None, xscale=None, yscale=None, xticks=None, yticks=None, xlim=None, ylim=None, norm=None, **kwargs ): # All 2d plots in xarray share this function signature. # Method signature below should be consistent. # Default colormap if cmap is None: try: from cmocean import cm cmap = cm.thermal except: warnings.warn( "cmocean not installed, cannot set default colormap cmocean.cm.thermal" ) pass # Prepare dataarray for polar plotting if projection == "polar": darray = _wrap_and_sort_directions(darray) darray = _freq_or_period_clean_attributes(darray, as_period=as_period) if np.diff(darray.get_axis_num([attrs.FREQNAME, attrs.DIRNAME])) < 0: darray = _transpose_spectral_coordinates(darray) # Log values make it easier to view multiple wave systems in spectrum # Try and ensure that log won't be calculated twice if facet grids if as_log10: if not (darray.min() == -5 and 0 not in darray.values): darray.values = np.log10( darray.where(darray.values > 0).fillna(0.00001) ) # Decide on a default for the colorbar before facetgrids if add_colorbar is None: add_colorbar = plotfunc.__name__ != "contour" imshow_rgb = plotfunc.__name__ == "imshow" and darray.ndim == ( 3 + (row is not None) + (col is not None) ) if imshow_rgb: # Don't add a colorbar when showing an image with explicit colors add_colorbar = False # Matplotlib does not support normalising RGB data, so do it here. # See eg. https://github.com/matplotlib/matplotlib/pull/10220 if robust or vmax is not None or vmin is not None: darray = _rescale_imshow_rgb(darray, vmin, vmax, robust) vmin, vmax, robust = None, None, False # Handle facetgrids first if row or col: allargs = locals().copy() del allargs["darray"] del allargs["imshow_rgb"] allargs.update(allargs.pop("kwargs")) # Need the decorated plotting function allargs["plotfunc"] = globals()[plotfunc.__name__] # subplot_kws to allow polar facet grids subplot_kws = allargs.pop("subplot_kws", {}) or {} subplot_kws.update({"projection": projection}) allargs["subplot_kws"] = subplot_kws # Removed local variables to avoid warnings allargs.pop("cm", None) allargs.pop("projection", None) return _easy_facetgrid(darray, kind="dataarray", **allargs) plt = import_matplotlib_pyplot() rgb = kwargs.pop("rgb", None) if rgb is not None and plotfunc.__name__ != "imshow": raise ValueError('The "rgb" keyword is only valid for imshow()') elif rgb is not None and not imshow_rgb: raise ValueError( 'The "rgb" keyword is only valid for imshow()' "with a three-dimensional array (per facet)" ) xlab, ylab = _infer_xy_labels( darray=darray, x=x, y=y, imshow=imshow_rgb, rgb=rgb ) # better to pass the ndarrays directly to plotting functions xval = darray[xlab].values yval = darray[ylab].values # check if we need to broadcast one dimension if xval.ndim < yval.ndim: xval = np.broadcast_to(xval, yval.shape) if yval.ndim < xval.ndim: yval = np.broadcast_to(yval, xval.shape) # May need to transpose for correct x, y labels # xlab may be the name of a coord, we have to check for dim names if imshow_rgb: # For RGB[A] images, matplotlib requires the color dimension # to be last. In Xarray the order should be unimportant, so # we transpose to (y, x, color) to make this work. yx_dims = (ylab, xlab) dims = yx_dims + tuple(d for d in darray.dims if d not in yx_dims) if dims != darray.dims: darray = darray.transpose(*dims, transpose_coords=True) elif darray[xlab].dims[-1] == darray.dims[0]: darray = darray.transpose(transpose_coords=True) # Pass the data as a masked ndarray too zval = darray.to_masked_array(copy=False) # Replace pd.Intervals if contained in xval or yval. xplt, xlab_extra = _resolve_intervals_2dplot(xval, plotfunc.__name__) yplt, ylab_extra = _resolve_intervals_2dplot(yval, plotfunc.__name__) # Convert coordinates if polar if projection == "polar": xplt, yplt = np.meshgrid(np.deg2rad(xplt), yplt) _ensure_plottable(xplt, yplt) cmap_params, cbar_kwargs = _process_cmap_cbar_kwargs( plotfunc, zval.data, **locals() ) if "contour" in plotfunc.__name__: # extend is a keyword argument only for contour and contourf, but # passing it to the colorbar is sufficient for imshow and # pcolormesh kwargs["extend"] = cmap_params["extend"] kwargs["levels"] = cmap_params["levels"] # if colors == a single color, matplotlib draws dashed negative # contours. we lose this feature if we pass cmap and not colors if isinstance(colors, str): cmap_params["cmap"] = None kwargs["colors"] = colors if "pcolormesh" == plotfunc.__name__: kwargs["infer_intervals"] = infer_intervals if "imshow" == plotfunc.__name__ and isinstance(aspect, str): # forbid usage of mpl strings raise ValueError( "plt.imshow's `aspect` kwarg is not available " "in xarray" ) ax = get_axis(figsize, size, aspect, ax, subplot_kw={"projection": projection}) primitive = plotfunc( xplt, yplt, zval, ax=ax, cmap=cmap_params["cmap"], vmin=cmap_params["vmin"], vmax=cmap_params["vmax"], norm=cmap_params["norm"], **kwargs ) # Label the plot with metadata if add_labels: ax.set_xlabel(label_from_attrs(darray[xlab], xlab_extra)) ax.set_ylabel(label_from_attrs(darray[ylab], ylab_extra)) ax.set_title(darray._title_for_slice()) # Make polar axis Nautical if projection == "polar": ax.set_theta_zero_location("N") ax.set_theta_direction(-1) if not show_direction_label: ax.set_xticklabels([]) if not show_radius_label: ax.set_yticklabels([]) if add_colorbar: if add_labels and "label" not in cbar_kwargs: cbar_kwargs["label"] = label_from_attrs(darray) cbar = _add_colorbar(primitive, ax, cbar_ax, cbar_kwargs, cmap_params) elif cbar_ax is not None or cbar_kwargs: # inform the user about keywords which aren't used raise ValueError( "cbar_ax and cbar_kwargs can't be used with add_colorbar=False." ) # origin kwarg overrides yincrease if "origin" in kwargs: yincrease = None _update_axes( ax, xincrease, yincrease, xscale, yscale, xticks, yticks, xlim, ylim ) # Rotate dates on xlabels # Do this without calling autofmt_xdate so that x-axes ticks # on other subplots (if any) are not deleted. # https://stackoverflow.com/questions/17430105/autofmt-xdate-deletes-x-axis-labels-of-all-subplots if np.issubdtype(xplt.dtype, np.datetime64): for xlabels in ax.get_xticklabels(): xlabels.set_rotation(30) xlabels.set_ha("right") return primitive
def newplotfunc( darray, x=None, y=None, figsize=None, size=None, aspect=None, ax=None, row=None, col=None, col_wrap=None, xincrease=True, yincrease=True, add_colorbar=None, add_labels=True, vmin=None, vmax=None, cmap=None, center=None, robust=False, extend=None, levels=None, infer_intervals=None, colors=None, subplot_kws=None, cbar_ax=None, cbar_kwargs=None, xscale=None, yscale=None, xticks=None, yticks=None, xlim=None, ylim=None, norm=None, **kwargs, ): # All 2d plots in xarray share this function signature. # Method signature below should be consistent. # Decide on a default for the colorbar before facetgrids if add_colorbar is None: add_colorbar = plotfunc.__name__ != "contour" imshow_rgb = plotfunc.__name__ == "imshow" and darray.ndim == ( 3 + (row is not None) + (col is not None) ) if imshow_rgb: # Don't add a colorbar when showing an image with explicit colors add_colorbar = False # Matplotlib does not support normalising RGB data, so do it here. # See eg. https://github.com/matplotlib/matplotlib/pull/10220 if robust or vmax is not None or vmin is not None: darray = _rescale_imshow_rgb(darray, vmin, vmax, robust) vmin, vmax, robust = None, None, False # Handle facetgrids first if row or col: allargs = locals().copy() del allargs["darray"] del allargs["imshow_rgb"] allargs.update(allargs.pop("kwargs")) # Need the decorated plotting function allargs["plotfunc"] = globals()[plotfunc.__name__] return _easy_facetgrid(darray, kind="dataarray", **allargs) plt = import_matplotlib_pyplot() rgb = kwargs.pop("rgb", None) if rgb is not None and plotfunc.__name__ != "imshow": raise ValueError('The "rgb" keyword is only valid for imshow()') elif rgb is not None and not imshow_rgb: raise ValueError( 'The "rgb" keyword is only valid for imshow()' "with a three-dimensional array (per facet)" ) xlab, ylab = _infer_xy_labels( darray=darray, x=x, y=y, imshow=imshow_rgb, rgb=rgb ) # better to pass the ndarrays directly to plotting functions xval = darray[xlab].values yval = darray[ylab].values # check if we need to broadcast one dimension if xval.ndim < yval.ndim: xval = np.broadcast_to(xval, yval.shape) if yval.ndim < xval.ndim: yval = np.broadcast_to(yval, xval.shape) # May need to transpose for correct x, y labels # xlab may be the name of a coord, we have to check for dim names if imshow_rgb: # For RGB[A] images, matplotlib requires the color dimension # to be last. In Xarray the order should be unimportant, so # we transpose to (y, x, color) to make this work. yx_dims = (ylab, xlab) dims = yx_dims + tuple(d for d in darray.dims if d not in yx_dims) if dims != darray.dims: darray = darray.transpose(*dims, transpose_coords=True) elif darray[xlab].dims[-1] == darray.dims[0]: darray = darray.transpose(transpose_coords=True) # Pass the data as a masked ndarray too zval = darray.to_masked_array(copy=False) # Replace pd.Intervals if contained in xval or yval. xplt, xlab_extra = _resolve_intervals_2dplot(xval, plotfunc.__name__) yplt, ylab_extra = _resolve_intervals_2dplot(yval, plotfunc.__name__) _ensure_plottable(xplt, yplt) kwargs = locals() zdat = zval.data cmap_params, cbar_kwargs = _process_cmap_cbar_kwargs( plotfunc, zdat, **kwargs ) if "contour" in plotfunc.__name__: # extend is a keyword argument only for contour and contourf, but # passing it to the colorbar is sufficient for imshow and # pcolormesh kwargs["extend"] = cmap_params["extend"] kwargs["levels"] = cmap_params["levels"] # if colors == a single color, matplotlib draws dashed negative # contours. we lose this feature if we pass cmap and not colors if isinstance(colors, str): cmap_params["cmap"] = None kwargs["colors"] = colors if "pcolormesh" == plotfunc.__name__: kwargs["infer_intervals"] = infer_intervals if "imshow" == plotfunc.__name__ and isinstance(aspect, str): # forbid usage of mpl strings raise ValueError( "plt.imshow's `aspect` kwarg is not available " "in xarray" ) ax = get_axis(figsize, size, aspect, ax) plot_args = { key:value for key,value in kwargs.items() if value is not None } plot_args.update( ax=ax, cmap=cmap_params["cmap"], vmin=cmap_params["vmin"], vmax=cmap_params["vmax"], norm=cmap_params["norm"] ) primitive = plotfunc( xplt, yplt, zval, **plot_args ) # Label the plot with metadata if add_labels: ax.set_xlabel(label_from_attrs(darray[xlab], xlab_extra)) ax.set_ylabel(label_from_attrs(darray[ylab], ylab_extra)) ax.set_title(darray._title_for_slice()) if add_colorbar: if add_labels and "label" not in cbar_kwargs: cbar_kwargs["label"] = label_from_attrs(darray) cbar = _add_colorbar(primitive, ax, cbar_ax, cbar_kwargs, cmap_params) elif cbar_ax is not None or cbar_kwargs: # inform the user about keywords which aren't used raise ValueError( "cbar_ax and cbar_kwargs can't be used with " "add_colorbar=False." ) # origin kwarg overrides yincrease if "origin" in kwargs: yincrease = None _update_axes( ax, xincrease, yincrease, xscale, yscale, xticks, yticks, xlim, ylim ) # Rotate dates on xlabels # Do this without calling autofmt_xdate so that x-axes ticks # on other subplots (if any) are not deleted. # https://stackoverflow.com/questions/17430105/autofmt-xdate-deletes-x-axis-labels-of-all-subplots if np.issubdtype(xplt.dtype, np.datetime64): for xlabels in ax.get_xticklabels(): xlabels.set_rotation(30) xlabels.set_ha("right") return primitive
def _infer_line_data(darray, x, y, hue): error_msg = "must be either None or one of ({:s})".format( ", ".join([repr(dd) for dd in darray.dims]) ) ndims = len(darray.dims) if x is not None and x not in darray.dims and x not in darray.coords: raise ValueError("x " + error_msg) if y is not None and y not in darray.dims and y not in darray.coords: raise ValueError("y " + error_msg) if x is not None and y is not None: raise ValueError("You cannot specify both x and y kwargs" "for line plots.") if ndims == 1: huename = None hueplt = None huelabel = "" if x is not None: xplt = darray[x] yplt = darray elif y is not None: xplt = darray yplt = darray[y] else: # Both x & y are None dim = darray.dims[0] xplt = darray[dim] yplt = darray else: if x is None and y is None and hue is None: raise ValueError("For 2D inputs, please" "specify either hue, x or y.") if y is None: xname, huename = _infer_xy_labels(darray=darray, x=x, y=hue) xplt = darray[xname] if xplt.ndim > 1: if huename in darray.dims: otherindex = 1 if darray.dims.index(huename) == 0 else 0 otherdim = darray.dims[otherindex] yplt = darray.transpose(otherdim, huename, transpose_coords=False) xplt = xplt.transpose(otherdim, huename, transpose_coords=False) else: raise ValueError( "For 2D inputs, hue must be a dimension" " i.e. one of " + repr(darray.dims) ) else: (xdim,) = darray[xname].dims (huedim,) = darray[huename].dims yplt = darray.transpose(xdim, huedim) else: yname, huename = _infer_xy_labels(darray=darray, x=y, y=hue) yplt = darray[yname] if yplt.ndim > 1: if huename in darray.dims: otherindex = 1 if darray.dims.index(huename) == 0 else 0 otherdim = darray.dims[otherindex] xplt = darray.transpose(otherdim, huename, transpose_coords=False) else: raise ValueError( "For 2D inputs, hue must be a dimension" " i.e. one of " + repr(darray.dims) ) else: (ydim,) = darray[yname].dims (huedim,) = darray[huename].dims xplt = darray.transpose(ydim, huedim) huelabel = label_from_attrs(darray[huename]) hueplt = darray[huename] xlabel = label_from_attrs(xplt) ylabel = label_from_attrs(yplt) return xplt, yplt, hueplt, xlabel, ylabel, huelabel