jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def visualize_histograms(histograms,
                         output=None,
                         labels=DATASET_LIST,
                         linestyles=None,
                         rotation=90,
                         legend=None,
                         y_log=False,
                         colors=['seagreen', 'orange', 'cornflowerblue']):
    """
    Plotting histograms one near the other
    """

    n_histograms = len(histograms)
    #
    # assuming homogeneous data leengths
    # TODO: better error checking
    n_ticks = len(histograms[0])

    bin_width = 1 / (n_histograms + 1)
    bins = [[i + j * bin_width for i in range(n_ticks)]
            for j in range(1, n_histograms + 1)]

    #
    # setting up seaborn
    seaborn.set_style("white")
    seaborn.set_context("poster")
    # seaborn.set_palette(palette, n_colors=n_histograms)

    fig, ax = pyplot.subplots()

    if legend is not None:
        _legend = pyplot.legend(legend)
    #
    # setting labels
    middle_histogram = n_histograms // 2 + 1  # if n_histograms > 1 else 0
    pyplot.xticks(bins[middle_histogram], DATASET_LIST)
    if rotation is not None:
        locs, labels = pyplot.xticks()
        pyplot.setp(labels, rotation=90)

    #
    # actual plotting
    print(histograms)
    for i, histogram in enumerate(histograms):
        ax.bar(bins[i], histogram, width=bin_width,
               facecolor=colors[i], edgecolor="none",
               log=y_log)

    seaborn.despine()

    if output is not None:

        pp = PdfPages(output)
        pp.savefig(fig)
        pp.close()
//  [python]
def visualize_histograms(histograms,
                         output=None,
                         labels=DATASET_LIST,
                         linestyles=None,
                         rotation=90,
                         legend=None,
                         y_log=False,
                         colors=['seagreen', 'orange', 'cornflowerblue']):
    """
    Plotting histograms one near the other
    """

    n_histograms = len(histograms)
    #
    # assuming homogeneous data leengths
    # TODO: better error checking
    n_ticks = len(histograms[0])

    bin_width = 1 / (n_histograms + 1)
    bins = [[i + j * bin_width for i in range(n_ticks)]
            for j in range(1, n_histograms + 1)]

    #
    # setting up seaborn
    seaborn.set_style("white")
    seaborn.set_context("poster")
    # seaborn.set_palette(palette, n_colors=n_histograms)

    fig, ax = pyplot.subplots()

    if legend is not None:
        _legend = pyplot.legend(legend)
    #
    # setting labels
    middle_histogram = n_histograms // 2 + 1  # if n_histograms > 1 else 0
    pyplot.xticks(bins[middle_histogram], DATASET_LIST)
    if rotation is not None:
        locs, labels = pyplot.xticks()
        pyplot.setp(labels, rotation=90)

    #
    # actual plotting
    print(histograms)
    for i, histogram in enumerate(histograms):
        ax.bar(bins[i], histogram, width=bin_width,
               facecolor=colors[i], edgecolor="none",
               log=y_log)

    seaborn.utils.despine()

    if output is not None:

        pp = PdfPages(output)
        pp.savefig(fig)
        pp.close()
//  [python]
def plot_metrics_per_dataset(
    data,
    datasets,
    x,
    y,
    hue,
    hue_order,
    y_label=None,
    x_label=None,
    save_path=None,
    figsize=(10, 4),
    test="t-test_paired",
    order=None,
    ax=None,
    **kwargs,
):
    pairs_prelim = [(model, model) for model in hue_order]
    pairs = list(itertools.combinations(pairs_prelim, 2))
    print(pairs)
    pairs=[((model_type_map['poissonvi'], model_type_map['poissonvi']), 
        (model_type_map['binaryvi'], model_type_map['binaryvi'])),
       #
        ((model_type_map['binaryvi'], model_type_map['binaryvi']), 
        (model_type_map['peakvi'], model_type_map['peakvi'])),
      ]
    if not ax:
        fig, ax = plt.subplots(figsize=figsize)
    ax = create_annotated_stripplot(
        data=data,
        y=y,
        x=x,
        hue=hue,
        order=order,
        hue_order=hue_order,
        ax=ax,
        y_label=y_label,
        x_label=x_label,
        test=test,
        pairs=pairs,
        **kwargs,
    )

    sns.despine(left=False)
    if save_path:
        fig.savefig(
            os.path.join(save_path, f'{y.split(".")[-1]}_{"_".join(hue_order)}.pdf')
        )
        fig.savefig(
            os.path.join(save_path, f'{y.split(".")[-1]}_{"_".join(hue_order)}.png')
        )
    return ax
//  [python]
def plot_metrics_per_dataset(
    data,
    datasets,
    x,
    y,
    hue,
    hue_order,
    y_label=None,
    x_label=None,
    save_path=None,
    figsize=(10, 4),
    test="t-test_paired",
    order=None,
    ax=None,
    **kwargs,
):
    pairs_prelim = [(model, model) for model in hue_order]
    pairs = list(itertools.combinations(pairs_prelim, 2))
    print(pairs)
    pairs=[((model_type_map['poissonvi'], model_type_map['poissonvi']), 
        (model_type_map['binaryvi'], model_type_map['binaryvi'])),
       #
        ((model_type_map['binaryvi'], model_type_map['binaryvi']), 
        (model_type_map['peakvi'], model_type_map['peakvi'])),
      ]
    if not ax:
        fig, ax = plt.subplots(figsize=figsize)
    ax = create_annotated_stripplot(
        data=data,
        y=y,
        x=x,
        hue=hue,
        order=order,
        hue_order=hue_order,
        ax=ax,
        y_label=y_label,
        x_label=x_label,
        test=test,
        pairs=pairs,
        **kwargs,
    )

    sns.utils.despine(left=False)
    if save_path:
        fig.savefig(
            os.path.join(save_path, f'{y.split(".")[-1]}_{"_".join(hue_order)}.pdf')
        )
        fig.savefig(
            os.path.join(save_path, f'{y.split(".")[-1]}_{"_".join(hue_order)}.png')
        )
    return ax
//  [python]
def set_chart_style(style="whitegrid", despine=True):
    sns.set_style(style)
    if despine:
        sns.despine()
//  [python]
def set_chart_style(style="whitegrid", despine=True):
    sns.set_style(style)
    if despine:
        sns.utils.despine()
