Skip to content

Preserve fractional cyclic coordinates for integer input - #273

Open
ktz03 wants to merge 1 commit into
pydata:masterfrom
ktz03:fix/cc-integer-periodic-mapping
Open

ktz03 wants to merge 1 commit into
pydata:masterfrom
ktz03:fix/cc-integer-periodic-mapping

Conversation

@ktz03

@ktz03 ktz03 commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

cc() truncates fractional periodic coordinates when its input has an integer dtype. For example, with bounds 0.1 and 3.4, the coordinate 4 should wrap to approximately 0.7; assigning that result into an integer array changes the resulting spline basis. This affects direct cc(), formula construction and prediction using an existing DesignInfo.

Convert integer coordinates to floating point before cyclic mapping. Preserve the existing floating-point input dtype and input immutability. Add direct mapping and public-API regressions covering signed and unsigned integer input, float32/float64 controls, centering and prediction.

Validation on Windows with Python 3.13.15, NumPy 2.5.4, SciPy 1.18.1 and pandas 3.0.6:

  • Reproduced on the latest PyPI release, 1.0.3, and current master. The integer/float basis difference changes from 1.1751149047931713 to zero in the minimal reproduction.
  • The complete pytest suite passes 159 tests with one existing skip (test_EvalEnvironment_eq), both normally and with the official PATSY_AVOID_OPTIONAL_DEPENDENCIES=1 compatibility mode. The same final tests on the original implementation produce seven failures, all new integer regressions; five new controls pass.
  • The official API-reference check, Ruff 0.16.10 formatting check for both changed files and git diff --check pass.

The full official Python/platform matrix and an R/mgcv runtime comparison were not run locally. The compatibility mode was run with pandas and SciPy installed.

Fixes #272.

@bashtage

Copy link
Copy Markdown
Contributor

This is a change in behavior in the sense that the same inputs produce different outputs. With the current maintenance-focused approach to minimal patch releases, it is challenging to merge patches, even when they are likely correct. There is a clear workaround for users for this since they can convert to float themselves.

So I'd say I'm unsure about this.

@codecov-commenter

codecov-commenter commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.45%. Comparing base (331879f) to head (36f8bc8).
⚠️ Report is 85 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #273      +/-   ##
==========================================
+ Coverage   97.60%   98.45%   +0.84%     
==========================================
  Files          30       30              
  Lines        3096     3107      +11     
  Branches      591      677      +86     
==========================================
+ Hits         3022     3059      +37     
+ Misses         39       27      -12     
+ Partials       35       21      -14     
Flag Coverage Δ
unittests 98.06% <100.00%> (+0.45%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

cc() truncates periodic coordinates for integer input with fractional bounds

3 participants