def hfss_plot_convergences_report(convergence_t: pd.core.frame.DataFrame, convergence_f: pd.core.frame.DataFrame, fig: mpl.figure.Figure = None, _display=True): """Plot convergence frequency vs. pass number if fig is None. Plot delta frequency and solved elements vs. pass number. Plot delta frequency vs. solved elements. Args: convergence_t (pandas.core.frame.DataFrame): Convergence vs pass number of the eigenemode freqs. convergence_f (pandas.core.frame.DataFrame): Convergence vs pass number of the eigenemode freqs. fig (matplotlib.figure.Figure, optional): A mpl figure. Defaults to None. _display (bool, optional): Display the plot? Defaults to True. """ if fig is None: fig = plt.figure(figsize=(11, 3.)) # Grid spec and axes; height_ratios=[4, 1], wspace=0.5 gs = mpl.gridspec.GridSpec(1, 3, width_ratios=[1.2, 1.5, 1]) axs = [fig.add_subplot(gs[i]) for i in range(3)] ax0t = axs[1].twinx() plot_convergence_f_vspass(axs[0], convergence_f) plot_convergence_max_df(axs[1], convergence_t.iloc[:, 1]) plot_convergence_solved_elem(ax0t, convergence_t.iloc[:, 0]) plot_convergence_maxdf_vs_sol(axs[2], convergence_t.iloc[:, 1], convergence_t.iloc[:, 0]) fig.tight_layout(w_pad=0.1) # pad=0.0, w_pad=0.1, h_pad=1.0)
def style_figure(fig: matplotlib.figure.Figure, title: str, bottom: float = 0.2) -> None: """Stylize the supplied matplotlib Figure instance.""" fig.tight_layout() if bottom is not None: fig.subplots_adjust(bottom=bottom) fig.suptitle(title) fig.legend(ncol=10, handlelength=0.75, handletextpad=0.25, columnspacing=0.5, loc='lower left')
def fig_square(fig: mpl.figure.Figure) -> None: """Adjust figure width so that it is square, and tight layout. Parameters ---------- fig : mpl.figure.Figure `Figure` instance. """ fig.set_size_inches(mpl.figure.figaspect(1)) fig.tight_layout()
def apply(self, fig: matplotlib.figure.Figure) -> None: # It shouldn't hurt to align the labels if there's only one. fig.align_ylabels() # Adjust the layout. fig.tight_layout() adjust_default_args = dict( # Reduce spacing between subplots hspace=0, wspace=0, # Reduce external spacing left=0.10, bottom=0.105, right=0.98, top=0.98, ) adjust_default_args.update(self.edge_padding) fig.subplots_adjust(**adjust_default_args)
def plot_convergences(self, convergence_t: pd.DataFrame = None, convergence_f: pd.DataFrame = None, fig: mpl.figure.Figure = None, _display: bool = True): """Creates 3 plots, useful to determin the convergence achieved by the renderer: * convergence frequency vs. pass number if fig is None. * delta frequency and solved elements vs. pass number. * delta frequency vs. solved elements. Args: convergence_t (pd.DataFrame): Convergence vs pass number of the eigenemode freqs. convergence_f (pd.DataFrame): Convergence vs pass number of the eigenemode freqs. fig (matplotlib.figure.Figure, optional): A mpl figure. Defaults to None. _display (bool, optional): Display the plot? Defaults to True. """ if convergence_t is None: convergence_t = self.convergence_t if convergence_f is None: convergence_f = self.convergence_f if fig is None: fig = plt.figure(figsize=(11, 3.)) # Grid spec and axes; height_ratios=[4, 1], wspace=0.5 gspec = mpl.gridspec.GridSpec(1, 3, width_ratios=[1.2, 1.5, 1]) axs = [fig.add_subplot(gspec[i]) for i in range(3)] ax0t = axs[1].twinx() plot_convergence_f_vspass(axs[0], convergence_f) plot_convergence_max_df(axs[1], convergence_t.iloc[:, 1]) plot_convergence_solved_elem(ax0t, convergence_t.iloc[:, 0]) plot_convergence_maxdf_vs_sol(axs[2], convergence_t.iloc[:, 1], convergence_t.iloc[:, 0]) fig.tight_layout(w_pad=0.1) # pad=0.0, w_pad=0.1, h_pad=1.0)
def _trends_helper( adata: AnnData, models: Dict[str, Dict[str, Any]], gene: str, ln_key: str, lineage_names: Optional[Sequence[str]] = None, same_plot: bool = False, sharey: Union[str, bool] = False, show_ylabel: bool = True, show_lineage: bool = True, show_xticks_and_label: bool = True, lineage_cmap=None, abs_prob_cmap=cm.viridis, gene_as_title: bool = False, legend_loc: Optional[str] = "best", fig: mpl.figure.Figure = None, axes: Union[mpl.axes.Axes, Sequence[mpl.axes.Axes]] = None, **kwargs, ) -> None: """ Plot an expression gene for some lineages. Parameters ---------- %(adata)s %(model)s gene Name of the gene in `adata.var_names``. ln_key Key in ``adata.obsm`` where to find the lineages. lineage_names Names of lineages to plot. same_plot Whether to plot all lineages in the same plot or separately. sharey Whether the y-axis is being shared. show_ylabel Whether to show y-label on the y-axis. Usually, only the first column will contain the y-label. show_lineage Whether to show the lineage as the title. Usually, only first row will contain the lineage names. show_xticks_and_label Whether to show x-ticks and x-label. Usually, only the last row will show this. lineage_cmap Colormap to use when coloring the the lineage. If `None`, use colors from ``adata.uns``. abs_prob_cmap: Colormap to use when coloring in the absorption probabilities, if they are being plotted. gene_as_title Whether to use the gene names as titles (with lineage names as well) or on the y-axis. legend_loc Location of the legend. If `None`, don't show any legend. fig Figure to use. ax Ax to use. **kwargs Keyword arguments for :meth:`cellrank.ul.models.BaseModel.plot`. Returns ------- %(just_plots)s """ n_lineages = len(lineage_names) if same_plot: axes = [axes] * len(lineage_names) fig.tight_layout() axes = np.ravel(axes) percs = kwargs.pop("perc", None) if percs is None or not isinstance(percs[0], (tuple, list)): percs = [percs] same_perc = False # we need to show colorbar always if percs differ if len(percs) != n_lineages or n_lineages == 1: if len(percs) != 1: raise ValueError( f"Percentile must be a collection of size `1` or `{n_lineages}`, got `{len(percs)}`." ) same_perc = True percs = percs * n_lineages hide_cells = kwargs.pop("hide_cells", False) show_cbar = kwargs.pop("show_cbar", True) if same_plot: lineage_colors = ( lineage_cmap.colors if lineage_cmap is not None and hasattr(lineage_cmap, "colors") else adata.uns.get(f"{_colors(ln_key)}", cm.Set1.colors) ) else: lineage_colors = ( "black" if not mcolors.is_color_like(lineage_cmap) else lineage_cmap ) for i, (name, ax, perc) in enumerate(zip(lineage_names, axes, percs)): if same_plot: if gene_as_title: title = gene ylabel = "expression" if show_ylabel else None else: title = "" ylabel = gene else: if gene_as_title: title = None ylabel = "expression" if i == 0 else None else: title = ( (name if name is not None else "no lineage") if show_lineage else "" ) ylabel = gene if i == 0 else None models[gene][name].plot( ax=ax, fig=fig, perc=perc, show_cbar=False, title=title, hide_cells=hide_cells or (same_plot and i == n_lineages - 1), same_plot=same_plot, lineage_color=lineage_colors[i] if same_plot and name is not None else lineage_colors, abs_prob_cmap=abs_prob_cmap, ylabel=ylabel, **kwargs, ) if sharey in ("row", "all", True) and i == 0: plt.setp(ax.get_yticklabels(), visible=True) if show_xticks_and_label: plt.setp(ax.get_xticklabels(), visible=True) else: ax.set_xlabel(None) if not same_plot and same_perc and show_cbar and not hide_cells: vmin = np.min([models[gene][ln].w_all for ln in lineage_names]) vmax = np.max([models[gene][ln].w_all for ln in lineage_names]) norm = mcolors.Normalize(vmin=vmin, vmax=vmax) for ax in axes: [ c for c in ax.get_children() if isinstance(c, mpl.collections.PathCollection) ][0].set_norm(norm) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="2.5%", pad=0.1) _ = mpl.colorbar.ColorbarBase( cax, norm=norm, cmap=abs_prob_cmap, label="absorption probability" ) if same_plot and lineage_names != [None] and legend_loc is not None: ax.legend(lineage_names, loc=legend_loc)
def _trends_helper( models: Dict[str, Dict[str, Any]], gene: str, transpose: bool = False, lineage_names: Optional[Sequence[str]] = None, same_plot: bool = False, sharey: Union[str, bool] = False, show_ylabel: bool = True, show_lineage: Union[bool, np.ndarray] = True, show_xticks_and_label: Union[bool, np.ndarray] = True, lineage_cmap: Optional[Union[mpl.colors.ListedColormap, Sequence]] = None, lineage_probability_color: Optional[str] = None, abs_prob_cmap=cm.viridis, gene_as_title: bool = False, legend_loc: Optional[str] = "best", fig: mpl.figure.Figure = None, axes: Union[mpl.axes.Axes, Sequence[mpl.axes.Axes]] = None, **kwargs, ) -> None: """ Plot an expression gene for some lineages. Parameters ---------- %(adata)s %(model)s gene Name of the gene in `adata.var_names``. ln_key Key in ``adata.obsm`` where to find the lineages. lineage_names Names of lineages to plot. same_plot Whether to plot all lineages in the same plot or separately. sharey Whether the y-axis is being shared. show_ylabel Whether to show y-label on the y-axis. Usually, only the first column will contain the y-label. show_lineage Whether to show the lineage as the title. Usually, only first row will contain the lineage names. show_xticks_and_label Whether to show x-ticks and x-label. Usually, only the last row will show this. lineage_cmap Colormap to use when coloring the the lineage. When ``transpose``, this corresponds to the color of genes. lineage_probability_color Actual color of 1 ``lineage``. Only used when ``same_plot=True`` and ``transpose=True`` and ``lineage_probability=True``. abs_prob_cmap: Colormap to use when coloring in the absorption probabilities, if they are being plotted. gene_as_title Whether to use the gene names as titles (with lineage names as well) or on the y-axis. legend_loc Location of the legend. If `None`, don't show any legend. fig Figure to use. ax Ax to use. **kwargs Keyword arguments for :meth:`cellrank.ul.models.BaseModel.plot`. Returns ------- %(just_plots)s """ n_lineages = len(lineage_names) if same_plot: axes = [axes] * len(lineage_names) fig.tight_layout() axes = np.ravel(axes) percs = kwargs.pop("perc", None) if percs is None or not isinstance(percs[0], (tuple, list)): percs = [percs] same_perc = False # we need to show colorbar always if percs differ if len(percs) != n_lineages or n_lineages == 1: if len(percs) != 1: raise ValueError( f"Percentile must be a collection of size `1` or `{n_lineages}`, got `{len(percs)}`." ) same_perc = True percs = percs * n_lineages hide_cells = kwargs.pop("hide_cells", False) show_cbar = kwargs.pop("cbar", True) show_prob = kwargs.pop("lineage_probability", False) if same_plot: if not transpose: lineage_colors = (lineage_cmap.colors if lineage_cmap is not None and hasattr(lineage_cmap, "colors") else lineage_cmap) else: # this should be fine w.r.t. to the missing genes, since they are in the same order AND # we're also passing the failed models (this is important) # these are actually gene colors, bu w/e if lineage_cmap is not None: lineage_colors = ( lineage_cmap.colors if hasattr(lineage_cmap, "colors") else [c for _, c in zip(lineage_names, lineage_cmap)]) else: lineage_colors = _create_categorical_colors(n_lineages) else: lineage_colors = (("black" if not mcolors.is_color_like(lineage_cmap) else lineage_cmap), ) * n_lineages if n_lineages > len(lineage_colors): raise ValueError( f"Expected at least `{n_lineages}` colors, found `{len(lineage_colors)}`." ) lineage_color_mapper = { ln: lineage_colors[i] for i, ln in enumerate(lineage_names) } successful_models = { ln: models[gene][ln] for ln in lineage_names if models[gene][ln] } if show_prob and same_plot: minns, maxxs = zip(*[ models[gene][n]._return_min_max(show_conf_int=kwargs.get( "conf_int", False), ) for n in lineage_names ]) minn, maxx = min(minns), max(maxxs) kwargs["loc"] = legend_loc kwargs["scaler"] = lambda x: (x - minn) / (maxx - minn) else: kwargs["loc"] = None if isinstance(show_xticks_and_label, bool): show_xticks_and_label = [show_xticks_and_label] * len(lineage_names) elif len(show_xticks_and_label) != len(lineage_names): raise ValueError( f"Expected `show_xticks_label` to be the same length as `lineage_names`, " f"found `{len(show_xticks_and_label)}` != `{len(lineage_names)}`.") if isinstance(show_lineage, bool): show_lineage = [show_lineage] * len(lineage_names) elif len(show_lineage) != len(lineage_names): raise ValueError( f"Expected `show_lineage` to be the same length as `lineage_names`, " f"found `{len(show_lineage)}` != `{len(lineage_names)}`.") last_ax = None ylabel_shown = False cells_shown = False for i, (name, ax, perc) in enumerate(zip(lineage_names, axes, percs)): model = models[gene][name] if isinstance(model, FailedModel): if not same_plot: ax.remove() continue if same_plot: if gene_as_title: title = gene ylabel = "expression" if show_ylabel else None else: title = "" ylabel = gene else: if gene_as_title: title = None ylabel = "expression" if not ylabel_shown else None else: title = ((name if name is not None else "no lineage") if show_lineage[i] else "") ylabel = gene if not ylabel_shown else None model.plot( ax=ax, fig=fig, perc=perc, cbar=False, title=title, hide_cells=cells_shown if not hide_cells else True, same_plot=same_plot, lineage_color=lineage_color_mapper[name], lineage_probability_color=lineage_probability_color, abs_prob_cmap=abs_prob_cmap, lineage_probability=show_prob, ylabel=ylabel, **kwargs, ) if sharey in ("row", "all", True) and not ylabel_shown: plt.setp(ax.get_yticklabels(), visible=True) if show_xticks_and_label[i]: plt.setp(ax.get_xticklabels(), visible=True) else: ax.set_xlabel(None) last_ax = ax ylabel_shown = True cells_shown = True if not same_plot and same_perc and show_cbar and not hide_cells: vmin = np.min([model.w_all for model in successful_models.values()]) vmax = np.max([model.w_all for model in successful_models.values()]) norm = mcolors.Normalize(vmin=vmin, vmax=vmax) for ax in axes: children = [ c for c in ax.get_children() if isinstance(c, mpl.collections.PathCollection) ] if len(children): children[0].set_norm(norm) divider = make_axes_locatable(last_ax) cax = divider.append_axes("right", size="2%", pad=0.1) _ = mpl.colorbar.ColorbarBase( cax, norm=norm, cmap=abs_prob_cmap, label="absorption probability", ticks=np.linspace(norm.vmin, norm.vmax, 5), ) if same_plot and lineage_names != [None] and legend_loc is not None: handles = [ mpl.lines.Line2D([], [], color=lineage_color_mapper[ln], label=ln) for ln in successful_models.keys() ] last_ax.legend(handles=handles, loc=legend_loc)