//  [python]
def make_log_beta_resid_hist(self, ax):
        for plot_version in self._plot_versions:
            data = plot_version.load_output_draws('beta_scaling_parameters', self._loc_id)
            data = data[data.scaling_parameter == 'log_beta_residual_mean'].drop(columns='scaling_parameter').T

            ax.hist(data.values, color=plot_version.color, bins=HIST_BINS, histtype='step')
            ax.hist(data.values, color=plot_version.color, bins=HIST_BINS, histtype='stepfilled', alpha=FILL_ALPHA)
        ax.set_xlim(-1, 1)
        ax.set_ylabel('Residual count', fontsize=AX_LABEL_FONTSIZE)
        sns.despine(ax=ax, left=True, bottom=True)
//  [python]
def make_log_beta_resid_hist(self, ax):
        for plot_version in self._plot_versions:
            data = plot_version.load_output_draws('beta_scaling_parameters', self._loc_id)
            data = data[data.scaling_parameter == 'log_beta_residual_mean'].drop(columns='scaling_parameter').T

            ax.hist(data.values, color=plot_version.color, bins=HIST_BINS, histtype='step')
            ax.hist(data.values, color=plot_version.color, bins=HIST_BINS, histtype='stepfilled', alpha=FILL_ALPHA)
        ax.set_xlim(-1, 1)
        ax.set_ylabel('Residual count', fontsize=AX_LABEL_FONTSIZE)
        sns.utils.despine(ax=ax, left=True, bottom=True)
//  [python]
def make_coefficient_plot(self, ax, covariate: str, label: str):
        for i, plot_version in enumerate(self._plot_versions):
            data = plot_version.load_output_draws('coefficients', self._loc_id)
            data = data[data.covariate == covariate].drop(columns='covariate').T
            # Boxplots are super annoying.
            props = dict(color=plot_version.color, linewidth=2)
            ax.boxplot(
                data,
                positions=[i],
                widths=[.7],
                boxprops=props,
                capprops=props,
                whiskerprops=props,
                flierprops={**props, **dict(markeredgecolor=plot_version.color)},
                medianprops=props,
                labels=[' '],  # Keeps the plot vertical size consistent with other things on the same row.
            )

        ax.set_ylabel(label, fontsize=AX_LABEL_FONTSIZE)
        sns.despine(ax=ax, left=True, bottom=True)
//  [python]
def make_coefficient_plot(self, ax, covariate: str, label: str):
        for i, plot_version in enumerate(self._plot_versions):
            data = plot_version.load_output_draws('coefficients', self._loc_id)
            data = data[data.covariate == covariate].drop(columns='covariate').T
            # Boxplots are super annoying.
            props = dict(color=plot_version.color, linewidth=2)
            ax.boxplot(
                data,
                positions=[i],
                widths=[.7],
                boxprops=props,
                capprops=props,
                whiskerprops=props,
                flierprops={**props, **dict(markeredgecolor=plot_version.color)},
                medianprops=props,
                labels=[' '],  # Keeps the plot vertical size consistent with other things on the same row.
            )

        ax.set_ylabel(label, fontsize=AX_LABEL_FONTSIZE)
        sns.utils.despine(ax=ax, left=True, bottom=True)
//  [python]
def log_kdes(self, tag, data, save_img=False):
        def np_val(x):
            return x.cpu().numpy().squeeze() if isinstance(x, torch.Tensor) else x.squeeze()

        fig, ax = plt.subplots(1, len(data), figsize=(5 * len(data), 3), sharex=True, sharey=True)
        for i, (name, covariates) in enumerate(data.items()):
            try:
                if len(covariates) == 1:
                    (x_n, x), = tuple(covariates.items())
                    sns.kdeplot(x=np_val(x), ax=ax[i], shade=True, thresh=0.05)
                elif len(covariates) == 2:
                    (x_n, x), (y_n, y) = tuple(covariates.items())
                    sns.kdeplot(x=np_val(x), y=np_val(y), ax=ax[i], shade=True, thresh=0.05)
                    ax[i].set_ylabel(y_n)
                else:
                    raise ValueError(f'got too many values: {len(covariates)}')
            except np.linalg.LinAlgError:
                print(f'got a linalg error when plotting {tag}/{name}')

            ax[i].set_title(name)
            ax[i].set_xlabel(x_n)

        sns.despine()

        if save_img:
            p = os.path.join(self.trainer.logger.experiment.log_dir, f'{tag}.png')
            plt.savefig(p, dpi=300)

        self.logger.experiment.add_figure(tag, fig, self.current_epoch)
//  [python]
def log_kdes(self, tag, data, save_img=False):
        def np_val(x):
            return x.cpu().numpy().squeeze() if isinstance(x, torch.Tensor) else x.squeeze()

        fig, ax = plt.subplots(1, len(data), figsize=(5 * len(data), 3), sharex=True, sharey=True)
        for i, (name, covariates) in enumerate(data.items()):
            try:
                if len(covariates) == 1:
                    (x_n, x), = tuple(covariates.items())
                    sns.kdeplot(x=np_val(x), ax=ax[i], shade=True, thresh=0.05)
                elif len(covariates) == 2:
                    (x_n, x), (y_n, y) = tuple(covariates.items())
                    sns.kdeplot(x=np_val(x), y=np_val(y), ax=ax[i], shade=True, thresh=0.05)
                    ax[i].set_ylabel(y_n)
                else:
                    raise ValueError(f'got too many values: {len(covariates)}')
            except np.linalg.LinAlgError:
                print(f'got a linalg error when plotting {tag}/{name}')

            ax[i].set_title(name)
            ax[i].set_xlabel(x_n)

        sns.utils.despine()

        if save_img:
            p = os.path.join(self.trainer.logger.experiment.log_dir, f'{tag}.png')
            plt.savefig(p, dpi=300)

        self.logger.experiment.add_figure(tag, fig, self.current_epoch)
//  [python]
def full_plot(v_full, vmin, vmax, colorbar=False):
    dot_size = 2
    fig2 = plt.figure(figsize = (2.1, 2.1), dpi=300)
    ax10 = fig2.add_subplot(1, 1, 1) 
    # ax10.set_title('Complete', fontsize=7)
    p = ax10.scatter(transformed_states[:, 0] , transformed_states[:, 1], c=v_full, marker='.', s=dot_size, lw=0, cmap='plasma', vmin=vmin, vmax=vmax)
    ax10.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False)
    # vv = np.where(v_full < -0.8)[0]  # re-plotting low values to be seen on the top
    # ax10.scatter(transformed_states[vv, 0] , transformed_states[vv, 1], c=v_full[vv], marker='.', s=dot_size, lw=0, cmap='plasma', vmin=-1, vmax=0)
    if colorbar:
        vf1 = np.linspace(-1, 1, 5, endpoint=True)
        cb = plt.colorbar(p, ticks=vf1, ax=ax10)
        # # cb.set_label('D-Network Values', size=7, rotation=270)
        for l in cb.ax.yaxis.get_ticklabels():
            l.set_size(7)
        cb.ax.get_yaxis().labelpad = 8
    fig2.tight_layout(pad=0.0)
    seaborn.despine(ax=ax10, top=True, right=True, left=True, bottom=True)
    return fig2, ax10
