Skip to content

Comments

Major update: Seaborn 0.13.2 compatibility and modernized infrastructure (v0.2.7 → v0.3.1)#55

Merged
pog87 merged 7 commits intopog87:masterfrom
syntactic:modernization_packaging_testing
Oct 6, 2025
Merged

Major update: Seaborn 0.13.2 compatibility and modernized infrastructure (v0.2.7 → v0.3.1)#55
pog87 merged 7 commits intopog87:masterfrom
syntactic:modernization_packaging_testing

Conversation

@syntactic
Copy link
Contributor

This PR brings PtitPrince from v0.2.7 to v0.3.1. It includes comprehensive updates for Seaborn 0.13.2 compatibility, along with modernized packaging and testing infrastructure.

Seaborn 0.13.2 Compatibility (v0.3.0)

Core Refactoring

  • Adapted plotting internals to work with Seaborn 0.13+ API changes. Previously this library was dependent on Seaborn 0.11 which is about five years old.
  • Migrated from _CategoricalScatterPlotter to modern _CategoricalPlotter base class
  • Updated orientation handling to support new seaborn conventions (orient='x'/'y' instead of 'v'/'h' internally)
  • Implemented modern legend configuration using _get_patch_legend_artist
  • Added future-proofing for Seaborn 0.14 deprecation warnings

Bug Fixes

  • Fixed dodge alignment in raincloud components when using hue parameter
  • Corrected pointplot hue handling for proper color mapping
  • Fixed axis label positioning after seaborn API changes
  • Aligned move offsets with stripplot layering for proper visual alignment
  • Improved raincloud component alignment when using hue with multiple categories

Enhancements

  • Added _LEGACY_GRAY constant for backward-compatible gray color handling
  • Implemented complementary gray color generation for better visual consistency
  • Enhanced stripplot with automatic hue assignment to avoid deprecation warnings

Modernized Infrastructure (v0.3.1)

Packaging

  • Migrated to pyproject.toml with Hatchling build backend (PEP 621 compliant)
  • Removed legacy setup.py and requirements.txt
  • Added proper dependency groups: dev, notebooks
  • Updated Python support: 3.9, 3.10, 3.11, 3.12 (dropped Python 2)

Testing

  • Added comprehensive pytest test suite: 60+ tests with 89% code coverage
  • Tests cover all three main functions: RainCloud, half_violinplot, stripplot
  • Added notebook integration tests
  • Created fixtures for sample data and automatic plot cleanup
  • Updated CI/CD to test across Python 3.9-3.12 on Ubuntu

Code Quality

  • Added pre-commit hooks with Ruff for automated formatting and linting
  • Updated type hints to modern Python 3.9+ syntax (list/dict instead of List/Dict)
  • Removed deprecated from __future__ import division
  • Cleaned up unused variables and improved code clarity
  • Consistent code formatting across the entire codebase

Breaking Changes

  • Removed default palette="Set2" from RainCloud() to avoid seaborn 0.14 warnings
    • Migration: Users who want the old colors should explicitly pass palette='Set2'
    • This eliminates FutureWarning spam for users not specifying palettes

Documentation

  • Added CHANGELOG.md following Keep a Changelog format
  • Updated README with version history, badges, and Python version requirements
  • Removed outdated setup.py installation instructions
  • Updated Jupyter notebooks and regenerated all tutorial figures

Updated Examples

  • Regenerated all tutorial figures (figureP01-P20) with current styling
  • Updated both main notebooks to work with latest API
  • All notebook cells execute without errors

Testing

  • All 60 unit tests pass
  • Jupyter notebooks tested and working
  • Package builds successfully with python -m build
  • Pre-commit hooks configured and passing

Version History

This PR combines work from two releases:

  • v0.3.0: Seaborn 0.13.2 compatibility and bug fixes
  • v0.3.1: Modernized packaging, testing, and infrastructure

Seaborn v0.12 and v0.13 introduced significant breaking changes to the internal categorical plotting API, removing `_CategoricalScatterPlotter` and redesigning `_CategoricalPlotter`. This commit refactors the library to restore compatibility with modern Seaborn versions.

Key changes include:

- **Refactored `_Half_ViolinPlotter`**:
  - Now inherits from the modern `seaborn._CategoricalPlotter`.
  - Replaces manual data looping with a more robust and efficient `pandas.groupby` workflow for density estimation.
  - Modernizes internal data handling to use an intermediate list of dictionaries (`violin_data`) instead of parallel lists for support, density, and counts.

- **Rewrote `stripplot` Wrapper**:
  - The custom `_StripPlotter` class, which depended on the removed API, has been deleted.
  - The public `stripplot` function is now a lightweight wrapper around the official `sns.stripplot`.
  - The custom `move` parameter functionality is preserved by manually transforming the plot artist's offsets after it has been drawn.

