Python scripts for plotting, analysing and grids of runs

See the ./python directory for scripts, which mostly require Python 2.7+. To configure your system to work with the script libraries add CosmoMC's python path to your environment variables, e.g. in ~/.bashrc (or ~/bash_profile, etc):
export PYTHONPATH=COSMOMC..PATH/python:$PYTHONPATH
where COSOMC..PATH is the full path of wherever you installed CosmoMC. If you have problems on a Mac or need to install python, see Installing Python.

Scripts for plotting and analysing are described below. See also grid scripts and GetDist GUI documentation. For plotting from Planck chains see the Planck readme for how to download and install.

Plotting scripts

GetDistPlots (directly, or via planckStyle) are used to make plots from chain results using your own custom scripts. For
grids of chains, as the Planck downloads, you can also use python python/makePlots.py PLA .. to make plots (en masse if you wish) for quick inspection of grid results.

The sample scripts make use of planckStyle. This can be interchanged with GetDistPlots if you do not want to use the Planck style (or some extra functions used in the batch2/output samples). Both implement the functions

The GetDistPlotter main plotting class is defined in python/GetDistPlots.py. For example you can do
import planckStyle

g = planckStyle.getSinglePlotter(chain_dir = './PLA')

roots = ['base_nnu_mnu_plikHM_TT_lowTEB', 'base_nnu_mnu_plikHM_TT_lowTEB_lensing', 'base_nnu_mnu_plikHM_TT_lowTEB_lensing_post_BAO']
g.plot_2d(roots, 'mnu', 'nnu', filled=True)
g.add_legend(['Planck', 'Planck+lensing', 'Planck+lensing+BAO'], legend_loc='upper right');
g.export('mnu_nnu.png')
The chain_dir argument can be neglected if you have set up a default in config.ini. You can do "from pylab import *" and use standard matplotlib commands to customize the plots, and there are also many plot script options you can use to customize settings, and also change global getdist plot settings using g.settings.xxx. For example:
import planckStyle

g = planckStyle.getSinglePlotter(chain_dir = './PLA', ratio=1)

roots = ['base_nnu_mnu_plikHM_TT_lowTEB', 'base_nnu_mnu_plikHM_TT_lowTEB_lensing', 'base_nnu_mnu_plikHM_TT_lowTEB_lensing_post_BAO']
g.settings.solid_contour_palefactor = 0.8
g.plot_2d(roots, 'mnu', 'nnu', filled=True, colors=['orange', 'darkred', 'green'], lims=[0, 1.3, 2, 4.2])
g.add_legend(['Planck', 'Planck+lensing', 'Planck+lensing+BAO'], legend_loc='upper right', colored_text=True);
g.add_y_marker(3.046)
g.export('mnu_nnu2.png')
Outputs of the two versions should look like this:

See python/GetDistPlots.py for the various functions and options available, and the sample scripts in batch2/outputs.

The main functions for making single plots are:

    def plot_1d(self, roots, param, marker=None, marker_color=None, label_right=False,
                no_ylabel=False, no_ytick=False, no_zero=False, normalized=False, param_renames={}, **kwargs):
    def plot_2d(self, roots, param1=None, param2=None, param_pair=None, shaded=False, add_legend_proxy=True, **kwargs):
    def plot_3d(self, roots, in_params=None, params_for_plots=None, color_bar=True, line_offset=0, add_legend_proxy=True, **kwargs):

    def add_legend(self, legend_labels, legend_loc=None, line_offset=0, legend_ncol=None, colored_text=False,
                   figure=False, ax=None, label_order=None, align_right=False, fontsize=None):
These functions make sets of subplots:
    def plots_1d(self, roots, params=None, legend_labels=None, legend_ncol=None, label_order=None, nx=None,
                 paramList=None, roots_per_param=False, share_y=None, markers=None, xlims=None, param_renames={}):
    def plots_2d(self, roots, param1=None, params2=None, param_pairs=None, nx=None, legend_labels=None, legend_ncol=None,
                 label_order=None, filled=False):
    def triangle_plot(self, roots, in_params=None, legend_labels=None, plot_3d_with_param=None, filled=False, filled_compare=False, shaded=False,
                      contour_args=None, contour_colors=None, contour_ls=None, contour_lws=None, line_args=None, label_order=None):
    def rectangle_plot(self, xparams, yparams, yroots=None, roots=None, plot_roots=None, plot_texts=None,
                       ymarkers=None, xmarkers=None, param_limits={}, legend_labels=None, legend_ncol=None,
                       label_order=None, marker_args={}, **kwargs):
