Esempio n. 1
0
def draw_heatmap(colors: Union[pd.DataFrame, pd.Series],
                 axes: mpl.axes.Axes,
                 axis=0,
                 index_order: Union[Sequence[Union[str, int]], None] = None,
                 **kwargs):
    """

    :param colors: pd.Series or pd.DataFrame
    :param axes: matplotlib axes object
    :param axis: 0 or 1
    :param index_order: the order of colors
    :param kwargs: passed to `axes.pcolormesh`
    :return:
    """
    colors = colors.copy()
    # if index_order is not None:
    #     index_order = list(index_order)[::-1]
    colors, labels = _process_colors(colors, index_order)
    matrix, cmap = _color_list_to_matrix_and_cmap(colors, axis=axis)
    axes.pcolormesh(matrix, cmap=cmap, **kwargs)
    if axis == 1:
        axes.set_yticks(_determine_ticks(labels))
        axes.set_yticklabels(labels)
        _ = axes.set_xticks([])
    elif axis == 0:
        axes.set_xticks(_determine_ticks(labels))
        axes.set_xticklabels(labels, rotation=90)
        _ = axes.set_yticks([])
    else:
        raise ValueError('axis must be 0 or 1.')
    for item in ['left', 'right', 'bottom', 'top']:
        axes.spines[item].set_visible(False)
Esempio n. 2
0
def plot_on_a_plain_grid(x: np.ndarray, y: np.ndarray, z: np.ndarray,
                         ax: matplotlib.axes.Axes) -> matplotlib.axes.Axes:
    """
    Plot a heatmap of z using x and y as axes. Assumes that the data
    are rectangular, i.e. that x and y together describe a rectangular
    grid. The arrays of x and y need not be sorted in any particular
    way, but data must belong together such that z[n] has x[n] and
    y[n] as setpoints.  The setpoints need not be equidistantly
    spaced, but linear interpolation is used to find the edges of the
    plotted squares.

    Args:
        x: The x values
        y: The y values
        z: The z values

    Returns:
        The matplotlib figure handle
    """

    xrow, yrow, z_to_plot = reshape_2D_data(x, y, z)

    # we use a general edge calculator,
    # in the case of non-equidistantly spaced data
    # TODO: is this appropriate for a log ax?
    dxs = np.diff(xrow) / 2
    dys = np.diff(yrow) / 2
    x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]), xrow[:-1] + dxs,
                              np.array([xrow[-1] + dxs[-1]])))
    y_edges = np.concatenate((np.array([yrow[0] - dys[0]]), yrow[:-1] + dys,
                              np.array([yrow[-1] + dys[-1]])))

    ax.pcolormesh(x_edges, y_edges, np.ma.masked_invalid(z_to_plot))

    return ax
Esempio n. 3
0
def plot_sensor_hit_histogram(axes: mpl.axes.Axes, hist: np.ndarray,
                              x_edges: np.ndarray, y_edges: np.ndarray):
    """ plot the hitmap of the sensor into a given axes
.
    plots the hitmap of the sensor into a provided axes instance and
    annotates the plot accordingly
    """
    cmap = cm.get_cmap('viridis', 1024)
    axes.set_title("Sensor Hitmap")
    axes.set_xlabel("x [mm]")
    axes.set_ylabel("y [mm]")
    axes.pcolormesh(x_edges, y_edges, hist, cmap=cmap)
Esempio n. 4
0
    def _do_mesh(self, a: mpl.axes.Axes, x: np.ndarray, y: np.ndarray):
        """Create density plot

        Parameters
        ----------
        a
            Axes to draw on
        x, y
            data
        """
        grid = np.array(
            np.meshgrid(np.linspace(*self._bounds[0], 200),
                        np.linspace(*self._bounds[1], 200)))
        grid_flat = np.reshape(grid, (2, -1))
        c = self._calc_kde(x, y, *grid_flat).reshape(grid.shape[1:])
        a.pcolormesh(*grid, c)