//  [python]
def full_plot(v_full, vmin, vmax, colorbar=False):
    dot_size = 2
    fig2 = plt.figure(figsize = (2.1, 2.1), dpi=300)
    ax10 = fig2.add_subplot(1, 1, 1) 
    # ax10.set_title('Complete', fontsize=7)
    p = ax10.scatter(transformed_states[:, 0] , transformed_states[:, 1], c=v_full, marker='.', s=dot_size, lw=0, cmap='plasma', vmin=vmin, vmax=vmax)
    ax10.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False)
    # vv = np.where(v_full < -0.8)[0]  # re-plotting low values to be seen on the top
    # ax10.scatter(transformed_states[vv, 0] , transformed_states[vv, 1], c=v_full[vv], marker='.', s=dot_size, lw=0, cmap='plasma', vmin=-1, vmax=0)
    if colorbar:
        vf1 = np.linspace(-1, 1, 5, endpoint=True)
        cb = plt.colorbar(p, ticks=vf1, ax=ax10)
        # # cb.set_label('D-Network Values', size=7, rotation=270)
        for l in cb.ax.yaxis.get_ticklabels():
            l.set_size(7)
        cb.ax.get_yaxis().labelpad = 8
    fig2.tight_layout(pad=0.0)
    seaborn.utils.despine(ax=ax10, top=True, right=True, left=True, bottom=True)
    return fig2, ax10
//  [python]
def _plot(self, region):
        self._refresh(region)

        # plot patch at slice region
        bottom, top = self.ax.get_ylim()
        patch_region = self.slice_region.copy()

        rect = patches.Rectangle((patch_region.start, bottom),
                                 len(patch_region), (top - bottom)/20,
                                 facecolor='grey', edgecolor='grey')
        self.ax.add_patch(rect)

        if self.names:
            self.add_legend()
        self.remove_colorbar_ax()
        sns.despine(ax=self.ax, top=True, right=True)
//  [python]
def _plot(self, region):
        self._refresh(region)

        # plot patch at slice region
        bottom, top = self.ax.get_ylim()
        patch_region = self.slice_region.copy()

        rect = patches.Rectangle((patch_region.start, bottom),
                                 len(patch_region), (top - bottom)/20,
                                 facecolor='grey', edgecolor='grey')
        self.ax.add_patch(rect)

        if self.names:
            self.add_legend()
        self.remove_colorbar_ax()
        sns.utils.despine(ax=self.ax, top=True, right=True)
//  [python]
def plot_figure2(df):
    # Make axes
    fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(12,3))

    df['desired coverage (1-α)'] = 1-df['alpha']

    # Left barplot -- gray lines to indicate desired coverage level
    sns.barplot('desired coverage (1-α)','desired coverage (1-α)',data=df, alpha=0.3, ax=axs[0], edgecolor='k', ci=None, fill=False)
    # Left barplot -- empirical coverages
    bplot = sns.barplot(x='desired coverage (1-α)', y='coverage', hue='predictor', data=df, ax=axs[0], alpha=0.5, ci='sd', linewidth=0.01)
    # Change alpha on face colors
    for patch in bplot.artists:
        r, g, b, a = patch.get_facecolor()
        patch.set_facecolor((r,g,b,0.5))
    # Right barplot - empirical sizes
    sns.barplot(x='desired coverage (1-α)', y='size', hue='predictor', data=df, ax=axs[1], ci='sd', alpha=0.5, linewidth=0.01)
    sns.despine(top=True, right=True)

    axs[0].set_ylim(ymin=0.85,ymax=1.0)
    axs[0].set_yticks([0.85, 0.9, 0.95, 1])
    axs[0].set_ylabel('empirical coverage')

    axs[1].set_ylabel('average size')

    # Font size 
    for ax in axs:
        for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
                ax.get_xticklabels() + ax.get_yticklabels()):
            item.set_fontsize(15)
        ax.legend(fontsize=15,title_fontsize=15)
    axs[1].get_legend().remove()

    plt.tight_layout(rect=[0, 0.03, 1, 0.93])
    plt.savefig('./outputs/barplot-figure2.pdf')
//  [python]
def plot_figure2(df):
    # Make axes
    fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(12,3))

    df['desired coverage (1-α)'] = 1-df['alpha']

    # Left barplot -- gray lines to indicate desired coverage level
    sns.barplot('desired coverage (1-α)','desired coverage (1-α)',data=df, alpha=0.3, ax=axs[0], edgecolor='k', ci=None, fill=False)
    # Left barplot -- empirical coverages
    bplot = sns.barplot(x='desired coverage (1-α)', y='coverage', hue='predictor', data=df, ax=axs[0], alpha=0.5, ci='sd', linewidth=0.01)
    # Change alpha on face colors
    for patch in bplot.artists:
        r, g, b, a = patch.get_facecolor()
        patch.set_facecolor((r,g,b,0.5))
    # Right barplot - empirical sizes
    sns.barplot(x='desired coverage (1-α)', y='size', hue='predictor', data=df, ax=axs[1], ci='sd', alpha=0.5, linewidth=0.01)
    sns.utils.despine(top=True, right=True)

    axs[0].set_ylim(ymin=0.85,ymax=1.0)
    axs[0].set_yticks([0.85, 0.9, 0.95, 1])
    axs[0].set_ylabel('empirical coverage')

    axs[1].set_ylabel('average size')

    # Font size 
    for ax in axs:
        for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
                ax.get_xticklabels() + ax.get_yticklabels()):
            item.set_fontsize(15)
        ax.legend(fontsize=15,title_fontsize=15)
    axs[1].get_legend().remove()

    plt.tight_layout(rect=[0, 0.03, 1, 0.93])
    plt.savefig('./outputs/barplot-figure2.pdf')
