Adding Custom Observables

Observables need no parameters beyond the ensemble itself and are automatically cached.

To write a custom observable is quite simple: you write a function that takes an ensemble and computes the observable you’re interested in, and decorate it with @observable.

For example, here is the actual implementation of average_field()

from tdg.observable import observable

@observable
def average_field(ensemble):
    r'''
    The average auxiliary field, one per configuration.
    '''
    return ensemble.configurations.mean((1,2))

You can use the value of another observable inside your observable, just call ensemble.other. For example, the N observable is just a sum of n,

@observable
def N(ensemble):
    r'''
    The total number, one per configuration.
    Computed via fermion contractions; the sum of :func:`~.n` on sites.
    '''
    return ensemble.n.sum(1)

Observables will be evaluated lazily but then cached for reuse. You should be careful to avoid creating a circular dependency.

Naming collisions are a risk. Only the name of the actual function is used for the GrandCanonical attribute/method. So, even though they are defined in different submodules, the action S() and total spin Spin() get different names.

Sometimes you want to share a common step between different observables but don’t need to treat the commonality as a “full” observable. In this case you can mark the function @intermediate instead. For example, _vorticity_vorticity is an @intermediate; it is used in both vorticity_squared() and vorticity_vorticity() but is otherwise not needed for further analysis.

Intermediate quantities are also not written to or read from disk. One example intermediate quantity is the propagator G which takes memory like the spacetime volume squared to store. In this case marking it @intermediate rather than @observable is a tradeoff between paying storage costs now or potential computation costs later.

A derived quantity can be constructed the same way, but with the @derived decorator. These are attached to the Bootstrap class, as they require expectation values for evaluation.