GetDist: Showing 1D constrain on 2D plane

Use of Cobaya. camb, CLASS, cosmomc, compilers, etc.
Post Reply
José Ferreira
Posts: 7
Joined: August 27 2021
Affiliation: Faculdade de Ciências da Universidade de Lisboa

GetDist: Showing 1D constrain on 2D plane

Post by José Ferreira » August 12 2022

Hi,

First of all, apologies if the title is not very clear, but I don't know how to summarize what I'm trying to achieve any better.

Using my specific case as an example, I have a dataset which constrains my model in both parameters $h$ and $\Omega_m$, whereas the other dataset only sets constrains on $\Omega_m$.
If I try to plot them together, it looks like the following:
Image

You can immediately see two problems which I'm trying to tackle:
1. The constrains don't show up on the $h$ vs $\Omega_m$ plane as a rectangle with the corresponding 1$\sigma$ and 2$\sigma$ regions;
2. The legend for the 1D constrains on $\Omega_m$ isn't rendered by GetDist.

I used GIMP to show how I would like this plot to look like:
Image

However, after searching around in this forum and in the documentation, I found no solution to either of these problems and therefore would like to ask for assistance.
Ideas for workarounds to these issues included manually looking at the regions provided by the plot in red and using matplotlib itself trying to add the region my hand but I failed to do that. The same thing happened for the legend.

Thanks in advance.


José Ferreira
Posts: 7
Joined: August 27 2021
Affiliation: Faculdade de Ciências da Universidade de Lisboa

Re: GetDist: Showing 1D constrain on 2D plane

Post by José Ferreira » August 15 2022

Ah, I should have seen that one, many thanks.

With respect to the legend, I didn't found a good solution to the problem, as no matter what, it doesn't seem to be able to add a legend when one of the dataset is only present in 1D.
So what I did what finding a (very awful) workaround by disabling the legend of the plot and creating one by hand.
Here's a snippet of what the code looks like, in case somebody is interested or wishes to improve on this solution:

Code: Select all

# also assume the required packages are being imported
# assume that mcsamples is a set of samples from an MCMC...

# init and config plot
markers = None
contour_alpha = 0.5
colors = ["#006FED", "#E03424", "#008000"]
contour_colors = ["#006FED", "#E03424", "#008000"]
g = plots.get_subplot_plotter()
g.settings.alpha_factor_contour_lines=contour_alpha
g.settings.line_labels = False

# plot samples
g.triangle_plot(mcsamples, filled=True, markers=markers, contour_colors=contour_colors, colors=colors, param_limits={"h": [0.67, 0.72], "Omega_m": [0.2, 0.37]})

# add horizontal region to plot
g.add_y_bands(0.3353, 0.0091, color="#008000", ax=(1,0), zorder=0.5, alpha1=0.7, alpha2=0.35)

# awful workaround to create custom legend without being attached to axis
# required because the legend for the 1D SNIa (or the horizontal region) isn't showing
class AnyObject:
    pass
class AnyObject2:
    pass
class AnyObject3:
    pass

class AnyObjectHandler:
    def __init__(self, color):
        self.color = color

    def legend_artist(self, legend, orig_handle, fontsize, handlebox):
        x0, y0 = handlebox.xdescent, handlebox.ydescent
        width, height = handlebox.width, handlebox.height
        patch = mpatches.Rectangle([x0, y0], width, height, facecolor=self.color)
        handlebox.add_artist(patch)
        return patch

legends = ["ET", "ET + Pantheon (binned)", "Pantheon (binned)"]
g.fig.legend([AnyObject(), AnyObject2(), AnyObject3()], legends, handler_map={AnyObject: AnyObjectHandler("#006FED"), AnyObject2: AnyObjectHandler("#E03424"), AnyObject3: AnyObjectHandler("#008000")})

# show corner plot
plt.show()

Antony Lewis
Posts: 1936
Joined: September 23 2004
Affiliation: University of Sussex
Contact:

Re: GetDist: Showing 1D constrain on 2D plane

Post by Antony Lewis » August 15 2022

For the legend, you could try adding, immediately after (and in the 'else')
https://github.com/cmbant/getdist/blob/master/getdist/plots.py#L1893

the backup code:

Code: Select all

 
 for i, contour in enumerate(lines):
     if contour is None:
         args = self.lines_added.get(i)
         if args:
             args.pop('filled', None)
             lines[i] = matplotlib.lines.Line2D([0, 1], [0, 1], **args)

Post Reply