//  [python]
def _plot(self, region):
        logger.debug("Generating matrix from hic object")
        if region is None:
            raise ValueError("Cannot plot triangle plot for whole genome.")
        if region.start is None:
            region.start = 1
        if region.end is None:
            region.end = self.hic_data.chromosome_lengths[region.chromosome]
        if self.aspect is None and self.proportional:
            if self.max_dist is None:
                self.aspect = .5
            else:
                rl = region.end - region.start
                self.aspect = .5*min(self.max_dist, rl)/rl
            self._dimensions_stale = True

        # Have to copy unfortunately, otherwise modifying matrix in buffer
        self._refresh(region)

        # set limits and aspect ratio
        # self.ax.set_aspect(aspect="equal")
        self.ax.set_ylim(0, self.max_dist/2 if self.max_dist else (region.end-region.start)/2)
        # remove outline everywhere except at bottom
        sns.despine(ax=self.ax, top=True, right=True, left=True)
        self.ax.set_yticks([])
        # hide background patch
        self.ax.patch.set_visible(False)
        if self.adjust_range:
            self.add_adj_slider()

        def drag_pan(self, button, key, x, y):
            mpl.axes.Axes.drag_pan(self, button, 'x', x, y)  # pretend key=='x'

        self.ax.drag_pan = types.MethodType(drag_pan, self.ax)
//  [python]
def _plot(self, region):
        logger.debug("Generating matrix from hic object")
        if region is None:
            raise ValueError("Cannot plot triangle plot for whole genome.")
        if region.start is None:
            region.start = 1
        if region.end is None:
            region.end = self.hic_data.chromosome_lengths[region.chromosome]
        if self.aspect is None and self.proportional:
            if self.max_dist is None:
                self.aspect = .5
            else:
                rl = region.end - region.start
                self.aspect = .5*min(self.max_dist, rl)/rl
            self._dimensions_stale = True

        # Have to copy unfortunately, otherwise modifying matrix in buffer
        self._refresh(region)

        # set limits and aspect ratio
        # self.ax.set_aspect(aspect="equal")
        self.ax.set_ylim(0, self.max_dist/2 if self.max_dist else (region.end-region.start)/2)
        # remove outline everywhere except at bottom
        sns.utils.despine(ax=self.ax, top=True, right=True, left=True)
        self.ax.set_yticks([])
        # hide background patch
        self.ax.patch.set_visible(False)
        if self.adjust_range:
            self.add_adj_slider()

        def drag_pan(self, button, key, x, y):
            mpl.axes.Axes.drag_pan(self, button, 'x', x, y)  # pretend key=='x'

        self.ax.drag_pan = types.MethodType(drag_pan, self.ax)
//  [python]
def violinplot(self, n=1000, **kwargs):
        """Plot violins of each distribution in the model family

        Parameters
        ----------
        n : int
            Number of random variables to generate
        kwargs : dict or keywords
            Any keyword arguments to seaborn.violinplot

        Returns
        -------
        ax : matplotlib.Axes object
            Axes object with violins plotted
        """
        kwargs.setdefault('palette', 'Purples')

        dfs = []

        for rv in self.rvs:
            psi = rv.rvs(n)
            df = pd.Series(psi, name=self.ylabel).to_frame()
            alpha, beta = rv.args
            alpha = self.nice_number_string(alpha, decimal_places=2)
            beta = self.nice_number_string(beta, decimal_places=2)

            df['parameters'] = '$\\alpha = {0}$\n$\\beta = {1}$'.format(
                alpha, beta)
            dfs.append(df)
        data = pd.concat(dfs)

        if 'ax' not in kwargs:
            fig, ax = plt.subplots(figsize=(len(self.alphas)*0.625, 4))
        else:
            ax = kwargs.pop('ax')
        ax = violinplot(x='parameters', y=self.ylabel, data=data,
                        ax=ax, **kwargs)
        sns.despine(ax=ax)
        return ax
//  [python]
def violinplot(self, n=1000, **kwargs):
        """Plot violins of each distribution in the model family

        Parameters
        ----------
        n : int
            Number of random variables to generate
        kwargs : dict or keywords
            Any keyword arguments to seaborn.violinplot

        Returns
        -------
        ax : matplotlib.Axes object
            Axes object with violins plotted
        """
        kwargs.setdefault('palette', 'Purples')

        dfs = []

        for rv in self.rvs:
            psi = rv.rvs(n)
            df = pd.Series(psi, name=self.ylabel).to_frame()
            alpha, beta = rv.args
            alpha = self.nice_number_string(alpha, decimal_places=2)
            beta = self.nice_number_string(beta, decimal_places=2)

            df['parameters'] = '$\\alpha = {0}$\n$\\beta = {1}$'.format(
                alpha, beta)
            dfs.append(df)
        data = pd.concat(dfs)

        if 'ax' not in kwargs:
            fig, ax = plt.subplots(figsize=(len(self.alphas)*0.625, 4))
        else:
            ax = kwargs.pop('ax')
        ax = violinplot(x='parameters', y=self.ylabel, data=data,
                        ax=ax, **kwargs)
        sns.utils.despine(ax=ax)
        return ax
//  [python]
def plot_violin_fovs(Cells_df):
    '''
    Create violin plots of cell stats across FOVs
    '''

    sns.set(style="whitegrid", palette="pastel", color_codes=True, font_scale=1.25)

    columns = ['sb', 'sd', 'delta', 'tau', 'elong_rate', 'septum_position']
    ylabels = ['$\mu$m', '$\mu$m', '$\mu$m', 'min', '$\lambda$', 'daughter/mother']
    titles = ['Length at Birth', 'Length at Division', 'Delta',
              'Generation Time', 'Elongation Rate', 'Septum Position']

    fig, axes = plt.subplots(nrows=len(columns), ncols=1,
                            figsize=[15,2.5*len(columns)], squeeze=False)
    ax = np.ravel(axes)

    for i, column in enumerate(columns):
        # Draw a nested violinplot and split the violins for easier comparison
        sns.violinplot(x="fov", y=column, data=Cells_df,
                      scale="count", inner="quartile", ax=ax[i], lw=1)

        ax[i].set_title(titles[i], size=18)
        ax[i].set_ylabel(ylabels[i], size=16)
        ax[i].set_xlabel('')
        ax[i].tick_params(axis='both', which='major', labelsize=10)

    ax[i].set_xlabel('FOV', size=16)

    # plt.tight_layout()

    # Make title, need a little extra space
    plt.subplots_adjust(top=.925, hspace=0.5)
    fig.suptitle('Cell Parameters Across FOVs', size=20)

    sns.despine()
    # plt.show()

    return fig, ax