These functions give more fine grained control for adding things to a figure:
    def make_figure(self, nplot=1, nx=None, ny=None, xstretch=1, ystretch=1):

    def add_1d(self, root, param, plotno=0, normalized=False, **kwargs)

    def add_2d_contours(self, root, param1=None, param2=None, plotno=0, of=None, cols=None,
                            add_legend_proxy=True, param_pair=None, density=None, alpha=None, **kwargs):
    def add_2d_shading(self, root, param1, param2):
    def add_3d_scatter(self, root, in_params, color_bar=True, alpha=1, extra_thin=1, **ax_args):

    def finish_plot(self, legend_labels=None, legend_loc=None, line_offset=0, legend_ncol=None, label_order=None, no_gap=False, no_extra_legend_space=False, no_tight=False):
        has_legend = self.settings.line_labels and legend_labels and len(legend_labels) > 1
Utility function add annotation and markers to plots:
    def add_x_marker(self, marker, color=None, ls=None, lw=None):
    def add_y_marker(self, marker, color=None, ls=None, lw=None):
    def add_y_bands(self, y, sigma, xlim=None, color='gray', ax=None, alpha1=0.15, alpha2=0.1):
    def add_text(self, text_label, x=0.95, y=0.06, ax=None, **kwargs):
    def add_text_left(self, text_label, x=0.05, y=0.06, ax=None, **kwargs):
Finally there's the export function:
    def export(self, fname=None, adir=None, watermark=None, tag=None):
Plus additional function that you can find in the source code for GetDistPlots.py.

Analysis scripts

The GetDist program can be used to get means, variances, limits etc from all parameters in a chain. The python scripts allow you to do this dynamically, and also offer additional features such as being able to define new derived parameters.

Calculating derived parameters

For simple calculations like finding the mean and variance of new derived parameters you can use the functions in python/chains.py. For example, if you want to calculate the posterior mean and limits for σ8 Ωm0.6 from Planck you could write a python script
import GetDistPlots as s

g = s.getSinglePlotter(chain_dir=r'./PLA')

samples = g.sampleAnalyser.samplesForRoot('base_plikHM_TT_lowTEB_lensing')

p = samples.getParams()

derived = p.sigma8 * p.omegam ** 0.6

print 'mean, err = ', samples.mean(derived), samples.std(derived)
print '95% limits: ', samples.twoTailLimits(derived, 0.95)
Here p.omegam is a vector of parameter values, similar p.sigma8; samples.mean and samples.std sum the samples with the corresponding weights to calculate the result.

See python/getdist/chains.py and python/getdist/MCSamples.py for other functions you can use. Use GetDist or MCSamples.py if you want to reproduce Planck results: chains.py only does tail integrals, it does not check for skewness or calculate credible intervals for skewed distributions. MCSamples gives you code access to most getdist results.

For example if you want to do a power law fit in the variable Ωm and H0, you could do

import GetDistPlots as s

g = s.getSinglePlotter(chain_dir=r'./PLA')
samples = g.sampleAnalyser.samplesForRoot('base_plikHM_TT_lowTEB')

print samples.PCA(['omegam', 'H0'], 'LL', 'omegam')
which fits Ωm and H0, using log transforms (L), normalized so the exponent of Ωm is unity (as in GetDist PCA outputs). The output includes
Principle components
PC1 (e-value: 0.006151)
[0.042284]  (\Omega_m/0.314833)^{1.000000}
[0.042284]  (H_0/67.300590)^{2.971216}
          = 1.000011 +- 0.004690
ND limits:     0.984    1.017    0.983    1.019
which tells you that ΩmH02.97is constrained at the 0.4% level.

Adding and plotting new derived parameters

You can use the addDerived function of MCSamples to add a new parameter to existing chains, which can then be used like any of the original parameters. An example gives the idea (from batch2/outputs/DA-H-BAO.py), which adds a new parameter with name tag 'rsH' which is a function of the original parameters 'Hubble057' and 'rdrag':
    p = samples.getParams()
    rd_fid = 149.28
    rsH = p.Hubble057 * p.rdrag / rd_fid
    samples.addDerived(rsH, name='rsH', label=r'H(0.57) (r_{\mathrm{drag}}/r_{\mathrm{drag}}^{\rm fid})\, [{\rm km} \,{\rm s}^{-1}{\rm Mpc}^{-1}]')
    samples.updateChainBaseStatistics()
The last line is needed to ensure caches etc are cleared, but only needs to be called once if you are adding several new parameters. After doing this, you can use 'rsH' as you would any of the original parameter names in the chain.

Other scripts

Multi-purpose use and utility scripts include

Installing Python Windows

See the Python 2.7 download. Also install Matplotlib and PySide standard packages using standard methods, or download builds from here.

Installing Python on a Mac

There are several options, here's one: Check that python --version says 2.7.9. If not, edit your system path to remove other python installations.

Writing Python

While not needed for GetDist/Cosmomc scripts to run, you may also find an integrated development environment like PyDev or PyCharm useful (they are similar). This will let you run in one click, check syntax as you type, format nicely, etc.