Esempio n. 5
0
def plot_on_a_plain_grid(x: np.ndarray,
                         y: np.ndarray,
                         z: np.ndarray,
                         ax: matplotlib.axes.Axes,
                         colorbar: matplotlib.colorbar.Colorbar = None,
                         **kwargs) -> AxesTuple:
    """
    Plot a heatmap of z using x and y as axes. Assumes that the data
    are rectangular, i.e. that x and y together describe a rectangular
    grid. The arrays of x and y need not be sorted in any particular
    way, but data must belong together such that z[n] has x[n] and
    y[n] as setpoints.  The setpoints need not be equidistantly
    spaced, but linear interpolation is used to find the edges of the
    plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used
    for the plotting. By default the data in any vector plot will be rasterized
    if more that 5000 points are supplied. This can be overridden
    by supplying the `rasterized` kwarg.

    Args:
        x: The x values
        y: The y values
        z: The z values
        ax: The axis to plot onto
        colorbar: a colorbar to reuse the axis for

    Returns:
        The matplotlib axes handle for plot and colorbar
    """

    xrow, yrow, z_to_plot = reshape_2D_data(x, y, z)

    # we use a general edge calculator,
    # in the case of non-equidistantly spaced data
    # TODO: is this appropriate for a log ax?
    dxs = np.diff(xrow) / 2
    dys = np.diff(yrow) / 2
    x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]), xrow[:-1] + dxs,
                              np.array([xrow[-1] + dxs[-1]])))
    y_edges = np.concatenate((np.array([yrow[0] - dys[0]]), yrow[:-1] + dys,
                              np.array([yrow[-1] + dys[-1]])))
    if 'rasterized' in kwargs.keys():
        rasterized = kwargs.pop('rasterized')
    else:
        rasterized = len(x_edges) * len(y_edges) \
                      > qc.config.plotting.rasterize_threshold

    colormesh = ax.pcolormesh(x_edges,
                              y_edges,
                              np.ma.masked_invalid(z_to_plot),
                              rasterized=rasterized,
                              **kwargs)
    if colorbar is not None:
        colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax)
    else:
        colorbar = ax.figure.colorbar(colormesh, ax=ax)
    return ax, colorbar
