Пример #1
0
def test_relative_luminance():
    """Test relative luminance."""
    out1 = utils.relative_luminance("white")
    assert out1 == 1

    out2 = utils.relative_luminance("#000000")
    assert out2 == 0

    out3 = utils.relative_luminance((.25, .5, .75))
    assert out3 == pytest.approx(0.201624536)

    rgbs = mpl.cm.RdBu(np.linspace(0, 1, 10))
    lums1 = [utils.relative_luminance(rgb) for rgb in rgbs]
    lums2 = utils.relative_luminance(rgbs)

    for lum1, lum2 in zip(lums1, lums2):
        assert lum1 == pytest.approx(lum2)
Пример #2
0
	def choropleth(
			self,
			gdf:gpd.GeoDataFrame,
			column,
			cmap=None,
			legend=True,
			vmin=None,
			vmax=None,
			labels=None,
			colorbar_fraction = 0.046,
			colorbar_pad = 0.04,
			colorbar_shrink = 0.75,
			**kwargs,
	):
		if legend == 'manual':
			manual_legend = True
			legend = False
		else:
			manual_legend = False

		y = gdf.plot(
			ax=self.ax,
			column=column,
			cmap=cmap,
			legend=legend,
			vmin=vmin,
			vmax=vmax,
			**kwargs
		)

		if manual_legend:
			mn = gdf[column].min() if vmin is None else vmin
			mx = gdf[column].max() if vmax is None else vmax
			from matplotlib.colors import Normalize
			from matplotlib import cm
			norm = Normalize(vmin=mn, vmax=mx)
			n_cmap = cm.ScalarMappable(norm=norm, cmap=cmap)
			n_cmap.set_array([])
			self.fig.colorbar(n_cmap, fraction=colorbar_fraction, pad=colorbar_pad, shrink=colorbar_shrink)

		if labels is not None:
			from seaborn.utils import relative_luminance
			areacolors = y.collections[0].get_facecolors()
			label_col = labels.pop('column')
			formatter = labels.pop('formatter', lambda x: x)
			for r in range(len(gdf)):
				self.ax.annotate(
					s=str(formatter(gdf.iloc[r][label_col])),
					xy=gdf.iloc[r].geometry.representative_point().coords[0],
					ha='center', va='center', clip_on=True,
					color=".15" if relative_luminance(areacolors[r]) > .408 else "w",
					**labels
				)
		return self
Пример #3
0
 def _annotate_heatmap(self, ax, mesh):
     """Add textual labels with the value in each cell."""
     mesh.update_scalarmappable()
     xpos, ypos = np.meshgrid(ax.get_xticks(), ax.get_yticks())
     for x, y, m, color, val in zip(xpos.flat, ypos.flat, mesh.get_array(),
                                    mesh.get_facecolors(),
                                    self.annot_data.flat):
         if m is not np.ma.masked:
             l = relative_luminance(color)
             text_color = ".15" if l > .408 else "w"
             annotation = ("{:" + self.fmt + "}").format(val)
             text_kwargs = dict(color=text_color, ha="center", va="center")
             text_kwargs.update(self.annot_kws)
             ax.text(x, y, annotation, **text_kwargs)
Пример #4
0
def annotate_corr_plot(corr, cmap=None, clim=(-1, 1), ax=None):
    ax = ax if ax is not None else plt.gca()

    if isinstance(cmap, str):
        cmap = plt.cm.get_cmap(cmap)
    for i in range(corr.shape[0]):
        for j in range(corr.shape[1]):
            if cmap is None:
                invert = abs(corr[i, j]) > .5
            else:
                color = cmap((corr[i, j] - clim[0]) / (clim[1] - clim[0]))
                invert = relative_luminance(color) <= .408
            text_color = 'w' if invert else 'k'
            text = str(int(100. * corr[i, j]))
            ax.annotate(text, xy=(j, i), ha='center', va='center', color=text_color)
Пример #5
0
def annotate_corr_plot(corr, cmap=None, clim=(-1, 1), ax=None):
    ax = ax if ax is not None else plt.gca()

    if isinstance(cmap, str):
        cmap = plt.cm.get_cmap(cmap)
    for i in range(corr.shape[0]):
        for j in range(corr.shape[1]):
            if cmap is None:
                invert = abs(corr[i, j]) > .5
            else:
                color = cmap((corr[i, j] - clim[0]) / (clim[1] - clim[0]))
                invert = relative_luminance(color) <= .408
            text_color = 'w' if invert else 'k'
            text = str(int(100. * corr[i, j]))
            ax.annotate(text,
                        xy=(j, i),
                        ha='center',
                        va='center',
                        color=text_color)