//  [python]
def plot_violin_fovs(Cells_df):
    '''
    Create violin plots of cell stats across FOVs
    '''

    sns.set(style="whitegrid", palette="pastel", color_codes=True, font_scale=1.25)

    columns = ['sb', 'sd', 'delta', 'tau', 'elong_rate', 'septum_position']
    ylabels = ['$\mu$m', '$\mu$m', '$\mu$m', 'min', '$\lambda$', 'daughter/mother']
    titles = ['Length at Birth', 'Length at Division', 'Delta',
              'Generation Time', 'Elongation Rate', 'Septum Position']

    fig, axes = plt.subplots(nrows=len(columns), ncols=1,
                            figsize=[15,2.5*len(columns)], squeeze=False)
    ax = np.ravel(axes)

    for i, column in enumerate(columns):
        # Draw a nested violinplot and split the violins for easier comparison
        sns.violinplot(x="fov", y=column, data=Cells_df,
                      scale="count", inner="quartile", ax=ax[i], lw=1)

        ax[i].set_title(titles[i], size=18)
        ax[i].set_ylabel(ylabels[i], size=16)
        ax[i].set_xlabel('')
        ax[i].tick_params(axis='both', which='major', labelsize=10)

    ax[i].set_xlabel('FOV', size=16)

    # plt.tight_layout()

    # Make title, need a little extra space
    plt.subplots_adjust(top=.925, hspace=0.5)
    fig.suptitle('Cell Parameters Across FOVs', size=20)

    sns.utils.despine()
    # plt.show()

    return fig, ax
//  [python]
def plot_violin_birth_label(Cells_df):
    '''
    Create violin plots of cell stats versus the birth label.

    This is a good way to test if the mother cells are aging, or the cells
    farther down the channel are not being segmented well.
    '''

    # sns.set(style="whitegrid", palette="pastel", color_codes=True, font_scale=1.25)

    columns = ['sb', 'sd', 'delta', 'tau', 'elong_rate', 'septum_position']
    ylabels = ['$\mu$m', '$\mu$m', '$\mu$m', 'min', '$\lambda$', 'daughter/mother']
    titles = ['Length at Birth', 'Length at Division', 'Delta',
              'Generation Time', 'Elongation Rate', 'Septum Position']

    fig, axes = plt.subplots(nrows=len(columns), ncols=1,
                            figsize=[8,2.5*len(columns)], squeeze=False)
    ax = np.ravel(axes)

    for i, column in enumerate(columns):
        # Draw a nested violinplot and split the violins for easier comparison
        sns.violinplot(x="birth_label", y=column, data=Cells_df,
                      scale="count", inner="quartile", ax=ax[i], lw=1)

        ax[i].set_title(titles[i])
        ax[i].set_ylabel(ylabels[i])
        ax[i].set_xlabel('')
        ax[i].tick_params(axis='both', which='major', labelsize=10)

    ax[i].set_xlabel('Birth Label')

    # plt.tight_layout()

    # Make title, need a little extra space
    plt.subplots_adjust(top=.925, hspace=0.5)
    fig.suptitle('Cell Parameters vs Birth Label')

    sns.despine()

    return fig, ax
//  [python]
def plot_violin_birth_label(Cells_df):
    '''
    Create violin plots of cell stats versus the birth label.

    This is a good way to test if the mother cells are aging, or the cells
    farther down the channel are not being segmented well.
    '''

    # sns.set(style="whitegrid", palette="pastel", color_codes=True, font_scale=1.25)

    columns = ['sb', 'sd', 'delta', 'tau', 'elong_rate', 'septum_position']
    ylabels = ['$\mu$m', '$\mu$m', '$\mu$m', 'min', '$\lambda$', 'daughter/mother']
    titles = ['Length at Birth', 'Length at Division', 'Delta',
              'Generation Time', 'Elongation Rate', 'Septum Position']

    fig, axes = plt.subplots(nrows=len(columns), ncols=1,
                            figsize=[8,2.5*len(columns)], squeeze=False)
    ax = np.ravel(axes)

    for i, column in enumerate(columns):
        # Draw a nested violinplot and split the violins for easier comparison
        sns.violinplot(x="birth_label", y=column, data=Cells_df,
                      scale="count", inner="quartile", ax=ax[i], lw=1)

        ax[i].set_title(titles[i])
        ax[i].set_ylabel(ylabels[i])
        ax[i].set_xlabel('')
        ax[i].tick_params(axis='both', which='major', labelsize=10)

    ax[i].set_xlabel('Birth Label')

    # plt.tight_layout()

    # Make title, need a little extra space
    plt.subplots_adjust(top=.925, hspace=0.5)
    fig.suptitle('Cell Parameters vs Birth Label')

    sns.utils.despine()

    return fig, ax
//  [python]
def plotmulti_phase_paramtime(data, exps, window=30, figlabelcols=None, figlabelfontsize=SMALL_SIZE):
    '''
    Plots cell parameters over time using a scatter plot and a moving average.
    Plots multiple datasets onto one
    '''

    # lists for plotting and formatting
    plot_params = ['sb', 'elong_rate', 'sd', 'tau', 'delta', 'septum_position']

    # create figure, going to apply graphs to each axis sequentially
    fig, axes = plt.subplots(nrows=3, ncols=2, figsize=[8,10])
    ax = np.ravel(axes)

    # Now plot the filtered data
    for ax_i, plot_param in enumerate(plot_params):

        fig, ax = plot_time(data=data, exps=exps,
                            plot_param=plot_param,
                            fig=fig, ax=ax, ax_i=ax_i,
                            df_key='df',
                            window=window)

    ax[4].set_xlabel('birth time (hours)')
    ax[5].set_xlabel('birth time (hours)')

    # legend for whole figure
    fig_legend_labels = [data[exp]['name'] for exp in exps]
    handles, _ = ax[0].get_legend_handles_labels()
    if figlabelcols == None:
        figlabelcols = int(len(exps)/2)
    fig.legend(handles, fig_legend_labels,
               ncol=figlabelcols, loc=8, fontsize=figlabelfontsize, frameon=False)

    # sns.despine()
    sns.despine()
    plt.tight_layout()
    fig.align_labels()
    plt.subplots_adjust(top=0.925, bottom=0.1, hspace=0.35)
    fig.suptitle('Parameters over time')

    return fig, ax