Esempio n. 6
0
def plot_correlations(
    fig: matplotlib.figure.Figure,
    ax: matplotlib.axes.Axes,
    r2: float,
    slope: float,
    y_inter: float,
    corr_vals: np.ndarray,
    vis_vals: np.ndarray,
    scale_factor: Union[float, int],
    corr_bname: str,
    vis_bname: str,
    odir: Union[Path, str],
):
    """
    Plot the correlations between NIR band and the visible bands for
    the Hedley et al. (2005) sunglint correction method

    Parameters
    ----------
    fig : matplotlib.figure object
        Reusing a matplotlib.figure object to avoid the creation many
        fig instantances

    ax : matplotlib.axes._subplots object
        Reusing the axes object

    r2 : float
        The correlation coefficient squared of the linear regression
        between NIR and a VIS band

    slope : float
        The slope/gradient of the linear regression between NIR and
        a VIS band

    y_inter : float
        The intercept of the linear regression between NIR and a
        VIS band

    corr_vals : numpy.ndarray
        1D array containing the NIR values from the ROI

    vis_vals : numpy.ndarray
        1D array containing the VIS values from the ROI

    scale_factor : int or None
        The scale factor used to convert integers to reflectances
        that range [0...1]

    corr_bname : str
        The NIR band number

    vis_bname : str
        The VIS band number

    odir : str
        Directory where the correlation plots are saved

    """
    # clear previous plot
    ax.clear()

    # ----------------------------------- #
    #   Create a unique cmap for hist2d   #
    # ----------------------------------- #
    ncolours = 256

    # get the jet colormap
    colour_array = plt.get_cmap("jet")(range(ncolours))  # 256 x 4

    # change alpha values
    # e.g. low values have alpha = 1, high values have alpha = 0
    # color_array[:,-1] = np.linspace(1.0,0.0,ncolors)
    # e.g. low values have alpha = 0, high values have alpha = 1
    # color_array[:,-1] = np.linspace(0.0,1.0,ncolors)

    # We want only the first few colours to have low alpha
    # as they would represent low density [meshgrid] bins
    # which we are not interested in, and hence would want
    # them to appear as a white colour (alpha ~ 0)
    num_alpha = 25
    colour_array[0:num_alpha, -1] = np.linspace(0.0, 1.0, num_alpha)
    colour_array[num_alpha:, -1] = 1

    # create a colormap object
    cmap = LinearSegmentedColormap.from_list(name="jet_alpha",
                                             colors=colour_array)

    # ----------------------------------- #
    #  Plot density using np.histogram2d  #
    # ----------------------------------- #
    xbin_low, xbin_high = np.percentile(corr_vals, (1, 99),
                                        interpolation="linear")
    ybin_low, ybin_high = np.percentile(vis_vals, (1, 99),
                                        interpolation="linear")

    nbins = [int(xbin_high - xbin_low), int(ybin_high - ybin_low)]

    bin_range = [[int(xbin_low), int(xbin_high)],
                 [int(ybin_low), int(ybin_high)]]

    hist2d, xedges, yedges = np.histogram2d(x=corr_vals,
                                            y=vis_vals,
                                            bins=nbins,
                                            range=bin_range)

    # normalised hist to range [0...1] then rotate and flip
    hist2d = np.flipud(np.rot90(hist2d / hist2d.max()))

    # Mask zeros
    hist_masked = np.ma.masked_where(hist2d == 0, hist2d)

    # use pcolormesh to plot the hist2D
    qm = ax.pcolormesh(xedges, yedges, hist_masked, cmap=cmap)

    # create a colour bar axes within ax
    cbaxes = inset_axes(
        ax,
        width="3%",
        height="30%",
        bbox_to_anchor=(0.37, 0.03, 1, 1),
        loc="lower center",
        bbox_transform=ax.transAxes,
    )

    # Add a colour bar inside the axes
    fig.colorbar(
        cm.ScalarMappable(cmap=cmap),
        cax=cbaxes,
        ticks=[0.0, 1],
        orientation="vertical",
        label="Point Density",
    )

    # ----------------------------------- #
    #     Plot linear regression line     #
    # ----------------------------------- #
    x_range = np.array([xbin_low, xbin_high])
    (ln, ) = ax.plot(
        x_range,
        slope * (x_range) + y_inter,
        color="k",
        linestyle="-",
        label="linear regr.",
    )

    # ----------------------------------- #
    #          Format the figure          #
    # ----------------------------------- #
    # add legend (top left)
    lgnd = ax.legend(loc=2, fontsize=10)

    # add annotation
    ann_str = (r"$r^{2}$" + " = {0:0.2f}\n"
               "slope = {1:0.2f}\n"
               "y-inter = {2:0.2f}".format(r2, slope, y_inter))
    ann = ax.annotate(ann_str,
                      xy=(0.02, 0.76),
                      xycoords="axes fraction",
                      fontsize=10)

    # Add labels to figure
    xlabel = f"Reflectance ({corr_bname})"
    ylabel = f"Reflectance ({vis_bname})"

    if scale_factor is not None:
        if scale_factor > 1:
            xlabel += " " + r"$\times$" + " {0}".format(int(scale_factor))
            ylabel += " " + r"$\times$" + " {0}".format(int(scale_factor))

    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    # plt.show(); sys.exit()

    # Save figure
    png_file = os.path.join(
        odir, "Correlation_{0}_vs_{1}.png".format(corr_bname, vis_bname))

    fig.savefig(png_file,
                format="png",
                bbox_inches="tight",
                pad_inches=0.1,
                dpi=300)

    # delete all lines and annotations from figure,
    # so it can be reused in the next iteration
    qm.remove()
    ln.remove()
    ann.remove()
    lgnd.remove()
