Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format the corner plot in python?

Tags:

python

plot

mcmc

I have some package like emcee which runs mcmc algorithm for my model fitting. Once I have the postsample chain, I use the package corner to produce corner plot. Some of my parameters are very large number while others are small numbers. Because of this, the plot looks very weird (shown in the figure attached).enter image description here

Is there a way to display large numbers in scientific notation while small number as float? The x-axis tick label already has this. I would like the same for the fit result titles.

like image 395
konstant Avatar asked Oct 30 '25 10:10

konstant


1 Answers

Use title_fmt

You can format the title with the kwarg title_fmt:

title_fmt : string

    The format string for the quantiles given in titles. If you explicitly
    set ``show_titles=True`` and ``title_fmt=None``, the labels will be
    shown as the titles. (default: ``.2f``)

In your case, you might set title_fmt=".2E"

Example

Before specifying title_fmt:

before

After specifying title_fmt=".2E":

after

Code for example

# -*- coding: utf-8 -*-
"""Corner on top of each other"""
import corner
import matplotlib.lines as mlines
import matplotlib.pyplot as plt
import numpy as np

CORNER_KWARGS = dict(
    smooth=0.9,
    label_kwargs=dict(fontsize=16),
    title_kwargs=dict(fontsize=16),
    quantiles=[0.16, 0.84],
    levels=(1 - np.exp(-0.5), 1 - np.exp(-2), 1 - np.exp(-9 / 2.)),
    plot_density=False,
    plot_datapoints=False,
    fill_contours=True,
    show_titles=True,
    max_n_ticks=3,
    title_fmt=".2E"
)


def overlaid_corner(samples_list, sample_labels):
    """Plots multiple corners on top of each other"""
    # get some constants
    n = len(samples_list)
    _, ndim = samples_list[0].shape
    max_len = max([len(s) for s in samples_list])
    cmap = plt.cm.get_cmap('gist_rainbow', n)
    colors = [cmap(i) for i in range(n)]

    plot_range = []
    for dim in range(ndim):
        plot_range.append(
            [
                min([min(samples_list[i].T[dim]) for i in range(n)]),
                max([max(samples_list[i].T[dim]) for i in range(n)]),
            ]
        )

    CORNER_KWARGS.update(range=plot_range)

    fig = corner.corner(
        samples_list[0],
        color=colors[0],
        **CORNER_KWARGS
    )

    for idx in range(1, n):
        fig = corner.corner(
            samples_list[idx],
            fig=fig,
            weights=get_normalisation_weight(len(samples_list[idx]), max_len),
            color=colors[idx],
            **CORNER_KWARGS
        )

    plt.legend(
        handles=[
            mlines.Line2D([], [], color=colors[i], label=sample_labels[i])
            for i in range(n)
        ],
        fontsize=20, frameon=False,
        bbox_to_anchor=(1, ndim), loc="upper right"
    )
    plt.savefig("orig_corner.png")
    plt.close()


def get_normalisation_weight(len_current_samples, len_of_longest_samples):
    return np.ones(len_current_samples) * (len_of_longest_samples / len_current_samples)


def main():
    ndim, nsamples = 3, 10000
    np.random.seed(2000)
    samples = np.random.randn(ndim * nsamples).reshape([nsamples, ndim]) * 1e9

    overlaid_corner(
        [samples * 3, samples * 2, samples],
        ["samples x 3", "samples x 2", "samples"]
    )


if __name__ == "__main__":
    main()


like image 80
Avi Vajpeyi Avatar answered Nov 01 '25 23:11

Avi Vajpeyi