//  [python]
def plotmulti_phase_paramtime(data, exps, window=30, figlabelcols=None, figlabelfontsize=SMALL_SIZE):
    '''
    Plots cell parameters over time using a scatter plot and a moving average.
    Plots multiple datasets onto one
    '''

    # lists for plotting and formatting
    plot_params = ['sb', 'elong_rate', 'sd', 'tau', 'delta', 'septum_position']

    # create figure, going to apply graphs to each axis sequentially
    fig, axes = plt.subplots(nrows=3, ncols=2, figsize=[8,10])
    ax = np.ravel(axes)

    # Now plot the filtered data
    for ax_i, plot_param in enumerate(plot_params):

        fig, ax = plot_time(data=data, exps=exps,
                            plot_param=plot_param,
                            fig=fig, ax=ax, ax_i=ax_i,
                            df_key='df',
                            window=window)

    ax[4].set_xlabel('birth time (hours)')
    ax[5].set_xlabel('birth time (hours)')

    # legend for whole figure
    fig_legend_labels = [data[exp]['name'] for exp in exps]
    handles, _ = ax[0].get_legend_handles_labels()
    if figlabelcols == None:
        figlabelcols = int(len(exps)/2)
    fig.legend(handles, fig_legend_labels,
               ncol=figlabelcols, loc=8, fontsize=figlabelfontsize, frameon=False)

    # sns.despine()
    sns.utils.despine()
    plt.tight_layout()
    fig.align_labels()
    plt.subplots_adjust(top=0.925, bottom=0.1, hspace=0.35)
    fig.suptitle('Parameters over time')

    return fig, ax
//  [python]
def plot_feather_traces(Cells, trace_limit=1000, color='b', time_int=1, title='Cell traces'):
    '''
    Plot length traces of all cells over time.

    Parameters
    ----------
    trace_limit : int
        Limit the number of traces to this value, chosen randomly from the dictionary Cells.
        Plotting all the traces can be time consuming and mask the trends in the graph.
    color : matplotlib color
        color to plot traces
    time_int : int or float
        Number of minutes per frame. Used to adjust timing.
    '''

    fig, axes = plt.subplots(ncols=1, nrows=1, figsize=(8, 4))
    ax = [axes] # same as axes.ravel()

    if trace_limit and trace_limit < len(Cells):
        cell_id_subset = sample(list(Cells), trace_limit)
        Cells = {cell_id : Cells[cell_id] for cell_id in cell_id_subset}

    # adjust time so it is in hours from first cell
    Cells_df = cells2df(Cells)
    first_time = Cells_df['birth_time'].min()
    first_time = first_time * time_int / 60.0

    for cell_id, Cell in six.iteritems(Cells):
        times = np.array(Cell.times_w_div) * time_int / 60.0 - first_time

        ax[0].plot(times, Cell.lengths_w_div, 'b-', lw=.5, alpha=0.25,
                   color=color)

    ax[0].set_xlabel('time (hours)')
    # ax[0].set_xlim(0, None)
    ax[0].set_ylabel('length ' + pnames['um'])
    ax[0].set_ylim(0, None)

    sns.despine()
    plt.tight_layout()
    plt.subplots_adjust(top=0.925)
    fig.suptitle(title)

    return fig, ax
//  [python]
def plot_feather_traces(Cells, trace_limit=1000, color='b', time_int=1, title='Cell traces'):
    '''
    Plot length traces of all cells over time.

    Parameters
    ----------
    trace_limit : int
        Limit the number of traces to this value, chosen randomly from the dictionary Cells.
        Plotting all the traces can be time consuming and mask the trends in the graph.
    color : matplotlib color
        color to plot traces
    time_int : int or float
        Number of minutes per frame. Used to adjust timing.
    '''

    fig, axes = plt.subplots(ncols=1, nrows=1, figsize=(8, 4))
    ax = [axes] # same as axes.ravel()

    if trace_limit and trace_limit < len(Cells):
        cell_id_subset = sample(list(Cells), trace_limit)
        Cells = {cell_id : Cells[cell_id] for cell_id in cell_id_subset}

    # adjust time so it is in hours from first cell
    Cells_df = cells2df(Cells)
    first_time = Cells_df['birth_time'].min()
    first_time = first_time * time_int / 60.0

    for cell_id, Cell in six.iteritems(Cells):
        times = np.array(Cell.times_w_div) * time_int / 60.0 - first_time

        ax[0].plot(times, Cell.lengths_w_div, 'b-', lw=.5, alpha=0.25,
                   color=color)

    ax[0].set_xlabel('time (hours)')
    # ax[0].set_xlim(0, None)
    ax[0].set_ylabel('length ' + pnames['um'])
    ax[0].set_ylim(0, None)

    sns.utils.despine()
    plt.tight_layout()
    plt.subplots_adjust(top=0.925)
    fig.suptitle(title)

    return fig, ax
//  [python]
def summary_plot(
    df, variables, ylabels, yscales, lin_trends, legend, savename, axlabels=None
):

    # initialize figure
    fig, axs = plt.subplots(
        1, len(variables), figsize=(4 * len(variables), 3.5), squeeze=False
    )

    # summary plot for each variable
    for nv, var in enumerate(variables):

        ax = axs[0, nv]
        single_plot(df, ax, var, lin_trend=lin_trends[nv], legend=legend[nv])

        # customize y-scale and y-label
        ysl = yscales[nv]
        if ysl is not None:
            ax.set_yscale(ysl)
        ax.set_ylabel(ylabels[nv])

    sns.despine(fig)
    plt.tight_layout()

    # add panel label
    if axlabels is not None:
        for nv, ax in enumerate(axs[0, :]):
            ax.text(
                -0.18,
                0.95,
                axlabels[nv],
                transform=ax.transAxes,
                size=15,
                weight="bold",
            )

    plt.savefig(savename)
    plt.close(fig)
//  [python]
def summary_plot(
    df, variables, ylabels, yscales, lin_trends, legend, savename, axlabels=None
):

    # initialize figure
    fig, axs = plt.subplots(
        1, len(variables), figsize=(4 * len(variables), 3.5), squeeze=False
    )

    # summary plot for each variable
    for nv, var in enumerate(variables):

        ax = axs[0, nv]
        single_plot(df, ax, var, lin_trend=lin_trends[nv], legend=legend[nv])

        # customize y-scale and y-label
        ysl = yscales[nv]
        if ysl is not None:
            ax.set_yscale(ysl)
        ax.set_ylabel(ylabels[nv])

    sns.utils.despine(fig)
    plt.tight_layout()

    # add panel label
    if axlabels is not None:
        for nv, ax in enumerate(axs[0, :]):
            ax.text(
                -0.18,
                0.95,
                axlabels[nv],
                transform=ax.transAxes,
                size=15,
                weight="bold",
            )

    plt.savefig(savename)
    plt.close(fig)