- **Updated Dependencies**:
  - Bumped the `seaborn` requirement from `0.11` to `0.13.2`.
  - Updated `matplotlib` version constraints in `setup.py` and `requirements.txt`.
This commit introduces several improvements to the codebase to enhance maintainability, fix a latent bug, and decouple from private APIs.

- **Fix `scale_width` Property Bug**: Converts `scale_width` from a `@property` with side effects into a private method `_scale_width()`. This ensures it is called explicitly and corrects the improper use of properties for state-mutating operations.

- **Decouple from Seaborn Internals**: Removes the call to Seaborn's private `_complement_color` function. A local, equivalent utility `_get_complementary_gray` is introduced to ensure long-term API stability.

- **Add Type Hinting**: Introduces type hints to the public functions (`stripplot`, `half_violinplot`, `RainCloud`) to improve code clarity, enable static analysis, and enhance IDE support.

- **Improve Readability**: Adds comments and clarifies logic in `stripplot` and `RainCloud` regarding artist manipulation (`move`) and legend pruning. A constant (`_LEGACY_GRAY`) is also introduced to replace a magic string.
This commit refactors the plotting logic to ensure that when a `hue` variable is used, the components of the raincloud plot (violin, strip plot, box plot) remain aligned on the categorical axis, preserving the intended raincloud aesthetic.

Previously, using a `hue` would cause seaborn's default "dodging" behavior, separating the violins and creating multiple lines in the pointplot, which is not suitable for a raincloud plot where all elements should share a common axis.

The specific changes are:

* **Violin Positioning:** The `_get_center_pos` method in `_Half_ViolinPlotter` has been simplified to remove hue-based horizontal offsets. All violins within a single category now share the same center position, forming a single "cloud."

* **Point Plot ("Thunder Line"):** The call to `sns.pointplot` within the `RainCloud` function no longer passes the `hue` parameter. This ensures that a single line is drawn to connect the means of the main categories, rather than separate, dodged lines for each hue level.

* **Legend Handling:** The old, manual legend creation logic has been removed from `draw_violins`. The plot now uses seaborn's internal `_configure_legend` API within the main `plot` method. This is a more robust and modern approach that aligns with the recent refactoring to support newer seaborn versions.

* **Cloud Direction:** The `split` parameter in `half_violinplot` is no longer toggled when a `hue` is present. This keeps all "clouds" facing the same direction, maintaining the consistent look of the plot.
Seaborn 0.13 emits multiple PathCollections for each stripplot, so the
previous assumption that the final collection held all raindrops caused
the move parameter to shift only one hue/category. That left some
bands centered while others slid to the side.

Capture the collection count before calling sns.stripplot and adjust
the offsets on every new PathCollection, skipping any without offsets.
The rain layer now shifts uniformly for every hue/dodge configuration.
This commit addresses several issues discovered during testing:

**Dodge alignment with stripplot:**
- Fix stripplot dodge offset to match boxplot width when dodge=True
- Seaborn's stripplot uses width=0.8 internally, but RainCloud uses
  width=0.15 for boxplots, causing misalignment
- Implement dodge rescaling by separating dodge offset from jitter
  using median offset per collection, then scaling only the dodge
  component while preserving original jitter magnitude

**Pointplot with multiple hue levels:**
- Fix pointplot to show separate colored lines per hue level when hue
  represents subgroups (e.g., timepoints)
- Previously showed single red line regardless of hue
- Now passes hue, palette, and hue_order to sns.pointplot when needed

**Axis labels:**
- Fix axis labels to use original variable names before x/y swap
- Horizontal plots now correctly show categorical var on y-axis and
  numeric var on x-axis
- Vertical plots show categorical var on x-axis and numeric on y-axis

**Additional fixes:**
- Fix pandas Series comparison bug when determining if hue represents
  subgroups vs just coloring categories
- Improve legend logic to only display when hue is semantically
  different from categorical variable

Version bumped to 0.3.0 to reflect these important behavioral fixes.
- Migrate from setup.py to modern pyproject.toml with hatchling
- Add comprehensive pytest test suite (60 tests, 89% coverage)
- Update CI to test Python 3.9-3.12 on Ubuntu
- Add pre-commit hooks with ruff for code quality
- Remove default palette parameter to avoid seaborn 0.14 warnings
- Update type hints to use modern syntax (list/dict instead of List/Dict)
- Remove deprecated Python 2 imports
- Add CHANGELOG.md and update README with version history
- Clean up unused variables and improve code quality
@pog87
Copy link
Owner

pog87 commented Oct 4, 2025

Cool, thank you! Allow me some time to carefully review before merging.

@pog87
Copy link
Owner

pog87 commented Oct 6, 2025

Approved! Thanks for your valuable contribution.
In case you are partecipating, #hacktoberfest

@pog87 pog87 merged commit 7192fab into pog87:master Oct 6, 2025
4 checks passed
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