Пример #6
0
def create_formats_for_nucleosomes(workbook):
    """
    Creates excel formats for the header that we will use

    :param workbook:
    :return:
    """
    color_palette = pd.read_hdf(META_FILE, '/meta/color_palette')

    # These formats will be used for the color palette
    color_formats = {}
    for key, bg_color in color_palette.items():
        # I love this hack from Seaborn:
        font_color = '#000000' if relative_luminance(bg_color) > .408 else '#FFFFFF'
        color_formats[key] = workbook.add_format(dict(font_color=font_color,
                                                      shrink=True,
                                                      align='center',
                                                      valign='vcenter',
                                                      bg_color=bg_color))
    return color_formats
Пример #7
0
def annotate_heatmap_string(mesh, annot_data, **kwargs):
    """
    Add textual labels with the value in each cell.

    (copied from seaborn so that I can pass an array of strings).
    """
    from seaborn.utils import relative_luminance

    ax = mesh.axes
    mesh.update_scalarmappable()
    height, width = annot_data.shape
    xpos, ypos = np.meshgrid(np.arange(width) + 0.5, np.arange(height) + 0.5)

    for x, y, m, color, ann in zip(xpos.flat, ypos.flat, mesh.get_array(),
                                   mesh.get_facecolors(), annot_data.flat):
        if m is not np.ma.masked:
            lum = relative_luminance(color)
            text_color = ".15" if lum > 0.408 else "w"
            text_kwargs = dict(color=text_color, ha="center", va="center")
            text_kwargs.update(**kwargs)
            ax.text(x, y, ann.decode("UTF-8"), **text_kwargs)
Пример #8
0
 def get_text_color(self, background_color):
     luminance = sb_utils.relative_luminance(background_color)
     text_color = ".15" if luminance > .408 else "w"
     return text_color
