PitchAura
A spatial analytics computation engine for football/soccer tracking data.
PitchAura transforms raw player tracking coordinates into spatial control matrices, Voronoi territories, tactical metrics, and cognitive vision models — built on NumPy/SciPy with no mandatory heavy dependencies.
Features
| Module | What it does |
|---|---|
| Space / Pitch Control | Kinematic control model (Spearman 2018) + Voronoi tessellation |
| Tactics | Space creation, passing lane lifespan, defensive line-breaking pockets |
| Cognitive | Player vision cones, blind-spot maps, VisionModel |
| Sync | Frame alignment across tracking streams + moving-average / Kalman filtering |
| I/O | kloppy adapter (from_tracking, from_events) |
| Viz | Plotly-based pitch control heatmaps, Voronoi plots, animations |
Installation
pip install pitch-aura
Optional extras
# kloppy I/O adapter
pip install "pitch-aura[kloppy]"
# Plotly visualisation
pip install "pitch-aura[viz]"
# Everything
pip install "pitch-aura[kloppy,viz]"
Runtime requirements: Python ≥ 3.12, NumPy ≥ 1.24, SciPy ≥ 1.10, pandas ≥ 2.0.
Quick Start
Build a FrameRecord manually
import numpy as np
import pitch_aura as pa
frame = pa.FrameRecord(
frame_id=1,
timestamp=0.04,
home_positions=np.array([[30.0, 0.0], [20.0, 10.0]]), # (N, 2) metres
away_positions=np.array([[-25.0, 5.0], [-15.0, -8.0]]),
home_velocities=np.array([[2.0, 0.5], [1.0, -1.0]]),
away_velocities=np.array([[-1.5, 0.0], [-2.0, 1.0]]),
home_team_id="home",
ball_position=np.array([5.0, 0.0]),
)
Kinematic pitch control
model = pa.KinematicControlModel()
grid = model.compute(frame) # returns ProbabilityGrid
print(grid.values.shape) # (68, 105) by default
Voronoi territories
voronoi = pa.VoronoiModel()
result = voronoi.compute(frame) # returns VoronoiResult
# result.regions: list of (player_idx, team, polygon_vertices) tuples
Load from kloppy
# pip install "pitch-aura[kloppy]"
import kloppy
dataset = kloppy.tracab.load(...)
sequence = pa.from_tracking(dataset) # FrameSequence
frame = sequence.frames[0] # FrameRecord
Tactics
from pitch_aura.tactics.space_creation import space_creation
from pitch_aura.tactics.passing_lanes import passing_lane_lifespan
from pitch_aura.tactics.line_breaking import line_breaking_pockets
# How much space each attacking player is creating
scores = space_creation(frame, model)
# How many frames a passing lane stays open
lifespan = passing_lane_lifespan(sequence, passer_idx=7, receiver_idx=9, model=model)
# Pockets in the defensive line
pockets = line_breaking_pockets(frame)
for p in pockets:
print(f"Pocket at depth {p.line_depth:.1f}m, y={p.y_left:.1f}–{p.y_right:.1f}m")
Cognitive Models
from pitch_aura.cognitive.vision_cone import player_heading, vision_cone_mask
from pitch_aura import VisionModel
# Per-frame vision cone mask for a single player
heading = player_heading(frame, player_idx=0, team="home")
mask = vision_cone_mask(frame, player_idx=0, team="home", grid=grid)
# Full VisionModel: blind-spot pressure surface
vision = VisionModel()
pressure = vision.blind_spot_pressure(frame, grid)
Sync Utilities
from pitch_aura.sync.alignment import align
from pitch_aura.sync.filters import smooth
# Align two FrameSequences by timestamp
aligned_home, aligned_away = align(seq_home, seq_away)
# Smooth positions with a Kalman filter
smoothed = smooth(sequence, method="kalman")
Visualisation
Requires pip install "pitch-aura[viz]". All functions return plotly.graph_objects.Figure and never call .show().
from pitch_aura.viz import plot_pitch_control, plot_voronoi_control
# Pitch control heatmap with player overlay
fig = plot_pitch_control(grid, frame, home_team_id="home")
fig.write_html("pitch_control.html")
# Voronoi territories
from pitch_aura.viz import plot_voronoi_control
fig = plot_voronoi_control(result, frame, home_team_id="home")
fig.show()
# Frame-by-frame animation
from pitch_aura.viz import animate_sequence
fig = animate_sequence(sequence, model)
fig.write_html("match_animation.html")
Composable low-level API
from pitch_aura.viz._pitch_draw import pitch_background
from pitch_aura.viz.heatmap import plot_heatmap
from pitch_aura.viz.players import plot_players
from pitch_aura.viz.tactics import plot_pockets, plot_passing_lane
fig = pitch_background()
fig = plot_heatmap(grid, fig=fig)
fig = plot_players(frame, fig=fig, show_pitch=False)
fig = plot_pockets(pockets, fig=fig)
API Reference
Core types
| Class | Description |
|---|---|
FrameRecord |
Single tracking frame: positions, velocities, team IDs, ball |
FrameSequence |
Ordered sequence of frames + PitchSpec |
ProbabilityGrid |
(H, W) control probability array with coordinate metadata |
VoronoiResult |
Clipped Voronoi regions per player |
PitchSpec |
Pitch dimensions and coordinate convention |
EventRecord |
Discrete event (pass, shot, etc.) aligned to a frame |
Models
| Class / function | Description |
|---|---|
KinematicControlModel |
Spearman (2018) time-to-intercept pitch control |
VoronoiModel |
Mirror-augmented Voronoi with Sutherland-Hodgman clipping |
VisionModel |
Sigmoid vision cone + blind-spot pressure surface |
Acknowledgements
The kinematic pitch control model is based on:
Spearman, W. (2018). Beyond Expected Goals. MIT Sloan Sports Analytics Conference.
License
GNU General Public License v3.0 — see LICENSE.
Metadata
Release files for pitch-aura 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pitch_aura-0.1.0.tar.gz | 14.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pitch_aura-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.0 MB
Release files / pitch_aura-0.1.0.tar.gz
| Download URL | pitch_aura-0.1.0.tar.gz |
|---|---|
| Size | 14.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6d2b775d72e2c3d76aaab41b1592e1649a126b921ffb2a305c0ae04d22b3a0bb
|
|
BLAKE2b-256 checksum How to use checksums |
6ca88929f97cdbd7265186022d79b7bf8d0ec150f52b6d08085e5e84f695e6c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / pitch_aura-0.1.0-py3-none-any.whl
| Download URL | pitch_aura-0.1.0-py3-none-any.whl |
|---|---|
| Size | 61.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
17e91bc00add73920a4ac76bad11a1d3842b54443ee591c7d84bc83d097dbab9
|
|
BLAKE2b-256 checksum How to use checksums |
c94870efa71bc80492d0aff43434f9cbb29a421a1bcb747df2dd23d54bffdea8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|