How to add a new type of plot or table in validphys

So you want to make a plot or table of PDFs, data, covariance matrices etc.?

Pre-existing actions

First check whether there is already an action which makes this type of plot.

Some places to look:

Outline of approach

If there is no action for the plot you want, you can add your own!


Please follow the Code development! In particular, this means you should create a new branch of the code to make your edits on, then create a pull request, with reviewers, for merging into the master branch. This helps to avoid bugged actions being propagated.

  1. Locate the right place to put your plot/table. See the “places to look” above to find similar plots.

  2. Identify the inputs you need for your plot/table. For example, if you are plotting some \(\chi^2\)s you may need the action chi2_data as an input. Try searching in the relevant modules in validphys, using validphys --help or looking at the table of common inputs below.

  3. See if you can make use of functions in plotutils to help with making a plot.

  4. Write an action which takes the inputs and returns a figure or table.

  5. See Tools for developing with the Python programming language for general help on developing the python code. One approach is to make use of the IPython embed function. This allows you to play around with variables from inside the action you are making. Another is to use an IPython environment such as a Jupyter notebook, and obtain the necessary inputs using the API.

  6. Use the @figure decorator for figures and @table decorator for tables. This means that the output will be saved in output/figures and output/tables respectively.

Common inputs

Input name


pdf or pdfs


fit or fits



Name of the grouping for data, e.g. experiment or nnpdf31_process


Dataframe index for grouped data


(Data, Theory) tuples for each group of data


DataSetSpec objects for each group


Theory central values


Data central values


Experimental covariance matrix


Scale variation theory covariance matrix


Chi2Data namedtuple with entries replica_result, central_result and ndata for total \(\chi^2\), not including any correlations outwith experiments


Chi2Data namedtuple for all groups


PDF replicas


Two ( \(x\), \(Q^2\) ) tuples, one for fitted data and one for cut data, for each of the dataset_inputs

Worked example for plotting \(\phi\)

Say we want to make a plot which shows the breakdown of the \(\phi\) values by group. This action actually already exists, and it’s called plot_phi, but we will use it as an example. First we have a look in dataplots to see if there are similar actions. We can see that there is already an action called plot_groups_data_chi2 which does something similar but for \(\chi^2\)s instead. It looks like this:

def plot_groups_data_chi2(groups_data, groups_chi2, processed_metadata_group):
    """Plot the chi² of all groups of datasets with bars."""
    exchi2 = []
    xticks = []
    for group, group_res in zip(groups_data, groups_chi2):
    fig, ax = plotutils.barplot(exchi2, collabels=xticks, datalabels=[r'$\chi^2$'])
    ax.set_title(r"$\chi^2$ distribution by {}".format(processed_metadata_group))
    return fig

To adapt this for \(\phi\), we need to swap out the action groups_chi2 for groups_data_phi instead. So the start of the action will look like:

def plot_phi(groups_data, groups_data_phi, processed_metadata_group):
    We need to fill in this docstring later.
    from IPython import embed

Note that an IPython embed has been included to help explore the various objects. This is for development purposes and we will remove it when making any commits. We can set up a test runcard that calls our action, like:

    title: I didn't change the title
    keywords: [Guilty]
    author: Lazy Person

pdf: {id: "NNPDF31_nnlo_as_0118", label: "3.1 NNLO"}

theoryid: 53

use_cuts : nocuts

  - { dataset: NMC }
  - { dataset: ATLASTTBARTOT, cfac: [QCD] }
  - { dataset: CMSZDIFF12, cfac: [QCD,NRM], sys: 10 }
  - { dataset: LHCBWZMU7TEV, cfac: [NRM] }
  - { dataset: LHCBWZMU8TEV, cfac: [NRM] }
  - { dataset: ATLASWZRAP36PB}

 - plot_phi

Running this runcard and using embed we can see that groups_data_phi is a list of tuples, one for each group. Each tuple is (phi,``num_points``). So we can write our action in a similar way to the plot_groups_data_chi2 one:

def plot_phi(groups_data, groups_data_phi, processed_metadata_group):
    """plots phi for each group of data as a bar for a single
    PDF input

    See `phi_data` for information on how phi is calculated
    phi = [exp_phi for (exp_phi, npoints) in groups_data_phi]
    xticks = [ for group in groups_data]
    fig, ax = plotutils.barplot(phi, collabels=xticks, datalabels=[r'$\phi$'])
    ax.set_title(r"$\phi$ by {}".format(processed_metadata_group))
    return fig

Note that:

  • We used a list comprehension rather than a for loop.

  • We added a docstring explaining what the action does.

  • The action makes use of barplot from plotutils to do a bar chart.

  • The @figure decorator causes a figure to be generated and saved.