Esempio n. 7
0
def plot_on_a_plain_grid(x: np.ndarray,
                         y: np.ndarray,
                         z: np.ndarray,
                         ax: matplotlib.axes.Axes,
                         colorbar: matplotlib.colorbar.Colorbar = None,
                         **kwargs: Any) -> AxesTuple:
    """
    Plot a heatmap of z using x and y as axes. Assumes that the data
    are rectangular, i.e. that x and y together describe a rectangular
    grid. The arrays of x and y need not be sorted in any particular
    way, but data must belong together such that z[n] has x[n] and
    y[n] as setpoints.  The setpoints need not be equidistantly
    spaced, but linear interpolation is used to find the edges of the
    plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used
    for the plotting. By default the data in any vector plot will be rasterized
    if more that 5000 points are supplied. This can be overridden
    by supplying the `rasterized` kwarg.

    Args:
        x: The x values
        y: The y values
        z: The z values
        ax: The axis to plot onto
        colorbar: A colorbar to reuse the axis for

    Returns:
        The matplotlib axes handle for plot and colorbar
    """

    log.debug(f'Got kwargs: {kwargs}')

    x_is_stringy = isinstance(x[0], str)
    y_is_stringy = isinstance(y[0], str)
    z_is_stringy = isinstance(z[0], str)

    if x_is_stringy:
        x_strings = np.unique(x)
        x = _strings_as_ints(x)

    if y_is_stringy:
        y_strings = np.unique(y)
        y = _strings_as_ints(y)

    if z_is_stringy:
        z_strings = np.unique(z)
        z = _strings_as_ints(z)

    if x.ndim == 2 and y.ndim == 2 and z.ndim == 2:
        if not np.logical_or(np.any(np.isnan(x)), np.any(np.isnan(y))):
            # data is on a grid that may or may not be
            # rectilinear. Rely on matplotlib to plot
            # this directly
            x_to_plot, y_to_plot, z_to_plot = x, y, z
            num_points = x_to_plot.size
        else:
            x_to_plot, y_to_plot, z_to_plot = _clip_nan_from_shaped_data(
                x, y, z)
            num_points = x_to_plot.size * y_to_plot.size
    else:
        x_to_plot, y_to_plot, z_to_plot = reshape_2D_data(x, y, z)
        num_points = x_to_plot.size * y_to_plot.size

    if 'rasterized' in kwargs.keys():
        rasterized = kwargs.pop('rasterized')
    else:
        rasterized = num_points > qc.config.plotting.rasterize_threshold

    cmap = kwargs.pop('cmap') if 'cmap' in kwargs else None

    if z_is_stringy:
        name = cmap.name if hasattr(cmap, 'name') else 'viridis'
        cmap = matplotlib.cm.get_cmap(name, len(z_strings))

    colormesh = ax.pcolormesh(
        x_to_plot,
        y_to_plot,
        np.ma.masked_invalid(z_to_plot),
        rasterized=rasterized,
        cmap=cmap,
        shading="nearest",
        **kwargs,
    )

    if x_is_stringy:
        ax.set_xticks(np.arange(len(np.unique(x_strings))))
        ax.set_xticklabels(x_strings)

    if y_is_stringy:
        ax.set_yticks(np.arange(len(np.unique(y_strings))))
        ax.set_yticklabels(y_strings)

    if colorbar is not None:
        colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax)
    else:
        colorbar = ax.figure.colorbar(colormesh, ax=ax)

    if z_is_stringy:
        N = len(z_strings)
        f = (N - 1) / N
        colorbar.set_ticks([(n + 0.5) * f for n in range(N)])
        colorbar.set_ticklabels(z_strings)

    return ax, colorbar
