Plotting results ================ The outputs of parameter estimation performed by CWInPy are in the form of bilby :class:`~bilby.core.result.Result` or :class:`~bilby.core.grid.Grid` objects, for posterior samples or posteriors evaluated on a grid, respectively. The :class:`~bilby.core.result.Result` object itself has various methods for plotting the posteriors: * :meth:`~bilby.core.result.Result.plot_corner` * :meth:`~bilby.core.result.Result.plot_marginals` * :meth:`~bilby.core.result.Result.plot_single_density` However, CWInPy also provides a :class:`~cwinpy.plot.Plot` class for producing plots. This makes use of various plotting functions from the `PESummary `_ package [1]_ and `corner.py `_ [2]_ and can overplot posterior results from multiple different detectors/samplers. A selection of example plots are shown below, which are selected in :class:`~cwinpy.plot.Plot` class using the ``plottype`` argument: * "hist": produce a histogram of posterior samples for a single parameter (the ``kde`` option can be used to also overplot a kernel density estimate of the posterior); * "kde": produce a kernel density estimate using posterior samples for a single parameter; * "corner": produce what is known as a corner, or triangle, plot of posterior distributions for two or more parameters in this case produced with the `corner.py `_ [2]_ package; * "triangle": a different style of triangle plot (as produced by the `PESummary `_ package [1]_) that can only be used for pairs of parameters; * "reverse_triangle": another style of triangle plot (as produce by the `PESummary `_ package [1]_) that has the 1D distributions to the left/below rather than to the right/above the 2D distribution plot; * "contour": a contour plot that can be produced only for a pair of parameters. The examples are based on the outputs of the :ref:`Multiple detectors, software injection (circular polarisation)` example comparing CWInPy with the ``lalpulsar_parameter_estimation_nested`` code [3]_. Example: plotting 1D marginal posteriors ---------------------------------------- If we have a single bilby :class:`~bilby.core.result.Result` containing posterior samples saved to a file called ``cwinpy.hdf5`` and want to plot the posterior on the :math:`h_0` parameter this can be done with: .. code-block:: python from cwinpy.plot import Plot plot = Plot("cwinpy.hdf5", parameters="h0", plottype="hist", kde=True) plot.plot() plot.save("cwinpy.png", dpi=150) which will produce: .. thumbnail:: images/plotting_example1.png :width: 600px :align: center In the above code the ``kde=True`` keyword was used to also plot a kernel density estimate (KDE) of the posterior as well as a histogram. To just plot the histogram the ``kde`` keyword could be removed. To just plot a KDE without the histogram ``plottype="kde"`` can instead be used. Example: over-plotting multiple 1D posteriors --------------------------------------------- If we have multiple posterior results (e.g., from different detectors or from runs using different samplers) that we want to compare, these can be overplotted on the same figure. To do this we can pass a dictionary pointing to the various results. In this case we will overplot the :math:`\cos{\iota}` posterior results of running on a simulated pulsar signal using CWInPy to produce both posterior samples and an evaluation of the posterior on a grid, and using the ``lalpulsar_parameter_estimation_nested`` code, with: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters="cosiota", plottype="kde", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) which will produce: .. thumbnail:: images/plotting_example2.png :width: 600px :align: center In this example the ``pulsar`` keyword has been supplied pointing to a TEMPO(2)-style pulsar parameter file that contains the true *simulated* signal parameters, which are then overplotted with a vertical black line. To not overplot the true values this argument would be removed. Example: plotting 2D posteriors ------------------------------- We can also produce plots of pairs of parameters that include 1D marginalised posterior distributions and 2D joint posterior distributions (over-plotting multiple results as ): Corner plot ^^^^^^^^^^^ A "corner" plot, as produced with the `corner.py `_ [2]_ package, of a pair of parameters (in this case :math:`h_0` versus :math:`\cos{\iota}`) can be generated with, e.g.,: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters=["h0", "cosiota"], plottype="corner", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) which will produce: .. thumbnail:: images/plotting_example3.png :width: 600px :align: center .. note:: By default, a 2D distribution from any results in a :class:`~bilby.core.grid.Grid` will not be included. To add these the :meth:`~cwinpy.plot.Plot.plot` method can be passed the ``grid2d=True`` argument. Triangle plot ^^^^^^^^^^^^^ A different style of corner/triangle plot can be generated with, e.g.,: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters=["h0", "cosiota"], plottype="triangle", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) and will produce: .. thumbnail:: images/plotting_example4.png :width: 600px :align: center .. note:: This plot may take a bit of time to produce due to performing a bounded 2D kernel density estimate. Reverse triangle plot ^^^^^^^^^^^^^^^^^^^^^ Another style of corner plot, with the 1D marginal distributions shown below the 2D joint posterior plot, is a "reverse triangle" plot, which can be generated with, e.g.,: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters=["h0", "cosiota"], plottype="reverse_triangle", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) and will produce: .. thumbnail:: images/plotting_example5.png :width: 600px :align: center Contour plot ^^^^^^^^^^^^ A plot just containing the 2D posterior distribution, without the 1D marginal distributions, can be produced with: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters=["h0", "cosiota"], plottype="contour", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) and will produce: .. thumbnail:: images/plotting_example6.png :width: 600px :align: center Example: plotting multiple posteriors ------------------------------------- If wanting to plot posteriors for more than two parameters then only the "corner" plot option can be used. If we wanted to plot :math:`h_0`, :math:`\cos{\iota}`, :math:`\psi` and :math:`\phi_0` we could do: .. code-block:: python from cwinpy.plot import Plot plot = Plot( {"CWInPy": "cwinpy.hdf5", "lppen": "lppen.hdf5", "grid": "grid.json"}, parameters=["h0", "cosiota", "psi", "phi0"], plottype="corner", pulsar="simulation.par", ) plot.plot() plot.save("cwinpy.png", dpi=150) to produce: .. thumbnail:: images/plotting_example7.png :width: 600px :align: center Plotting API ------------ .. autoclass:: cwinpy.plot.Plot :members: Plotting references ------------------- .. [1] `C. Hoy & V. Raymond `_, *SoftwareX*, **15**, 100765 (2021) .. [2] `D. Foreman-Mackey `_, *JOSS*, **1**, 2, 24, (2016) .. [3] M. Pitkin, M. Isi, J. Veitch & G. Woan, `arXiv:1705.08978v1 `_ (2017)