Espresso is a collection of individual examples, or test problems. From a users’ perspective, each test problem is a separate Python object (specifically, a subclass of espresso.EspressoProblem) that is available to be imported:

from espresso import XrayTomography as testproblem1
from espresso import SimpleRegression as testproblem2

Then, create an instance of the class to access its functionality:

tp1 = testproblem1()
tp2 = testproblem2()

Each test problem defines one or more examples. All examples will represent the same fundamental inference problem (i.e. the same physical/conceptual scenario), but may provide access to different datasets or problem configurations — for full details, consult the problem-specific documentation. By default, the first example is loaded, but you can select a different example by passing example_number=<num> when creating your class instance:

tp1 = testproblem1(example_number = 3)
tp2 = testproblem2(example_number = 2)

If you wish to use more than one example in your code, you will need to create multiple testproblem instances (or re-initialise an existing one). Attempting to load a non-existent example number will raise a espresso.exceptions.InvalidExampleError exception.

from espresso.exceptions import InvalidExampleError
from espresso import XrayTomography as xrt

iexample = 1
    while True:
        x = xrt(example_number = iexample)

        # Do stuff
        # ...

        # Now increment the counter and go round again
        iexample += 1
except InvalidExampleError:
    print("Last valid example:",iexample-1)

Your test problem instance provides access to simulation capabilities, data and other information via a standardised interface. Let’s suppose we’ve imported and instantiated some test problem <TestProblem> (this is just a generic placeholder name – it can be any example from the list).

from espresso import <TestProblem>
tp = TestProblem()

All test problems will have at least the following attributes:

  • tp.model_size – The number of unknown parameters, \(M\), i.e. the dimension of the model vector \(\mathbf{m}\).

  • tp.starting_model – A numpy.ndarray with shape \((M,)\) containing a null model or other problem-appropriate starting point that can be used to initialise (e.g.) iterative algorithms.

  • tp.good_model – A numpy.ndarray with shape \((M,)\) containing a model vector that the problem contributor would regard as one example of a ‘good’ description of the relevant system. (Problems may be non-unique, and ‘good’ may involve subjective choices; i.e. this is one good model but not necessarily the best or only good model.)

  • tp.data_size – The dimension, \(N\), of the data vector, \(\mathbf{d}\)

  • – A numpy.ndarray with shape \((N,)\) containing a data vector, \(\mathbf{d}\).

  • tp.forward(model) – A function that takes one model vector (a numpy.ndarray of shape \((M,)\)) as input, and returns a simulated data vector (\(\mathbf{g}(\mathbf{m})\), numpy.ndarray with shape \((N,)\)). The output from tp.forward can be assumed to be directly comparable to the data vector (For some test problems, tp.forward() will accept an optional argument with_jacobian = True; see below for more details.)

In addition, the following attributes are standardized, but optional:

  • tp.description – A str containing a desciption/summary of the test problem.

  • tp.covariance_matrix – A numpy.ndarray with shape \((N,N)\) containing a covariance matrix, \(\mathbf{C_d}\), describing the (assumed) uncertainty on \(\mathbf{d}\).

  • tp.inverse_covariance_matrix – A numpy.ndarray with shape \((N,N)\) containing \(\mathbf{C_{d}^{-1}}\).

  • tp.jacobian(model) – A function that takes one model vector (a numpy.ndarray of shape \((M,)\)) as input, and returns an numpy.ndarray of shape \((N,M)\) containing \(\mathbf{G}\) such that \([\mathbf{G}]_{ij} = {\partial[\mathbf{g}(\mathbf{m})]_i}/{\partial [\mathbf{m}]_j}\). Problems that define tp.jacobian() will also accept an optional argument with_jacobian = True passed to tp.forward(), which then returns a \((\mathbf{g}(\mathbf{m}), \mathbf{G})\) pair. In some cases this will be computationally more efficient than calling tp.forward() and tp.jacobian() separately.

  • tp.plot_model(model) – A function to visualise a single model-like vector in some problem-appropriate manner.

  • tp.plot_data(data, data2=None) – A function to visualise one or two data-like vectors in a problem-appropriate manner.

  • tp.misfit(data,data2) – A function that returns a float representing a problem-appropriate measure of the disagreement between two data-like vectors (i.e. a value of 0 implies a perfect match).

  • tp.log_likelihood(data,data2) – A function that computes a log-likelihood function (float) between two data-like vectors.

  • tp.log_prior(model) – A function that implements a prior distribution in model space, returning the log-probability (float) for a model-like vector.

If a test problem does not implement a given attribute, attempting to use it will raise a NotImplementedError exception (which can then be caught and handled as necessary).

All test problems will also define the following basic metadata:

  • tp.problem_title

  • tp.problem_short_description – A few sentences summarising the problem.

  • tp.author_names

  • tp.contact_name – Primary contributor/maintainer for the Espresso test problem.

  • tp.contact_email

  • tp.citations – List of (citation, doi) pairs for any publication(s) that directly describe the test problem;

  • tp.linked_sites – List of (title, address) pairs for any related resources (e.g. links to data sources or external Github repos).

Finally, test problems may expose additional attributes beyond the scope of the Espresso API. For more details see API Reference and Test Problems Reference.