//  [python]
def plot_degree(degree_object: nx.Graph, output_file: str):
    """
    Diagnosis tool for the degree object. It takes a graph and plot its statistics

    :param degree_object: the graph to plot
    :param output_file: the path to save the file

    Example
    _______
    >>> graph = nx.complete_graph(100)
    >>> plot_degree(nx.degree(graph), "graph_degree")
    """

    D = dict(degree_object)
    degrees = {k: v for k, v in D.items()}
    degree_values = np.array(list(degrees.values()))

    fig, axes = plt.subplots(1, figsize=(10, 10))
    g1 = sns.distplot(degree_values, hist=True, ax=axes)

    key_max = max(degrees.keys(), key=(lambda k: degrees[k]))
    g1 = sns.distplot([degrees[key_max]], hist=False, kde=False, rug=True, color='r', ax=axes)
    axes.annotate('%s: %d' % (key_max, degrees[key_max]), xy=(degrees[key_max], 0),
                  xytext=(degrees[key_max], axes.dataLim.y1 / 2), arrowprops=dict(arrowstyle="->"))

    g1 = sns.distplot([np.median(degree_values)], hist=False, kde=False, rug=True, color='r', ax=axes)
    axes.annotate('median %f' % np.median(degree_values), xy=(np.median(degree_values), 0),
                  xytext=(np.median(degree_values), axes.dataLim.y1 / 2), arrowprops=dict(arrowstyle="->"))

    sns.despine(ax=axes, top=True, bottom=False, right=True, left=True)
    g1.set_ylabel("Density")
    g1.set_xlabel("Node Degree")

    if output_file.endswith('.pdf'):
        plt.savefig(output_file, format="pdf")
    elif output_file.endswith('.png'):
        plt.savefig(output_file, format="png")
    else:
        logging.warning('The null distribution figure can only be saved in pdf or png, forced to png')
        fig.savefig(output_file + '.png', format="png")
//  [python]
def plot_degree(degree_object: nx.Graph, output_file: str):
    """
    Diagnosis tool for the degree object. It takes a graph and plot its statistics

    :param degree_object: the graph to plot
    :param output_file: the path to save the file

    Example
    _______
    >>> graph = nx.complete_graph(100)
    >>> plot_degree(nx.degree(graph), "graph_degree")
    """

    D = dict(degree_object)
    degrees = {k: v for k, v in D.items()}
    degree_values = np.array(list(degrees.values()))

    fig, axes = plt.subplots(1, figsize=(10, 10))
    g1 = sns.distplot(degree_values, hist=True, ax=axes)

    key_max = max(degrees.keys(), key=(lambda k: degrees[k]))
    g1 = sns.distplot([degrees[key_max]], hist=False, kde=False, rug=True, color='r', ax=axes)
    axes.annotate('%s: %d' % (key_max, degrees[key_max]), xy=(degrees[key_max], 0),
                  xytext=(degrees[key_max], axes.dataLim.y1 / 2), arrowprops=dict(arrowstyle="->"))

    g1 = sns.distplot([np.median(degree_values)], hist=False, kde=False, rug=True, color='r', ax=axes)
    axes.annotate('median %f' % np.median(degree_values), xy=(np.median(degree_values), 0),
                  xytext=(np.median(degree_values), axes.dataLim.y1 / 2), arrowprops=dict(arrowstyle="->"))

    sns.utils.despine(ax=axes, top=True, bottom=False, right=True, left=True)
    g1.set_ylabel("Density")
    g1.set_xlabel("Node Degree")

    if output_file.endswith('.pdf'):
        plt.savefig(output_file, format="pdf")
    elif output_file.endswith('.png'):
        plt.savefig(output_file, format="png")
    else:
        logging.warning('The null distribution figure can only be saved in pdf or png, forced to png')
        fig.savefig(output_file + '.png', format="png")
//  [python]
def plot_violin(df, y=0.61):
    '''use the reduced dataframe as input (e.g. use only brain variants).'''
    
    df = df[df.MAX_MAF_25_BOOL == True]
    
    sns.violinplot(x='SET_MOSAIC', y='MAF', data=df, inner=None, color='0.4',
                   cut=0)
    
    plt.xlabel('Mosaic Variants')
    plt.xticks(ticks=[], labels=[])
    plt.yticks(ticks=[0, 0.3, 0.6])
    plt.ylabel('')
    plt.ylim(0,y)
    sns.despine(bottom=True, offset=5, trim=True)
    plt.show()
//  [python]
def plot_violin(df, y=0.61):
    '''use the reduced dataframe as input (e.g. use only brain variants).'''
    
    df = df[df.MAX_MAF_25_BOOL == True]
    
    sns.violinplot(x='SET_MOSAIC', y='MAF', data=df, inner=None, color='0.4',
                   cut=0)
    
    plt.xlabel('Mosaic Variants')
    plt.xticks(ticks=[], labels=[])
    plt.yticks(ticks=[0, 0.3, 0.6])
    plt.ylabel('')
    plt.ylim(0,y)
    sns.utils.despine(bottom=True, offset=5, trim=True)
    plt.show()
//  [python]
def plot_line(df, x=300, y=0.51):
    '''use the reduced dataframe as input (e.g. use only brain variants).'''
    
    df = df[df.MAX_MAF_25_BOOL == True]
    df = df.sort_values(by=['MAF'], ascending=False)
    df = df.reset_index(drop=True).reset_index()
    plt.fill_between((df.iloc[:,0] + 1), df['UPPER_CI'], df['LOWER_CI'],
                     color='0.8')
    plt.plot((df.iloc[:,0] + 1), df['MAF'], color='g')
    plt.xlabel('Ranked Mosaic Variants')
    plt.ylabel('Allelic Fraction')
    plt.xlim(0,x)
    plt.ylim(0,y)
    sns.despine(offset=5, trim=True)
    plt.show()
//  [python]
def plot_line(df, x=300, y=0.51):
    '''use the reduced dataframe as input (e.g. use only brain variants).'''
    
    df = df[df.MAX_MAF_25_BOOL == True]
    df = df.sort_values(by=['MAF'], ascending=False)
    df = df.reset_index(drop=True).reset_index()
    plt.fill_between((df.iloc[:,0] + 1), df['UPPER_CI'], df['LOWER_CI'],
                     color='0.8')
    plt.plot((df.iloc[:,0] + 1), df['MAF'], color='g')
    plt.xlabel('Ranked Mosaic Variants')
    plt.ylabel('Allelic Fraction')
    plt.xlim(0,x)
    plt.ylim(0,y)
    sns.utils.despine(offset=5, trim=True)
    plt.show()
