Skip to main content

PitchAura

A spatial analytics computation engine for football/soccer tracking data.

PyPI version Python License: GPL v3

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)

Source distribution for pitch-aura 0.1.0
File Size Uploaded
pitch_aura-0.1.0.tar.gz 14.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pitch-aura 0.1.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page