HomeTutorials15 – Visualisation & Analysis
15Beginner~8 min

Visualisation & Analysis

The lfm.viz module gives you 10 ready-made plotting functions. Two lines of code: import + call. Every function returns (fig, ax) so you can customise with standard matplotlib.

What you'll learn

  • How to create 2D slices of 3D fields with plot_slice
  • Radial profiles with automatic 1/r reference overlay
  • Time-evolution dashboards from sim.history
  • Fourier power spectrum P(k) analysis
  • Parameter sweeps: vary amplitude and plot the effect on χ_min

Install

pip install "lfm-physics[viz]"

This adds matplotlib as a dependency. The core library works without it.

Full script

"""15 – Visualisation & Analysis

The lfm.viz toolkit: plot slices, radial profiles, time-series
dashboards, power spectra, and parameter sweeps without writing
any matplotlib boilerplate.

Requires: pip install "lfm-physics[viz]"
"""

import lfm

# ── 1. Run a quick simulation ─────────────────────────────────────────

config = lfm.SimulationConfig(grid_size=32)
sim = lfm.Simulation(config)
sim.place_soliton((16, 16, 16), amplitude=6.0)
sim.equilibrate()
sim.run(steps=3000)

print("15 – Visualisation & Analysis")
print("=" * 55)
print()

m = sim.metrics()
print(f"  chi_min = {m['chi_min']:.2f}  (gravity well depth)")
print(f"  wells   = {m['well_fraction']*100:.1f}%")
print()

# ── 2. 2D slice through the chi field ─────────────────────────────────

from lfm.viz import plot_slice, plot_three_slices

fig, ax = plot_slice(sim.chi, axis=2, index=16, title="χ mid-plane (z=16)")
fig.savefig("tutorial_15_slice.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_slice.png")

# Three-panel overview (XY, XZ, YZ)
fig = plot_three_slices(sim.chi, title="χ field — three planes")
fig.savefig("tutorial_15_three_slices.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_three_slices.png")

# ── 3. Radial profile with 1/r reference ──────────────────────────────

from lfm.viz import plot_radial_profile

fig, ax = plot_radial_profile(sim.chi, center=(16, 16, 16), max_radius=12)
fig.savefig("tutorial_15_radial.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_radial.png")

# ── 4. Chi histogram ──────────────────────────────────────────────────

from lfm.viz import plot_chi_histogram

fig, ax = plot_chi_histogram(sim.chi, title="χ distribution after 3000 steps")
fig.savefig("tutorial_15_histogram.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_histogram.png")

# ── 5. Time-evolution dashboard ───────────────────────────────────────

from lfm.viz import plot_evolution

fig = plot_evolution(sim.history, title="Metric evolution")
fig.savefig("tutorial_15_evolution.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_evolution.png")

# ── 6. Fourier power spectrum ─────────────────────────────────────────

from lfm.viz import plot_power_spectrum

fig, ax = plot_power_spectrum(sim.chi, title="P(k) of χ field")
fig.savefig("tutorial_15_spectrum.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_spectrum.png")

# ── 7. Parameter sweep ───────────────────────────────────────────────

from lfm.viz import plot_sweep

sweep_cfg = lfm.SimulationConfig(grid_size=32)
results = lfm.sweep(
    sweep_cfg,
    param="amplitude",
    values=[2, 4, 6, 8],
    steps=2000,
    metric_names=["chi_min", "well_fraction"],
)
fig, ax = plot_sweep(results, x_param="amplitude", y_metric="chi_min",
                     title="χ_min vs soliton amplitude")
fig.savefig("tutorial_15_sweep.png", dpi=120, bbox_inches="tight")
print("Saved: tutorial_15_sweep.png")

print()
print("All plots saved.  Open the PNG files to explore your simulation.")
print("Every lfm.viz function returns (fig, ax) so you can customise further.")

Step-by-step walkthrough

Step 1 — Run a simulation

config = lfm.SimulationConfig(grid_size=32)
sim = lfm.Simulation(config)
sim.place_soliton((16, 16, 16), amplitude=6.0)
sim.equilibrate()
sim.run(steps=3000)

Standard setup: 32³ lattice, one soliton at the centre. After 3000 steps the χ-well has formed and the energy has redistributed.

Step 2 — Slice the χ field

from lfm.viz import plot_slice
fig, ax = plot_slice(sim.chi, axis=2, index=16)

plot_slice extracts a 2D plane from the 3D field. axis=2 means “cut along z”,index=16 picks the mid-plane. The red-blue colourmap shows χ < 19 (wells) in blue and χ ≈ 19 (vacuum) in white.

Step 3 — Radial profile

from lfm.viz import plot_radial_profile
fig, ax = plot_radial_profile(sim.chi, center=(16,16,16))

Azimuthally averages χ(r) and overlays a best-fit 1/r curve (dashed). If the soliton creates Newtonian-like gravity, the two curves should track closely.

Step 4 — Evolution dashboard

from lfm.viz import plot_evolution
fig = plot_evolution(sim.history)

Reads the metric snapshots stored in sim.historyand creates a multi-panel time-series. By default it plots chi_min,well_fraction, and energy_total if available.

Step 5 — Power spectrum

from lfm.viz import plot_power_spectrum
fig, ax = plot_power_spectrum(sim.chi)

Computes the radially-averaged Fourier power P(k) of the χ field. A localised soliton produces a smooth P(k); cosmic structure shows distinct peaks.

Step 6 — Parameter sweep

results = lfm.sweep(config, param="amplitude",
                    values=[2, 4, 6, 8], steps=2000)

from lfm.viz import plot_sweep
fig, ax = plot_sweep(results, "amplitude", "chi_min")

lfm.sweep() runs one simulation per amplitude value and records the final metrics.plot_sweep() then plots χ_min vs amplitude. Higher amplitude → deeper well → lower χ_min.

Expected output

15 – Visualisation & Analysis
=======================================================

  chi_min = 15.23  (gravity well depth)
  wells   = 4.2%

Saved: tutorial_15_slice.png
Saved: tutorial_15_three_slices.png
Saved: tutorial_15_radial.png
Saved: tutorial_15_histogram.png
Saved: tutorial_15_evolution.png
Saved: tutorial_15_spectrum.png
Saved: tutorial_15_sweep.png

All plots saved.  Open the PNG files to explore your simulation.
Every lfm.viz function returns (fig, ax) so you can customise further.

All 10 lfm.viz functions

FunctionPurposeReturns
plot_slice2D slice through a 3D field(fig, ax)
plot_three_slicesXY + XZ + YZ panelsfig
plot_chi_histogramDistribution of χ values(fig, ax)
plot_evolutionMulti-panel time-series dashboardfig
plot_energy_componentsStacked kinetic / gradient / potential(fig, ax)
plot_radial_profileχ(r) with 1/r reference(fig, ax)
plot_isosurface3D voxel renderingfig
plot_power_spectrumFourier P(k) plot(fig, ax)
plot_trajectoriesPeak motion scatter plot(fig, ax)
plot_sweepSweep results line plot(fig, ax)

Every function accepts an optional ax= parameter so you can embed it in your own subplot grid.

Composable design

All lfm.viz functions return standard matplotlib objects. You can combine them freely: create a 2×2 grid of subplots, pass eachax into a different function, then save the combined figure. No magic, no hidden state.