Skip to content

Conversation

@cvanelteren
Copy link
Collaborator

@cvanelteren cvanelteren commented Jan 7, 2026

Closes #450
Implements ridgeline plots (also known as joyplots) for visualizing distributions of multiple datasets as stacked, overlapping density curves.

Features:

  • Support for both vertical (traditional) and horizontal orientations
  • Kernel density estimation (KDE) for smooth curves
  • Customizable overlap between ridges
  • Color specification via colormap or custom colors
  • Integration with UltraPlot's color cycle
  • Transparent error handling for invalid distributions

Methods added:

  • ridgeline(): Create vertical ridgeline plots
  • ridgelineh(): Create horizontal ridgeline plots
  • _apply_ridgeline(): Internal implementation

Tests added:

  • test_ridgeline_basic: Basic functionality
  • test_ridgeline_colormap: Colormap support
  • test_ridgeline_horizontal: Horizontal orientation
  • test_ridgeline_custom_colors: Custom color specification
  • test_ridgeline_empty_data: Error handling for empty data
  • test_ridgeline_label_mismatch: Error handling for label mismatch

Implements ridgeline plots (also known as joyplots) for visualizing
distributions of multiple datasets as stacked, overlapping density curves.

Features:
- Support for both vertical (traditional) and horizontal orientations
- Kernel density estimation (KDE) for smooth curves
- Histogram mode for binned bar charts (hist=True)
- Customizable overlap between ridges
- Color specification via colormap or custom colors
- Integration with UltraPlot's color cycle
- Transparent error handling for invalid distributions
- Follows UltraPlot's docstring snippet manager pattern

Methods added:
- ridgeline(): Create vertical ridgeline plots
- ridgelineh(): Create horizontal ridgeline plots
- _apply_ridgeline(): Internal implementation

Tests added:
- test_ridgeline_basic: Basic KDE functionality
- test_ridgeline_colormap: Colormap support
- test_ridgeline_horizontal: Horizontal orientation
- test_ridgeline_custom_colors: Custom color specification
- test_ridgeline_histogram: Histogram mode
- test_ridgeline_histogram_colormap: Histogram with colormap
- test_ridgeline_comparison_kde_vs_hist: KDE vs histogram comparison
- test_ridgeline_empty_data: Error handling for empty data
- test_ridgeline_label_mismatch: Error handling for label mismatch

Docstrings registered with snippet manager following UltraPlot conventions.
@cvanelteren cvanelteren force-pushed the feature/ridgeline-plot branch from 67d6388 to bb2308c Compare January 7, 2026 04:45
The ridge outlines now only trace the top curve of each distribution,
not the baseline. This is achieved by:
- Using fill_between/fill_betweenx with edgecolor='none'
- Drawing a separate plot() line on top for the outline
- Proper z-ordering to ensure outline appears above fill

This creates cleaner ridgeline plots where the baseline doesn't have
a visible edge line connecting the endpoints.
Implements explicit z-ordering to ensure proper layering:
- Each ridge i gets: fill at base+i*2, outline at base+i*2+1
- Later ridges appear on top of earlier ridges
- Outline always appears on top of its corresponding fill
- Base zorder defaults to 2 (above grid/axes elements)
- User can override base zorder via zorder parameter

This ensures clean visual layering even with high overlap values
and when other plot elements are present (e.g., grids).
Reversed the z-order assignment so that visually lower ridges
(smaller index, closer to viewer) have higher z-order values.

Z-order formula: fill_zorder = base + (n_ridges - i - 1) * 2

This ensures proper visual layering where:
- Ridge 0 (bottom, front) has highest z-order
- Ridge n-1 (top, back) has lowest z-order

This prevents ridges from incorrectly popping in front of others
when overlap is high, maintaining the correct visual depth.
@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

❌ Patch coverage is 91.69811% with 22 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ultraplot/axes/plot.py 82.53% 14 Missing and 8 partials ⚠️

📢 Thoughts on this report? Let us know!

Replaced explicit bandwidth/weights parameters with a more flexible
kde_kw dictionary that passes all kwargs to scipy.stats.gaussian_kde.

Features:
- kde_kw: dict parameter for passing any KDE arguments (bw_method, weights, etc.)
- points: int parameter to control number of evaluation points (default 200)
- More maintainable and extensible than exposing individual parameters
- Follows UltraPlot's convention of using *_kw parameters

Example usage:
- Custom bandwidth: kde_kw={'bw_method': 0.5}
- With weights: kde_kw={'weights': weight_array}
- Silverman method: kde_kw={'bw_method': 'silverman'}
- Smoother curves: points=500

Tests added:
- test_ridgeline_kde_kw: Tests various kde_kw configurations
- test_ridgeline_points: Tests points parameter
@cvanelteren
Copy link
Collaborator Author

need to check a few more plots to see if this is what I invisioned.

@cvanelteren cvanelteren marked this pull request as draft January 7, 2026 06:31
…plots

Implements two distinct positioning modes for ridgeline plots:

1. Categorical Positioning (default): Evenly-spaced ridges with discrete labels
   - Uses overlap parameter to control spacing
   - Traditional 'joyplot' aesthetic

2. Continuous Positioning: Ridges anchored to specific Y-coordinates
   - Enabled by providing 'positions' parameter
   - 'height' parameter controls ridge height in Y-axis units
   - Essential for scientific plots where Y-axis represents physical variables
   - Supports: time series, depth profiles, redshift distributions, etc.

Parameters:
- positions: Array of Y-coordinates for each ridge
- height: Ridge height in Y-axis units (auto-determined if not provided)

Scientific use cases:
- Ocean temperature profiles vs depth
- Galaxy distributions vs redshift
- Climate data over time
- Atmospheric profiles vs altitude
- Any data where the vertical axis has physical meaning

Tests added:
- test_ridgeline_continuous_positioning: Visual test of continuous mode
- test_ridgeline_continuous_vs_categorical: Side-by-side comparison
- test_ridgeline_continuous_errors: Error handling validation
- test_ridgeline_continuous_auto_height: Auto height calculation
- Add comprehensive ridgeline plot examples to docs/stats.py
- Include examples for KDE vs histogram modes
- Demonstrate categorical vs continuous positioning for scientific use cases
- Replace deprecated mcm.get_cmap() with constructor.Colormap()
- All 15 ridgeline tests still passing
@cvanelteren cvanelteren marked this pull request as ready for review January 7, 2026 21:34
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.

Feature Request: Add Ridgeline Plot Support

2 participants