Пример #9
0
    def _dotplot(
        dot_size,
        dot_color,
        dot_ax,
        cmap: str = 'Reds',
        color_on: Optional[str] = 'dot',
        y_label: Optional[str] = None,
        dot_max: Optional[float] = None,
        dot_min: Optional[float] = None,
        standard_scale: Literal['var', 'group'] = None,
        smallest_dot: Optional[float] = 0.0,
        largest_dot: Optional[float] = 200,
        size_exponent: Optional[float] = 2,
        edge_color: Optional[ColorLike] = None,
        edge_lw: Optional[float] = None,
        grid: Optional[bool] = False,
        x_padding: Optional[float] = 0.8,
        y_padding: Optional[float] = 1.0,
        vmin: Optional[float] = None,
        vmax: Optional[float] = None,
        vcenter: Optional[float] = None,
        norm: Optional[Normalize] = None,
        **kwds,
    ):
        """\
        Makes a *dot plot* given two data frames, one containing
        the doc size and other containing the dot color. The indices and
        columns of the data frame are used to label the output image

        The dots are plotted using :func:`matplotlib.pyplot.scatter`. Thus, additional
        arguments can be passed.

        Parameters
        ----------
        dot_size: Data frame containing the dot_size.
        dot_color: Data frame containing the dot_color, should have the same,
                shape, columns and indices as dot_size.
        dot_ax: matplotlib axis
        cmap
            String denoting matplotlib color map.
        color_on
            Options are 'dot' or 'square'. Be default the colomap is applied to
            the color of the dot. Optionally, the colormap can be applied to an
            square behind the dot, in which case the dot is transparent and only
            the edge is shown.
        y_label: String. Label for y axis
        dot_max
            If none, the maximum dot size is set to the maximum fraction value found
            (e.g. 0.6). If given, the value should be a number between 0 and 1.
            All fractions larger than dot_max are clipped to this value.
        dot_min
            If none, the minimum dot size is set to 0. If given,
            the value should be a number between 0 and 1.
            All fractions smaller than dot_min are clipped to this value.
        standard_scale
            Whether or not to standardize that dimension between 0 and 1,
            meaning for each variable or group,
            subtract the minimum and divide each by its maximum.
        smallest_dot
            If none, the smallest dot has size 0.
            All expression levels with `dot_min` are plotted with this size.
        edge_color
            Dot edge color. When `color_on='dot'` the default is no edge. When
            `color_on='square'`, edge color is white
        edge_lw
            Dot edge line width. When `color_on='dot'` the default is no edge. When
            `color_on='square'`, line width = 1.5
        grid
            Adds a grid to the plot
        x_paddding
            Space between the plot left/right borders and the dots center. A unit
            is the distance between the x ticks. Only applied when color_on = dot
        y_paddding
            Space between the plot top/bottom borders and the dots center. A unit is
            the distance between the y ticks. Only applied when color_on = dot
        kwds
            Are passed to :func:`matplotlib.pyplot.scatter`.

        Returns
        -------
        matplotlib.colors.Normalize, dot_min, dot_max

        """
        assert dot_size.shape == dot_color.shape, (
            'please check that dot_size '
            'and dot_color dataframes have the same shape')

        assert list(dot_size.index) == list(
            dot_color.index), ('please check that dot_size '
                               'and dot_color dataframes have the same index')

        assert list(dot_size.columns) == list(dot_color.columns), (
            'please check that the dot_size '
            'and dot_color dataframes have the same columns')

        if standard_scale == 'group':
            dot_color = dot_color.sub(dot_color.min(1), axis=0)
            dot_color = dot_color.div(dot_color.max(1), axis=0).fillna(0)
        elif standard_scale == 'var':
            dot_color -= dot_color.min(0)
            dot_color = (dot_color / dot_color.max(0)).fillna(0)
        elif standard_scale is None:
            pass

        # make scatter plot in which
        # x = var_names
        # y = groupby category
        # size = fraction
        # color = mean expression

        # +0.5 in y and x to set the dot center at 0.5 multiples
        # this facilitates dendrogram and totals alignment for
        # matrixplot, dotplot and stackec_violin using the same coordinates.
        y, x = np.indices(dot_color.shape)
        y = y.flatten() + 0.5
        x = x.flatten() + 0.5
        frac = dot_size.values.flatten()
        mean_flat = dot_color.values.flatten()
        cmap = pl.get_cmap(kwds.get('cmap', cmap))
        if 'cmap' in kwds:
            del kwds['cmap']
        if dot_max is None:
            dot_max = np.ceil(max(frac) * 10) / 10
        else:
            if dot_max < 0 or dot_max > 1:
                raise ValueError("`dot_max` value has to be between 0 and 1")
        if dot_min is None:
            dot_min = 0
        else:
            if dot_min < 0 or dot_min > 1:
                raise ValueError("`dot_min` value has to be between 0 and 1")

        if dot_min != 0 or dot_max != 1:
            # clip frac between dot_min and  dot_max
            frac = np.clip(frac, dot_min, dot_max)
            old_range = dot_max - dot_min
            # re-scale frac between 0 and 1
            frac = (frac - dot_min) / old_range

        size = frac**size_exponent
        # rescale size to match smallest_dot and largest_dot
        size = size * (largest_dot - smallest_dot) + smallest_dot
        normalize = check_colornorm(vmin, vmax, vcenter, norm)

        if color_on == 'square':
            if edge_color is None:
                from seaborn.utils import relative_luminance

                # use either black or white for the edge color
                # depending on the luminance of the background
                # square color
                edge_color = []
                for color_value in cmap(normalize(mean_flat)):
                    lum = relative_luminance(color_value)
                    edge_color.append(".15" if lum > 0.408 else "w")

            edge_lw = 1.5 if edge_lw is None else edge_lw

            # first make a heatmap similar to `sc.pl.matrixplot`
            # (squares with the asigned colormap). Circles will be plotted
            # on top
            dot_ax.pcolor(dot_color.values, cmap=cmap, norm=normalize)
            for axis in ['top', 'bottom', 'left', 'right']:
                dot_ax.spines[axis].set_linewidth(1.5)
            kwds = fix_kwds(
                kwds,
                s=size,
                cmap=cmap,
                linewidth=edge_lw,
                facecolor='none',
                edgecolor=edge_color,
                norm=normalize,
            )
            dot_ax.scatter(x, y, **kwds)
        else:
            edge_color = 'none' if edge_color is None else edge_color
            edge_lw = 0.0 if edge_lw is None else edge_lw

            color = cmap(normalize(mean_flat))
            kwds = fix_kwds(
                kwds,
                s=size,
                cmap=cmap,
                color=color,
                linewidth=edge_lw,
                edgecolor=edge_color,
                norm=normalize,
            )

            dot_ax.scatter(x, y, **kwds)

        y_ticks = np.arange(dot_color.shape[0]) + 0.5
        dot_ax.set_yticks(y_ticks)
        dot_ax.set_yticklabels(
            [dot_color.index[idx] for idx, _ in enumerate(y_ticks)],
            minor=False)

        x_ticks = np.arange(dot_color.shape[1]) + 0.5
        dot_ax.set_xticks(x_ticks)
        dot_ax.set_xticklabels(
            [dot_color.columns[idx] for idx, _ in enumerate(x_ticks)],
            rotation=90,
            ha='center',
            minor=False,
        )
        dot_ax.tick_params(axis='both', labelsize='small')
        dot_ax.grid(False)
        dot_ax.set_ylabel(y_label)

        # to be consistent with the heatmap plot, is better to
        # invert the order of the y-axis, such that the first group is on
        # top
        dot_ax.set_ylim(dot_color.shape[0], 0)
        dot_ax.set_xlim(0, dot_color.shape[1])

        if color_on == 'dot':
            # add padding to the x and y lims when the color is not in the square
            # default y range goes from 0.5 to num cols + 0.5
            # and default x range goes from 0.5 to num rows + 0.5, thus
            # the padding needs to be corrected.
            x_padding = x_padding - 0.5
            y_padding = y_padding - 0.5
            dot_ax.set_ylim(dot_color.shape[0] + y_padding, -y_padding)

            dot_ax.set_xlim(-x_padding, dot_color.shape[1] + x_padding)

        if grid:
            dot_ax.grid(True, color='gray', linewidth=0.1)
            dot_ax.set_axisbelow(True)

        return normalize, dot_min, dot_max
