Getting Started

This tutorial walks through a complete perturbative calculation from scratch. By the end you will know how to define fields, build an interaction action, compute moments, inspect Feynman diagrams, and export results to LaTeX.

Step 1 — Install and Import

pip install -e ".[dev]"
from sft_wick import (
    Field, Vertex, Action, compute_moment, LaTeXFormatter
)

Step 2 — Define Fields

Every calculation starts by declaring the field species. In the MSR formalism there are two types: physical (\(\phi\)) and response (\(\psi\)).

# Scalar fields (single component)
phi = Field('phi', 'physical')
psi = Field('psi', 'response')

For multi-component fields, specify n_components:

phi = Field('phi', 'physical', n_components=3)
psi = Field('psi', 'response', n_components=3)

Step 3 — Create an Observable

An observable is a list of field operators — concrete field instances with bound component indices and spatial arguments.

# Scalar: phi('x') creates phi(x)
obs = [psi('x'), phi('x'), phi('x'), phi('x')]

For multi-component fields, pass (component_index, spatial_arg):

obs = [psi('a', 'x'), phi('b', 'x'), phi('c', 'x'), phi('d', 'x')]

Step 4 — Compute the Zeroth-Order Moment

At zeroth order, only the free propagators contribute (no interactions):

result = compute_moment(obs, Action(vertices=[]), order=0)
print(result.order(0).to_latex())
3 R(x, x) C(x, x)

The factor of 3 arises because \(\psi\) can pair with any of the three \(\phi\)’s (giving \(R\)), and the remaining two pair together (giving \(C\)). See Wick’s Theorem for the combinatorial explanation.

Step 5 — Define an Interaction Vertex

Vertices represent terms in the interaction action \(S_{\mathrm{int}}\). A local vertex puts all fields at the same spatial point:

# S_int = integral F_{ijk} phi_i(z) phi_j(z) psi_k(z) dz
phi = Field('phi', 'physical', n_components=3)
psi = Field('psi', 'response', n_components=3)
v = Vertex(fields=[phi, phi, psi], coupling='F')

A non-local vertex gives each field its own spatial argument:

# S_int = iint K_{ij}(z, z') psi_i(z) psi_j(z') dz dz'
v_nl = Vertex(fields=[psi, psi], coupling='K', local=False)

Step 6 — Compute to First Order

Wrap vertices in an Action and request a higher-order expansion:

action = Action(vertices=[v])
obs = [psi('a', 'x'), phi('b', 'x'), phi('c', 'x'), phi('d', 'x')]

result = compute_moment(obs, action, order=1)

# Zeroth order
print("Order 0:", result.order(0).to_latex())

# First order
print("Order 1:", result.order(1).to_latex())

# All orders combined
print("Total:", result.total.to_latex())

Step 7 — Inspect Feynman Diagrams

Every non-vanishing contraction is stored as a DiagramInfo. Convert to a graph and inspect topology:

for d_info in result.diagrams_by_order[1]:
    fd = d_info.to_feynman_diagram()
    print(fd.summary())
    print(f"  Loops: {fd.n_loops}, Connected: {fd.is_connected}")

Render diagrams with matplotlib:

# Draw all diagrams at order 1
result.draw_diagrams(order=1)

# Draw everything
result.draw_diagrams()

Step 8 — Format as LaTeX

Every expression has a .to_latex() method:

print(result.order(0).to_latex())

For custom propagator names (e.g. G instead of C):

fmt = LaTeXFormatter(propagator_names={
    'C': 'G',
    'R': r'R^{\mathrm{ret}}'
})
print(fmt.format(result.order(0)))

Generate a complete align environment for a paper:

print(fmt.format_aligned(result.order_terms))

Step 9 — Conventions: Itô and Response Phase

By default, two physics conventions are active:

Itô prescription (ito=True): the response propagator vanishes at equal points \(R(x,x) = 0\), and causal R-loops are eliminated.

# Disable to keep R(x,x) symbolic:
result = compute_moment(obs, action, order=1, ito=False)

Response phase (response_phase=True): each term is multiplied by \((-\mathrm{i})^n\) where n counts response propagators, implementing \(\langle\phi\,\psi\rangle = -\mathrm{i}\,R\).

# Disable to get raw R propagators:
result = compute_moment(obs, action, order=1, response_phase=False)

# Or apply the phase manually:
from sft_wick import apply_response_phase
phased = apply_response_phase(raw_expr)

Diagram-based collection (collect_topology=True): terms whose Feynman diagrams are isomorphic (under dummy-variable relabeling and C-propagator symmetry) are grouped. Propagators are factored out with canonical component indices, and coupling coefficients are summed with permuted indices. At second order and above, spatial-variable relabeling further reduces the number of distinct terms.

# Disable to see all pairings expanded:
result = compute_moment(obs, action, order=2, collect_topology=False)

Next Steps

  • User Guide — detailed coverage of every feature

  • Examples — worked examples with multi-component fields, non-local vertices, and higher orders

  • API Reference — complete API reference