//  [python]
def _count_bar_(tdf, figsize, title='', color='pink',
                ylabel = 'Number of Metabolite-Sensor Communication', 
                pdf=None, show_plot = False, return_fig = False):
    fig, ax = plt.subplots(figsize = figsize)
    xtick = list(np.arange(0, len(tdf) * 2, 2))
    ax.bar(xtick, tdf.tolist(), color = color)

    for i in range(len(xtick)):
        ax.text(x=xtick[i], y=tdf.tolist()[i],
                s=int(tdf.tolist()[i]),
                ha = 'center',
                va = 'bottom',
                fontsize = 8
               )

    plt.xticks(ticks = xtick,
                labels = tdf.index.tolist())

    ax.set_title(title,
            pad = 10, fontweight = 'bold')

    ax.tick_params(axis = 'x', which = 'major',
                   rotation = 90, size = 12)

    ax.set_xlabel('')
    ax.set_ylabel(ylabel)
    ax.set_xlim(-1, len(xtick)*2+1)

    sns.despine(trim = True)
    plt.tight_layout()
    pdf.savefig(fig) if pdf else None
    plt.show() if show_plot else None
    plt.close()
    if return_fig:
        return(fig)
//  [python]
def _count_bar_(tdf, figsize, title='', color='pink',
                ylabel = 'Number of Metabolite-Sensor Communication', 
                pdf=None, show_plot = False, return_fig = False):
    fig, ax = plt.subplots(figsize = figsize)
    xtick = list(np.arange(0, len(tdf) * 2, 2))
    ax.bar(xtick, tdf.tolist(), color = color)

    for i in range(len(xtick)):
        ax.text(x=xtick[i], y=tdf.tolist()[i],
                s=int(tdf.tolist()[i]),
                ha = 'center',
                va = 'bottom',
                fontsize = 8
               )

    plt.xticks(ticks = xtick,
                labels = tdf.index.tolist())

    ax.set_title(title,
            pad = 10, fontweight = 'bold')

    ax.tick_params(axis = 'x', which = 'major',
                   rotation = 90, size = 12)

    ax.set_xlabel('')
    ax.set_ylabel(ylabel)
    ax.set_xlim(-1, len(xtick)*2+1)

    sns.utils.despine(trim = True)
    plt.tight_layout()
    pdf.savefig(fig) if pdf else None
    plt.show() if show_plot else None
    plt.close()
    if return_fig:
        return(fig)
//  [python]
def _histogram_(commu_mat,
                 commu_bg, 
                 title = '', 
                 pdf = False, 
                 show_plot = False,
                 bins = 100,
                 alpha = .6,
                 bg_color = 'grey',
                 obs_color = 'red',
                 figsize = (5.5, 4.2),
                 comm_score_col = 'Commu_Score',
                 return_fig = False):
    """
    plot histogram to show the distribution of communication in given pair of metabolite and sensor
    """
    ## visulize
    bg_values = []
    for x in commu_bg.iloc[:,2:commu_bg.shape[1]].values:
        bg_values.extend(x)
    fig, ax = plt.subplots(figsize=figsize)
    ax.hist(bg_values, bins = bins, #density = True,
            label = 'Background', alpha = alpha, color = bg_color)
    ymin, ymax = ax.get_ylim()
    n = 0
    for i in commu_mat[comm_score_col].tolist():
        ax.vlines(x = i, ymin = ymin, ymax = ymax*0.1, colors = obs_color,
                 alpha = alpha, label = 'Observed' if n == 0 else None)
        n += 1
#     ax.hist(commu_mat[comm_score_col], bins = bins, density = True,
#             label = 'Observed C', alpha = alpha, color = obs_color)
    ax.set_ylabel('Count')
    ax.set_xlabel('Communication Score')
    ax.set_title(title)
    ax.legend()
    sns.despine()
    plt.tight_layout()
    pdf.savefig(fig) if pdf else None
    if show_plot:
        plt.show()
    plt.close()
    if return_fig:
        return(fig)
//  [python]
def _histogram_(commu_mat,
                 commu_bg, 
                 title = '', 
                 pdf = False, 
                 show_plot = False,
                 bins = 100,
                 alpha = .6,
                 bg_color = 'grey',
                 obs_color = 'red',
                 figsize = (5.5, 4.2),
                 comm_score_col = 'Commu_Score',
                 return_fig = False):
    """
    plot histogram to show the distribution of communication in given pair of metabolite and sensor
    """
    ## visulize
    bg_values = []
    for x in commu_bg.iloc[:,2:commu_bg.shape[1]].values:
        bg_values.extend(x)
    fig, ax = plt.subplots(figsize=figsize)
    ax.hist(bg_values, bins = bins, #density = True,
            label = 'Background', alpha = alpha, color = bg_color)
    ymin, ymax = ax.get_ylim()
    n = 0
    for i in commu_mat[comm_score_col].tolist():
        ax.vlines(x = i, ymin = ymin, ymax = ymax*0.1, colors = obs_color,
                 alpha = alpha, label = 'Observed' if n == 0 else None)
        n += 1
#     ax.hist(commu_mat[comm_score_col], bins = bins, density = True,
#             label = 'Observed C', alpha = alpha, color = obs_color)
    ax.set_ylabel('Count')
    ax.set_xlabel('Communication Score')
    ax.set_title(title)
    ax.legend()
    sns.utils.despine()
    plt.tight_layout()
    pdf.savefig(fig) if pdf else None
    if show_plot:
        plt.show()
    plt.close()
    if return_fig:
        return(fig)
//  [python]
def plot_sml_morethan1tissues(df, y=50):
    '''Plot bars countig the number of variants that are present in each sml
    region and that are not only found in 1 tissue.'''
    
    df = df[(~(df.SET_ONE_TISSUE)) & (df.IN_25 == True) &
            (df.LG_SM == 'Sml')].sort_values(by=['ORGAN_SORTER', 'L_R'])
    
    sns.countplot(x='BRAIN_REGION', hue='L_R', data=df,
                  order=['PF', 'F', 'P', 'O', 'T'], edgecolor='k')
    
    plt.ylim(0, y)
    plt.ylabel('Number of Variants')
    plt.xlabel('Cortical Lobes')
    sns.despine(bottom=True, offset=5, trim=True)
    
    plt.show()