Esempio n. 8
0
def plot_on_a_plain_grid(x: np.ndarray,
                         y: np.ndarray,
                         z: np.ndarray,
                         ax: matplotlib.axes.Axes,
                         colorbar: matplotlib.colorbar.Colorbar=None,
                         **kwargs
                         ) -> AxesTuple:
    """
    Plot a heatmap of z using x and y as axes. Assumes that the data
    are rectangular, i.e. that x and y together describe a rectangular
    grid. The arrays of x and y need not be sorted in any particular
    way, but data must belong together such that z[n] has x[n] and
    y[n] as setpoints.  The setpoints need not be equidistantly
    spaced, but linear interpolation is used to find the edges of the
    plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used
    for the plotting. By default the data in any vector plot will be rasterized
    if more that 5000 points are supplied. This can be overridden
    by supplying the `rasterized` kwarg.

    Args:
        x: The x values
        y: The y values
        z: The z values
        ax: The axis to plot onto
        colorbar: a colorbar to reuse the axis for

    Returns:
        The matplotlib axes handle for plot and colorbar
    """

    log.debug(f'Got kwargs: {kwargs}')

    x_is_stringy = isinstance(x[0], str)
    y_is_stringy = isinstance(y[0], str)
    z_is_stringy = isinstance(z[0], str)

    if x_is_stringy:
        x_strings = np.unique(x)
        x = _strings_as_ints(x)

    if y_is_stringy:
        y_strings = np.unique(y)
        y = _strings_as_ints(y)

    if z_is_stringy:
        z_strings = np.unique(z)
        z = _strings_as_ints(z)

    xrow, yrow, z_to_plot = reshape_2D_data(x, y, z)

    # we use a general edge calculator,
    # in the case of non-equidistantly spaced data
    # TODO: is this appropriate for a log ax?
    dxs = np.diff(xrow)/2
    dys = np.diff(yrow)/2
    x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]),
                              xrow[:-1] + dxs,
                              np.array([xrow[-1] + dxs[-1]])))
    y_edges = np.concatenate((np.array([yrow[0] - dys[0]]),
                              yrow[:-1] + dys,
                              np.array([yrow[-1] + dys[-1]])))
    if 'rasterized' in kwargs.keys():
        rasterized = kwargs.pop('rasterized')
    else:
        rasterized = len(x_edges) * len(y_edges) \
                      > qc.config.plotting.rasterize_threshold

    cmap = kwargs.pop('cmap') if 'cmap' in kwargs else None

    if z_is_stringy:
        name = cmap.name if hasattr(cmap, 'name') else 'viridis'
        cmap = matplotlib.cm.get_cmap(name, len(z_strings))

    colormesh = ax.pcolormesh(x_edges, y_edges,
                              np.ma.masked_invalid(z_to_plot),
                              rasterized=rasterized,
                              cmap=cmap,
                              **kwargs)

    if x_is_stringy:
        ax.set_xticks(np.arange(len(np.unique(x_strings))))
        ax.set_xticklabels(x_strings)

    if y_is_stringy:
        ax.set_yticks(np.arange(len(np.unique(y_strings))))
        ax.set_yticklabels(y_strings)

    if colorbar is not None:
        colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax)
    else:
        colorbar = ax.figure.colorbar(colormesh, ax=ax)

    if z_is_stringy:
        N = len(z_strings)
        f = (N-1)/N
        colorbar.set_ticks([(n+0.5)*f for n in range(N)])
        colorbar.set_ticklabels(z_strings)

    return ax, colorbar
Esempio n. 9
0
def plot_polar_histogram(
    values: np.ndarray,
    r_edges: np.ndarray,
    theta_edges: np.ndarray,
    ax: mpl.axes.Axes = None,  # Not sure how to type this (not optional
    # but hard to find default)
    cmap: Optional[str] = None,
    vmin: Optional[float] = None,
    vmax: Optional[float] = None,
    symmetric_color_limits: bool = False,
    interpolation_factor: float = 5,
    angle_convention: str = "clock",
):
    """Plot color polar plot

    :param values: Values to color-code
    :param r_edges: Edges in radius
    :param theta_edges: Edges in angle
    :param ax: matplotlib.axes.Axes. Needs to be `polar=True`
    :param cmap: matplotlib colormap
    :param vmin: lower limit of colorbar range. If None, from data
    :param vmax: upper limit of colorbar range. If None, from data
    :param symmetric_color_limits: How to obtain lower and upper
    limits of colormap from data. If False, limits are (min, max). If
    True, limits are (-max(abs), max(abs))
    :param interpolation_factor: If None or 1, no interpolation is
    performed. If int > 1, each sector is broken in interpolation_factor
    parts, so they look more circular and less polygonal
    :param angle_convention: If "clock", angles increase clockwise
    and are 0 for positive y axis. If "math", angles increase
    counterclockwise and are 0 for positive x axis
    """

    if interpolation_factor is not None:
        values, theta_edges, r_edges = interpolate_polarmap_angles(
            values, theta_edges, r_edges, factor=interpolation_factor)
    theta, r = np.meshgrid(theta_edges, r_edges)

    # Select color limits:
    if symmetric_color_limits:
        vmax_ = np.nanmax(np.abs(values))
        vmin_ = -vmax_
    else:
        vmax_ = np.nanmax(values)
        vmin_ = np.nanmin(values)

    # Only use them if not specified in input
    if vmin is None:
        vmin = vmin_
    if vmax is None:
        vmax = vmax_

    # Plot histogram/map
    fig = ax.get_figure()
    im = ax.pcolormesh(theta, r, values, cmap=cmap, vmin=vmin, vmax=vmax)
    fig.colorbar(im, ax=ax, cmap=cmap)

    if angle_convention == "clock":
        # Adjusting axis and sense of rotation to make it compatible
        # with [2]: Direction of movement is y axis, angles increase clockwise
        ax.set_theta_zero_location("N")
        ax.set_theta_direction(-1)