Пример #10
0
    def plot(self, ax, cax):
        """Draw the heatmap on the provided Axes."""

        # Remove all the Axes spines
        despine(ax=ax, left=True, bottom=True)

        # Draw the heatmap and annotate
        height, width = self.plot_data.shape
        xpos, ypos = np.meshgrid(np.arange(width) + .5, np.arange(height) + .5)

        data = self.plot_data.data
        cellsize = self.cellsize

        mask = self.plot_data.mask
        if not isinstance(mask, np.ndarray) and not mask:
            mask = np.zeros(self.plot_data.shape, np.bool)

        annot_data = self.annot_data
        if not self.annot:
            annot_data = np.zeros(self.plot_data.shape)

        # Draw rectangles instead of using pcolormesh
        # Might be slower than original heatmap
        for x, y, m, val, s, an_val in zip(xpos.flat, ypos.flat, mask.flat,
                                           data.flat, cellsize.flat,
                                           annot_data.flat):
            if not m:
                vv = (val - self.vmin) / (self.vmax - self.vmin)
                size = np.clip(s / self.cellsize_vmax, 0.1, 1.0)
                color = self.cmap(vv)
                rect = plt.Rectangle([x - size / 2, y - size / 2],
                                     size,
                                     size,
                                     facecolor=color,
                                     **self.rect_kws)
                ax.add_patch(rect)

                if self.annot:
                    annotation = ("{:" + self.fmt + "}").format(an_val)
                    text = ax.text(x, y, annotation, **self.annot_kws)
                    # add edge to text
                    text_luminance = relative_luminance(text.get_color())
                    text_edge_color = ".15" if text_luminance > .408 else "w"
                    text.set_path_effects([
                        mpl.patheffects.withStroke(linewidth=1,
                                                   foreground=text_edge_color)
                    ])

        # Set the axis limits
        ax.set(xlim=(0, self.data.shape[1]), ylim=(0, self.data.shape[0]))

        # Set other attributes
        ax.set(**self.ax_kws)

        if self.cbar:
            norm = mpl.colors.Normalize(vmin=self.vmin, vmax=self.vmax)
            scalar_mappable = mpl.cm.ScalarMappable(cmap=self.cmap, norm=norm)
            scalar_mappable.set_array(self.plot_data.data)
            cb = ax.figure.colorbar(scalar_mappable, cax, ax, **self.cbar_kws)
            cb.outline.set_linewidth(0)
            # if kws.get('rasterized', False):
            #     cb.solids.set_rasterized(True)

        # Add row and column labels
        if isinstance(self.xticks, string_types) and self.xticks == "auto":
            xticks, xticklabels = self._auto_ticks(ax, self.xticklabels, 0)
        else:
            xticks, xticklabels = self.xticks, self.xticklabels

        if isinstance(self.yticks, string_types) and self.yticks == "auto":
            yticks, yticklabels = self._auto_ticks(ax, self.yticklabels, 1)
        else:
            yticks, yticklabels = self.yticks, self.yticklabels

        ax.set(xticks=xticks, yticks=yticks)
        xtl = ax.set_xticklabels(xticklabels)
        ytl = ax.set_yticklabels(yticklabels, rotation="vertical")

        # Possibly rotate them if they overlap
        ax.figure.draw(ax.figure.canvas.get_renderer())
        if axis_ticklabels_overlap(xtl):
            plt.setp(xtl, rotation="vertical")
        if axis_ticklabels_overlap(ytl):
            plt.setp(ytl, rotation="horizontal")

        # Add the axis labels
        ax.set(xlabel=self.xlabel, ylabel=self.ylabel)

        # Invert the y axis to show the plot in matrix form
        ax.invert_yaxis()