Chapter 16: Exercises - Spatial Analysis and Field Visualization
Overview
These exercises progress from basic field drawing to advanced tracking data analysis. Each level builds on previous skills, culminating in comprehensive spatial analytics systems.
Level 1: Fundamentals (Recall and Basic Application)
Exercise 1.1: Basic Field Drawing
Create a simple football field visualization.
Task: Write a function that draws a basic football field with: - Green playing surface - White yard lines every 10 yards - End zones with team colors - Field numbers at 10, 20, 30, 40, 50
Starter Code:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def draw_basic_field(home_color='crimson', away_color='navy'):
"""
Draw a basic football field with end zones.
Parameters:
-----------
home_color : str
Color for home end zone (left)
away_color : str
Color for away end zone (right)
Returns:
--------
tuple : (fig, ax) matplotlib objects
"""
fig, ax = plt.subplots(figsize=(14, 6))
# TODO: Set field background color
# TODO: Draw end zones
# TODO: Draw yard lines every 10 yards
# TODO: Add field numbers
# TODO: Set axis limits and remove axes
return fig, ax
# Test your function
fig, ax = draw_basic_field()
plt.title("Basic Football Field")
plt.show()
Expected Output: A horizontal football field with properly colored end zones and visible yard lines.
Exercise 1.2: Plot Player Positions
Plot offensive and defensive player positions on the field.
Task: Given player position data, plot each player as a marker on the field.
Data:
offense = [
{'x': 25, 'y': 26.67, 'position': 'QB', 'number': 7},
{'x': 23, 'y': 26.67, 'position': 'RB', 'number': 22},
{'x': 26, 'y': 26.67, 'position': 'C', 'number': 55},
{'x': 26, 'y': 24.5, 'position': 'LG', 'number': 65},
{'x': 26, 'y': 28.84, 'position': 'RG', 'number': 72},
{'x': 26, 'y': 22.5, 'position': 'LT', 'number': 76},
{'x': 26, 'y': 30.84, 'position': 'RT', 'number': 78},
{'x': 26, 'y': 10, 'position': 'WR', 'number': 1},
{'x': 26, 'y': 43.33, 'position': 'WR', 'number': 4},
{'x': 26, 'y': 35, 'position': 'TE', 'number': 87},
{'x': 24, 'y': 22, 'position': 'WR', 'number': 11}
]
defense = [
{'x': 27, 'y': 26.67, 'position': 'NT', 'number': 92},
{'x': 27, 'y': 23, 'position': 'DE', 'number': 91},
{'x': 27, 'y': 30, 'position': 'DE', 'number': 97},
{'x': 28.5, 'y': 20, 'position': 'LB', 'number': 55},
{'x': 28.5, 'y': 26.67, 'position': 'LB', 'number': 45},
{'x': 28.5, 'y': 33, 'position': 'LB', 'number': 52},
{'x': 30, 'y': 10, 'position': 'CB', 'number': 24},
{'x': 30, 'y': 43.33, 'position': 'CB', 'number': 20},
{'x': 32, 'y': 26.67, 'position': 'S', 'number': 3},
{'x': 35, 'y': 18, 'position': 'S', 'number': 21},
{'x': 35, 'y': 35, 'position': 'S', 'number': 27}
]
Requirements: - Offense in blue circles - Defense in red circles - Show jersey numbers inside markers - Add a legend
Exercise 1.3: Draw a Simple Route
Draw a receiver route on the field.
Task: Create a function to draw a basic slant route from a starting position.
Route Definition: - Start: (26, 10) - wide receiver position - Step 1: Run 3 yards forward to (29, 10) - Step 2: Break inside at 45 degrees to (35, 18)
Starter Code:
def draw_route(ax, start, waypoints, color='blue', linewidth=2):
"""
Draw a route on the football field.
Parameters:
-----------
ax : matplotlib Axes
The axes to draw on
start : tuple
(x, y) starting position
waypoints : list of tuples
List of (x, y) waypoints
color : str
Route line color
linewidth : float
Line width
"""
# TODO: Build list of all points
# TODO: Draw route line
# TODO: Add arrow at end of route
# TODO: Mark starting position
pass
Exercise 1.4: Field Coordinate System
Convert between different coordinate systems used in football analytics.
Task: Implement functions to convert between: 1. Absolute coordinates (0-120 yards, 0-53.33 yards) 2. Relative coordinates (yards from line of scrimmage, yards from center) 3. Percentage coordinates (0-100% for both dimensions)
Starter Code:
def absolute_to_relative(x, y, line_of_scrimmage, play_direction='right'):
"""Convert absolute coordinates to relative."""
pass
def relative_to_absolute(rel_x, rel_y, line_of_scrimmage, play_direction='right'):
"""Convert relative coordinates to absolute."""
pass
def absolute_to_percentage(x, y):
"""Convert absolute coordinates to percentage (0-100)."""
pass
Exercise 1.5: Hash Mark Visualization
Draw hash marks and understand their positioning.
Task: Create a visualization that shows: - College hash marks (40 feet from sideline = 13.33 yards) - NFL hash marks (18 feet 6 inches from center = 18.5 feet from center) - Label the difference between the two systems
Level 2: Application (Apply Concepts to New Situations)
Exercise 2.1: Formation Library
Create a library of common football formations.
Task: Build a class that can draw any of these formations: - Shotgun spread (4 WR) - I-Formation - Single back - Empty backfield - Goal line
Requirements:
class FormationLibrary:
"""Library of common football formations."""
FORMATIONS = {
'shotgun_spread': {
'QB': (0, 0),
'RB': None, # No RB
'WR1': (1, -20),
'WR2': (1, -8),
'WR3': (1, 8),
'WR4': (1, 20),
'TE': None,
# O-line positions...
},
# Add other formations...
}
def draw_formation(self, ax, formation_name, los, flip=False):
"""Draw specified formation on the field."""
pass
def list_formations(self):
"""Return list of available formations."""
pass
Deliverable: A class that can visualize at least 5 different formations.
Exercise 2.2: Route Tree Visualization
Create a complete route tree visualization.
Task: Draw all routes in the standard route tree (0-9) from a single receiver position.
Routes: - 0: Hitch - 1: Flat - 2: Slant - 3: Comeback - 4: Curl - 5: Out - 6: In (Dig) - 7: Corner - 8: Post - 9: Go (Fly)
Requirements: - Draw all routes from position (LOS, 10 yards from sideline) - Color-code by route type (short, medium, deep) - Label each route with number and name - Show break points clearly
Exercise 2.3: Target Heat Map
Create a passing target heat map from play data.
Task: Given target location data, create a kernel density heat map showing where a quarterback throws the ball.
Sample Data:
import numpy as np
# Generate sample target data (normally you'd use real data)
np.random.seed(42)
n_throws = 200
# Most targets are short-middle
targets = {
'x': np.concatenate([
np.random.normal(5, 3, 100), # Short passes
np.random.normal(12, 4, 60), # Medium passes
np.random.normal(25, 6, 40) # Deep passes
]),
'y': np.concatenate([
np.random.normal(0, 8, 100),
np.random.normal(0, 12, 60),
np.random.normal(0, 6, 40)
])
}
Requirements: - Use scipy.stats.gaussian_kde for density estimation - Show contour levels for different density regions - Overlay on a half-field visualization - Add a colorbar showing density values
Exercise 2.4: Zone Coverage Visualization
Draw zone coverage assignments on the field.
Task: Create visualizations for common zone coverages: - Cover 2 - Cover 3 - Cover 4 (Quarters)
Requirements: - Draw zone boundaries as semi-transparent regions - Position defenders in their zones - Use different colors for different zone types (deep, intermediate, short) - Add labels for each zone
Exercise 2.5: Play Diagram Generator
Build a tool that generates play diagrams from structured data.
Task: Given play data in a structured format, generate a complete play diagram.
Input Format:
play_data = {
'formation': 'shotgun_trips_right',
'line_of_scrimmage': 25,
'routes': {
'X': {'type': 'post', 'depth': 15},
'H': {'type': 'out', 'depth': 8},
'Y': {'type': 'slant', 'depth': 5},
'Z': {'type': 'go', 'depth': 30}
},
'protection': 'slide_left',
'rb_action': 'check_release'
}
Output: A complete play diagram showing formation, routes, and blocking assignments.
Level 3: Analysis (Break Down and Examine)
Exercise 3.1: Separation Analysis
Analyze receiver separation over the course of a route.
Task: Given tracking data for a receiver and their defender, calculate and visualize separation throughout a play.
Sample Data:
# Frame-by-frame tracking data (10 frames per second)
tracking_data = {
'frame': list(range(50)),
'receiver_x': [25 + i*0.5 for i in range(50)], # Simplified linear motion
'receiver_y': [10 + (0 if i < 15 else (i-15)*0.3) for i in range(50)],
'defender_x': [26 + i*0.48 for i in range(50)],
'defender_y': [10 + (0 if i < 17 else (i-17)*0.28) for i in range(50)],
}
Requirements: 1. Calculate separation distance at each frame 2. Create a line plot showing separation over time 3. Identify the moment of maximum separation 4. Overlay the routes on a field diagram with separation color-coded
Exercise 3.2: Pressure Analysis
Visualize and analyze pass rush pressure.
Task: Create a visualization showing: - Offensive line positions - Defensive front positions - Rush paths as arrows - Pocket integrity over time
Metrics to Calculate: - Time to pressure - Pocket size (convex hull area) - Number of unblocked rushers - Pressure rate by direction (left, center, right)
Exercise 3.3: Field Zone Efficiency
Analyze offensive efficiency by field zone.
Task: Divide the field into zones and calculate efficiency metrics for each.
Zone Definition: - Horizontal: Behind LOS, 0-5, 5-10, 10-20, 20+ yards - Vertical: Left numbers, left hash, middle, right hash, right numbers
Metrics: - Completion percentage - EPA per attempt - Success rate - Average yards
Visualization: Heat map with cells colored by the selected metric.
Exercise 3.4: Motion Analysis
Analyze pre-snap motion and its effects.
Task: Track player motion from pre-snap to snap and visualize patterns.
Requirements: 1. Draw motion paths for players who moved pre-snap 2. Calculate motion speed and distance 3. Compare success rate with/without motion 4. Identify most common motion types
Exercise 3.5: Defensive Alignment Recognition
Build a system to classify defensive alignments from player positions.
Task: Given defensive player positions at the snap, classify the formation.
Classifications: - Front: 4-3, 3-4, Nickel, Dime, Goal line - Coverage shell: 1-high, 2-high - Blitz indicators: Extra box defenders
Starter Code:
def classify_defense(positions):
"""
Classify defensive alignment from positions.
Parameters:
-----------
positions : list of dict
Each dict has 'x', 'y', and 'position' keys
Returns:
--------
dict : Classification results
{
'front': str,
'shell': str,
'box_count': int,
'blitz_likely': bool
}
"""
pass
Level 4: Synthesis (Combine Elements in New Ways)
Exercise 4.1: Interactive Play Viewer
Build an interactive play visualization tool.
Task: Create a tool that allows users to: - Step through plays frame by frame - Highlight specific players - Toggle route trails on/off - Show real-time speed and separation metrics
Technology: Use Plotly or matplotlib with widgets.
Exercise 4.2: Passing Chart Generator
Create a comprehensive passing chart system.
Task: Build a system that generates passing charts showing: - All pass attempts in a game/season - Outcomes (complete, incomplete, interception, touchdown) - Depth and direction - Receiver identity
Features: - Filter by game, opponent, quarter - Color by outcome or EPA - Show league average comparison lines - Export to common formats
Exercise 4.3: Formation Tendency Report
Build a formation tendency analysis system.
Task: Analyze formation usage and tendencies.
Requirements: 1. Parse play-by-play data to extract formations 2. Calculate usage rates by: - Down and distance - Field position - Score differential 3. Identify play type tendencies from each formation 4. Generate visual reports with charts
Exercise 4.4: Coverage Beater Identifier
Create a tool that identifies coverage weaknesses.
Task: Given a coverage type, visualize: - Soft spots in the zone - Route combinations that attack those spots - Historical success against this coverage
Process: 1. Define zone boundaries for each coverage 2. Identify gaps between zones 3. Draw routes that exploit gaps 4. Show success rate data
Exercise 4.5: Real-Time Tracking Simulator
Build a simulation of real-time tracking data display.
Task: Create a system that: - Reads tracking data from a file - Displays players moving in real-time - Shows speed vectors - Updates metrics live (speed, separation, time to throw)
Level 5: Evaluation (Judge and Justify)
Exercise 5.1: Visualization Framework Comparison
Evaluate different approaches to field visualization.
Task: Implement the same visualization (formation diagram with routes) using: 1. Matplotlib (static) 2. Plotly (interactive) 3. Matplotlib with animation
Evaluation Criteria: - Code complexity and maintainability - Performance with large datasets - Interactivity and user experience - Export and sharing capabilities
Deliverable: Written analysis comparing the three approaches with code examples.
Exercise 5.2: Tracking Data Quality Assessment
Evaluate the quality of tracking data and its impact on analysis.
Task: Given tracking data with known issues, identify and quantify problems.
Issues to Detect: - Missing frames - Position jumps (teleportation) - Unrealistic speeds - Player ID swaps
Deliverable: A data quality report with: - Issue counts by type - Visualizations of problematic plays - Recommendations for handling each issue type
Exercise 5.3: Spatial Metric Validation
Validate spatial metrics against game outcomes.
Task: Calculate several spatial metrics and evaluate their predictive power.
Metrics to Test: - Average separation at target - Time in pocket before throw - Space created by motion - Defensive pressure rate
Evaluation: - Correlation with EPA - Correlation with completion probability - Stability across sample sizes - Year-over-year consistency
Exercise 5.4: Visualization Design Critique
Critique and improve an existing spatial visualization.
Provided Visualization: A cluttered field diagram showing all player positions, routes, and coverage simultaneously.
Task: 1. Identify specific design problems 2. Explain why each is problematic (perceptual, cognitive, practical) 3. Propose and implement improvements 4. Justify your design decisions
Exercise 5.5: Comprehensive Spatial Analytics System
Design and implement a complete spatial analytics module.
Task: Build a production-ready spatial analytics system that includes: 1. Field visualization components 2. Player tracking analysis 3. Route and coverage visualization 4. Automated report generation
Requirements: - Modular, extensible architecture - Consistent styling across all visualizations - Performance optimization for large datasets - Comprehensive documentation
Deliverable: Complete Python module with documentation and example notebooks.
Submission Guidelines
Code Requirements
- All code must be executable Python
- Include docstrings for all functions and classes
- Follow PEP 8 style guidelines
- Include type hints for function signatures
Visualization Requirements
- All figures should have appropriate titles and labels
- Use consistent color schemes
- Include legends where appropriate
- Export visualizations in appropriate formats (PNG for static, HTML for interactive)
Analysis Requirements
- Explain your methodology
- Discuss limitations of your approach
- Suggest potential improvements or extensions
Grading Rubric
| Level | Weight | Criteria |
|---|---|---|
| Level 1 | 15% | Correct implementation, basic functionality |
| Level 2 | 25% | Complete features, proper structure |
| Level 3 | 25% | Accurate analysis, clear visualizations |
| Level 4 | 20% | Creative integration, user experience |
| Level 5 | 15% | Critical thinking, justified decisions |
Resources
- Matplotlib Documentation
- Plotly Python Documentation
- SciPy KDE Documentation
- NFL Big Data Bowl Examples
- Chapter 16 code examples in the
/codedirectory