Skip to content

feat: zones and grid utilities with tests; stabilize 3D; chore(poetry): dev deps to group 'dev'#24

Open
lblommesteyn wants to merge 2 commits into
Sport-Performance-Lab:mainfrom
lblommesteyn:fix/zones-3pt-arc
Open

feat: zones and grid utilities with tests; stabilize 3D; chore(poetry): dev deps to group 'dev'#24
lblommesteyn wants to merge 2 commits into
Sport-Performance-Lab:mainfrom
lblommesteyn:fix/zones-3pt-arc

Conversation

@lblommesteyn

Copy link
Copy Markdown

Summary

Consolidates recent work for side proj into one PR:

  • Zones: add CourtSpec and zone masks; add tests.
  • Grid: add utilities and tests.
  • Tests (3D): stabilize image comparison with fixed camera/limits and small tolerance.
  • Chore: move dev dependencies to [tool.poetry.group.dev.dependencies].

What changed

  • mplbasketball/zones.py: CourtSpec, restricted_area_mask, paint_mask, corner_three_mask, above_break_three_mask.
  • tests/test_zones.py: coverage for masks; H/V consistency checks.
  • mplbasketball/grid.py: get_extent, court_meshgrid, histogram2d_on_court, mask_out_of_bounds.
  • tests/test_grid.py: unit tests for grid helpers.
  • tests/test_court3d.py: deterministic camera/limits and small tolerance for 3D image compare.
  • mplbasketball/init.py: export CourtSpec, zone masks, and grid helpers at package root.
  • pyproject.toml: move dev deps to Poetry group.dev.

Rationale

  • Deterministic 3D rendering across Matplotlib builds.
  • Clear, reusable grid/zones APIs with tests.
  • Modern Poetry configuration for dev dependencies.

Testing (per CONTRIBUTING.md)

  • poetry run pytest -q tests/test_grid.py tests/test_zones.py → 6 passed locally.
  • poetry run pytest -q --mpl → full suite passes locally.

@ojadeyemi

Copy link
Copy Markdown
Contributor

Hey @lblommesteyn, just have a couple of questions:

  • Could you provide a screenshot or diagram showing how the new zone and grid utilities appear on the basketball court?
  • Can you walk us through a sample use case demonstrating their application?
  • How do these features integrate with the existing functionalities in the mplbasketball library?

Thanks
OJ

@lblommesteyn

Copy link
Copy Markdown
Author
 zone_and_grid_demo

Attached is zone_and_grid_demo.png showing:

  • Top-left: Shot chart colored by zone (restricted area, paint, corner 3, above-the-break 3, mid-range)
  • Top-right: Shot frequency heatmap (2D histogram aligned to court extent)
  • Bottom-left: Court with a 10x10 grid overlay (from court_meshgrid)
  • Bottom-right: In-bounds vs out-of-bounds points based on court extent

Sample use case

  • Given shot coordinates in court units, you can:
    • Categorize into standard zones using masks:
      • restricted_area_mask, paint_mask, corner_three_mask, above_break_three_mask
    • Build heatmaps and density views:
      • histogram2d_on_court returns (hist, x_edges, y_edges) aligned to the court via get_extent
    • Overlay grid lines for analytics or binning:
      • court_meshgrid returns x/y edge arrays; plot vertical/horizontal lines for visual binning
    • Filter spatial data to in-bounds:
      • mask_out_of_bounds returns a boolean mask for the court extent
  • These utilities make common analyses (per-zone FG%, per-bin frequencies, or spatial filters) much simpler and consistent across orientations and halves.

Integration with existing mplbasketball features

  • CourtSpec centralizes court params (units, type, origin), which all utilities consume.
  • The new helpers are exported at the package root (see mplbasketball/init.py), so you can do:
    • from mplbasketball import Court, CourtSpec, restricted_area_mask, court_meshgrid, histogram2d_on_court, get_extent, mask_out_of_bounds
  • They compose with Court.draw seamlessly; you draw the court via Court and layer plots generated from the masks/grids/heatmaps on top of the same Axes.
  • Tests cover zone logic and grid helpers; 3D tests were stabilized with fixed camera/limits and a small image tolerance to remain deterministic across Matplotlib versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants