Skip to content

Normalize NumPy dtypes and preserve fractional multipoles - #685

Draft
marcpaterno wants to merge 12 commits into
clarify-test-fixturesfrom
normalize-np-dtypes
Draft

marcpaterno wants to merge 12 commits into
clarify-test-fixturesfrom
normalize-np-dtypes

Conversation

@marcpaterno

@marcpaterno marcpaterno commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Make numeric array types explicit at Firecrown's data boundaries: scientific values, redshift samples, and covariance inputs use float64; exact multipoles and SACC indices use checked int64. Preserve fractional multipoles in unwindowed SACC spectra, including the CosmoSIS path, while keeping window grids and indices integral.

SACC unwindowed ell (2.5, 7.5) → float64 through metadata, theory, likelihood
SACC exact/window ell and indices → validated int64

The numeric-type contract is documented in docs/numeric-types.md, with regression coverage for dtype validation, fractional multipoles, and connector behavior. This PR builds on the typed fixtures in the preceding stack PR.

Evidence

  • Before: The integer-contract change rejected fractional unwindowed multipoles, and Augur's pinned CI checkout failed two tests with TypeError.
  • After: The Firecrown regular suite reports 4731 passed, 94 skipped, and 49 warnings; focused dtype and connector tests report 540 passed; nine external example cases pass. The pinned Augur checkout reports 122 passed, no failures. make lint passes.
  • The static PR API report against clarify-test-fixtures reports no breaking public API changes. It does not establish behavioral compatibility.

Merge Danger

Door: Two-way. The change can be reverted without a data migration.

Blast Radius: Numerical paths. Consumers that depended on implicit array dtypes or floating-point values in fields defined as exact integers may need adjustment.

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

PR revision: 622a30c75d2a91cd35bec82db5ac3b9802e0fbe7
Target: clarify-test-fixtures

No breaking API changes detected.

PR public API verdict

No breaking API changes detected.

Target: master
Revision: 622a30c75d2a91cd35bec82db5ac3b9802e0fbe7
Baseline: 15043d41af617b7f36abf2c8d630fd0325afaa66

Static analysis only: no behavioral compatibility guarantee or external-dependency signature analysis.

Public API changes: 15043d4 -> HEAD

Executive summary

No breaking API changes detected.

Breaking changes

None.

New public API

None.

Complete report artifact and workflow run | API job

@codecov

codecov Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.0%. Comparing base (0632c88) to head (622a30c).

Additional details and impacted files
@@                   Coverage Diff                   @@
##           clarify-test-fixtures     #685    +/-   ##
=======================================================
  Coverage                  100.0%   100.0%            
=======================================================
  Files                        163      165     +2     
  Lines                       9979    10134   +155     
  Branches                    1199     1218    +19     
=======================================================
+ Hits                        9979    10134   +155     
Files with missing lines Coverage Δ
firecrown/_integer_arrays.py 100.0% <100.0%> (ø)
firecrown/_source_arrays.py 100.0% <100.0%> (ø)
firecrown/connector/cosmosis/likelihood.py 100.0% <100.0%> (ø)
firecrown/data_functions/_filtering.py 100.0% <100.0%> (ø)
firecrown/data_types/_measurement.py 100.0% <100.0%> (ø)
firecrown/data_types/_utils.py 100.0% <100.0%> (ø)
firecrown/data_types/_vectors.py 100.0% <100.0%> (ø)
firecrown/generators/_inferred_galaxy_zdist.py 100.0% <100.0%> (ø)
firecrown/generators/_two_point.py 100.0% <100.0%> (ø)
firecrown/likelihood/_binned_cluster.py 100.0% <100.0%> (ø)
... and 18 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@marcpaterno
marcpaterno added this pull request to stack #699 October 25, 2026 01:06
@marcpaterno marcpaterno changed the title Normalize np dtypes Normalize NumPy dtypes and preserve fractional multipoles Oct 25, 2026
@vitenti

vitenti commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

Hello @marcpaterno :

  1. the current changes make SACC files with float window support fail to load. Normalize NumPy dtypes and preserve fractional multipoles #685 raises TypeError: Exact multipoles and indices must have an integer dtype. I think it is safe to accept float as long as they are integer values.
  2. SACC's add_ell_cl stores ell as float64, so for ordinary unwindowed data the CosmoSIS connector now writes data_vector/ell_* as a double array instead of an int array, and any reader using get_int_array_1d gets BlockWrongValueType. Could we write int when all values are integral and double only for fractional ells? The two lkscript_two_point*.py changes (add_ell_cl -> add_data_point with int ells) are what keeps the existing CosmoSIS test passing, so this case is not tested.
  3. sacc_indices also seem to break on reading doubles.
  4. get_int_array is still unusable from CosmoSIS: extract_section passes CosmoSIS int arrays as int32, so it now raises TypeError instead of returning wrong values. Converting int32 to int64 in extract_section would fix it.
  5. for cached_angular_cl, cache_clear and cache_info are no longer available on the public function (only on the private _cached_angular_cl), is that what you intended?
  6. About 25 test fixtures and scripts were changed from add_ell_cl to add_data_point with int64 ells; unwindowed add_ell_cl calls in tests went from 36 to 8. add_ell_cl is what users call, so I would keep it everywhere except where integer ells are the point of the test.
  7. docs/numeric-types.md has a dated "Policy status" note saying DataVector/TheoryVector conversion is not implemented yet, but this PR implements it. Also, nothing links to the document.

The array getters used `view()`, which reinterpreted stored bytes as the
requested dtype instead of checking the stored type. An int64 array read
through `get_float_array` returned reinterpreted bit patterns with no
error.

The getters now return the stored array without copying or converting
it, and raise TypeError when its dtype is not native int64 or float64.
Basic-dict conversion stores floating sequences explicitly as float64.

Tests cover matching dtype and shared storage for empty and non-empty
arrays, and rejection of mismatched dtypes, including byte-swapped,
unsigned, bool, and complex storage.
Reject boolean, complex, string, object, structured, datetime, and
masked inputs instead of silently discarding information.

Convert integer and float inputs to float64 before subtraction so
residuals no longer overflow int8 or lose precision in float32.
Return independent copies from get_data_vector and get_theory_vector.

Add tests for supported dtypes, rejected inputs, residual precision,
and Gaussian ingress through read and create_ready. Cover NamedParameters
basic-dict round trips for integer, float, and boolean values.
Add docs/numeric-types.md, a guide for physicists writing likelihoods
that sets the intended NumPy dtype policy: float64 for real scientific
values, int64 for exact multipoles and SACC indices, intp for native
NumPy indices, bool for masks, and strings for identifiers. It covers
converting inputs before arithmetic, accepted and rejected input types,
precision limits, DataVector/TheoryVector handling, NamedParameters
getter contracts, and a checklist for verifying a likelihood.

Retitle GLOSSARY.md to "Firecrown Language" and broaden its scope to
scientific likelihoods. Add terms distinguishing normalization (rescaling
a distribution to unit integral) from dtype conversion (changing a
numeric representation without rescaling), so the guide and glossary use
these words consistently.
Coerce real integer and floating z/dndz inputs to float64 at tomography,
SourceGalaxyArgs, NumberCountsArgs, WeakLensingArgs, the photo-z shift
transforms, and SACC reads. Integer inputs previously made ones_like
produce integer bias and alignment arrays, which truncated fractional
values (e.g. constant IA alignment).

Reject complex, object, string, datetime, structured, and masked arrays
with TypeError before conversion, so their values are not silently
dropped or altered. Conforming float64 inputs may still share storage.

BREAKING CHANGE: source and tomography constructors and the photo-z shift
functions now reject non-real or masked arrays that were previously
accepted.
Document how TomographicBin, SourceGalaxyArgs, NumberCountsArgs, and
WeakLensingArgs accept real integer and floating arrays for redshifts
and distribution values, converting them to float64 storage before
source calculations. Describe the public active and passive photo-z
transforms, which convert before weighted averages and interpolation.

Explain that conforming arrays may share storage, including strided
arrays, while other real dtypes are converted and may round values.
Masked arrays are rejected even when no entries are masked, since there
is no missing-data policy. Note that SACC source reads keep their copy,
flatten, and sort behavior, that tabulated bias and alignment fields
have float64 contracts validated during source-argument construction,
and that tracer preparation supplies double-valued arrays to pyccl.

In the TomographicBin tutorial, create the example redshift grid with
dtype=np.float64 and add a paragraph covering the accepted input dtypes,
rejected dtypes (boolean, complex, string, object, structured, datetime,
and masked), and the unchanged unit and normalization behavior.
Convert real integer and floating redshift arrays to float64 before
evaluating ZDistLSSTSRD distributions and binned distributions, so
results no longer depend on the input storage precision.

Reject unsupported coordinate dtypes (bool, complex, string, object,
structured, datetime, timedelta) and masked arrays with TypeError.

Return float64 from LinearGrid1D, RawGrid1D, equal-area bin edges, and
the Year 1 and Year 10 lens bin helpers.

Add tests for real precision, unsupported inputs, grid and edge dtypes,
and scalar and empty outputs. Update the tutorial to pass
dtype=np.float64 explicitly.
- Reject noninteger, masked, and overflowing inputs before conversion
  across metadata, measurements, likelihoods, and SACC operations.
- Validate multipoles before cache lookup and range-check temporary
  CosmoSIS C int arrays without changing stored domain multipoles.
- Preserve fractional window labels and sampling coordinates; update
  fixtures, tutorials, and tests for integer storage, empty selections,
  covariance ordering, and incompatible example rejection.

BREAKING CHANGE: Exact-multipole and index routes now reject floating
arrays, including integral-valued floats. Fractional CMB-cross and cosmic
shear examples fail at exact-support consumers rather than being accepted.
Supply integer support or use a compatible real-label route; fractional
coordinates are not automatically rounded.
- Add tests for _as_multipole_array rejecting masked arrays and
  arrays with non-integer, non-floating dtypes.
- Add a test for cached_angular_cl rejecting ell tuples that contain
  non-numeric values.
Window weights were summed at their input precision, so reduced-precision
SACC windows could lose accuracy before normalization. Window weights,
effective labels, real angular coordinates, and measured values are now
converted to float64 at their ingress points: TwoPointHarmonic,
TwoPointReal, TwoPointMeasurement, and extract_window_function. Weight
conversion happens before the zero-total check and column sums. Boolean,
complex, string, object, and masked arrays are rejected. Conforming
float64 arrays are shared rather than copied, and the covariance
identifier still hashes the original SACC buffer. Adds workflow and
contract tests for float32, int32, and int64 inputs, and updates the
numeric types documentation.
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