%global pypi_name UncertainSCI Name: python-uncertainsci Version: 1.0.1.1 # Explicit, not %%autorelease -- that macro is inert in this COPR # (ci/PROCEDURES.md golden rule 3). Release: 3%{?dist} Summary: Non-intrusive uncertainty quantification for biomedical simulation License: MIT URL: https://github.com/SCIInstitute/UncertainSCI Source0: %{url}/archive/v%{version}/%{pypi_name}-%{version}.tar.gz # This is the last tagged release (2023-10-12). Master has moved on and adds a # Gaussian-process subpackage, UncertainSCI.gp, that needs jax, equinox and # optax. None of those are in Fedora, and jax pulls in jaxlib, a Bazel/XLA # build. So we ship the tag and take only the master fixes it needs. Both # patches are upstream commits, exported with git format-patch, so they carry # their own author, date and message: # # Patch0 is 7c3789b "numpy: update to numpy 2" (2026-07-02). Without it the # tag fails 12 of its 29 tests on Fedora's numpy 2.4.6, and the failures are # in the library, not just the tests. families.py:335/358/821 convert size-1 # arrays to Python scalars (a TypeError since numpy 2.4: "only 0-dimensional # arrays can be converted to Python scalars"), and np.Inf was removed in # numpy 2.0. So the Jacobi, Laguerre and Hermite families are broken for # real users, not only in the suite. The patch also raises the numpy floor # in setup.py to >= 1.25. Patch0: python-uncertainsci-numpy2.patch # Patch1 is e08dfb7 "tests: deltas and whitespace changes" (2026-07-02). It # changes tests only, and it widens tolerances where the tests "fail # randomly". With Patch0 alone, 5 of 10 consecutive runs here failed, across # four different randomised-input tests (test_idistinv_Hermite, # test_fidist_jacobi, test_idistinv_laguerre, test_derivative_expansion). # That would fail about half of all COPR builds. Patch1: python-uncertainsci-test-tolerances.patch # Patch2 is ours. utils/version.py does `from packaging import version`, and # pce.py and distributions.py import that module at the top, so # `import UncertainSCI.pce` fails without packaging. The tag never declares # it; master's pyproject.toml does. This puts it into install_requires, so # the generated python3dist() Requires include it. Patch2: python-uncertainsci-declare-packaging.patch # Patch3 is ours, and it is the one that matters most. JacobiPolynomials # .fidistinv() caches precomputed data as pickles in # dirname(dirname(UncertainSCI.__file__))/data_set, i.e. # /usr/lib/python3.X/site-packages/data_set on a system install. Only # FileExistsError is caught, so for any non-root user os.makedirs raises # PermissionError. fidistinv is the default (fast_sampler=True) inverse for # every Jacobi family, which covers Uniform and Beta inputs, so # PolynomialChaosExpansion.generate_samples() -- step one of every upstream # demo -- failed for both, as uid 1000 against a read-only install. Run as # root, it would instead leave unowned pickles in /usr for every user to # unpickle. The patch moves the cache to $XDG_CACHE_HOME/UncertainSCI and # computes without a cache when that is not writable. It is still # upstream's code in master. %%check carries a regression test for it. Patch3: python-uncertainsci-user-cache.patch # Patch4 is ours, and changes tests only: two tests that fail at random for # reasons in the TEST, not the library. Found by running the suite 20+ times # rather than once. # - test_derivative_expansion compares derivative-expansion coefficients # against an ABSOLUTE 1e-8. For third derivatives they reach ~1e5, so # roundoff alone exceeds it. Over 300 random draws the worst RELATIVE error # was 1.45e-12; 7 draws broke the absolute bound, all at s=3. Made relative. # - test_gq draws N from randint(0, 61). N=0 is a 0-point rule, np.dot(w, V) # is then a 0-d scalar, and integrals[0] raises "IndexError: invalid index # to scalar variable" -- 1 run in 61. Draws from 1 now. # - test_exp_dist checks a Monte Carlo mean (M = 1e7) against an absolute # 0.1, with the rate drawn as lbd = -n*rand(). The exponential's sd is # 1/|lbd|, so near lbd = 0 the standard error passes 0.1 (at |lbd| = # 0.003 it is 0.105 and the check failed 3 of 8 times; at 0.01 it is # 0.032 and failed 0 of 8). The library is right. The tolerance now also # allows 5 standard errors. Patch4: python-uncertainsci-test-fixes.patch BuildArch: noarch BuildRequires: python3-devel BuildRequires: python3dist(pytest) %global _description %{expand: UncertainSCI is a Python toolkit from the SCI Institute (University of Utah) that estimates model and parametric uncertainty, with an emphasis on biomedical simulation. It uses polynomial chaos expansions (PCE) and treats the simulator as a black box. The user sets input distributions, builds a PCE, samples the parameter space, runs those samples through any external model, and then computes output statistics and sensitivities from the expansion.} %description %_description %package -n python3-uncertainsci Summary: %{summary} # Users will look for the import name. %py_provides python3-%{pypi_name} %description -n python3-uncertainsci %_description %prep %autosetup -n %{pypi_name}-%{version} -p1 %generate_buildrequires %pyproject_buildrequires %build %pyproject_wheel %install %pyproject_install %pyproject_save_files -l %{pypi_name} %check %pyproject_check_import # The upstream suite: 30 tests, about 35 s, no network. Only # UncertainSCI.vis uses matplotlib, but set Agg anyway so that nothing can # try to open a window on the builder. The fidistinv cache goes to a scratch # directory rather than the builder's home. export MPLBACKEND=Agg export XDG_CACHE_HOME=$(mktemp -d) # # Make the suite deterministic. Its tests draw ~95 random parameters from # numpy's global RNG, unseeded, so every build tested a fresh sample of the # parameter space and could fail on an unlucky draw. Repeated local runs # found four such tests (fixed in Patch4), and COPR then found a fifth: # build 11091855 failed on fedora-44-x86_64 alone, with # test_gq_modification_composite at beta = -0.9907, right at the singular # edge, 5.2e-5 against an absolute 5e-6. The other five chroots passed the # same code. A build gate must not be a lottery. Seed numpy per test from a # CRC of the test id, so every build on every arch tests the same # parameters regardless of test order. This changes only the source tree's # (unshipped) top-level conftest.py, which upstream leaves empty. Exploring # random parameters is still worth doing, locally and repeatedly (trap 52 # in docs/application-level-testing.md), not on the builder. cat >> conftest.py <<'EOF' # neurofedora %%check: seed numpy's global RNG per test, from the test's id import zlib import numpy as np import pytest @pytest.fixture(autouse=True) def _neurofedora_seed(request): np.random.seed(zlib.crc32(request.node.nodeid.encode())) EOF # # test_fidist_jacobi is deselected, and NOT because it is noise. It checks # the fast Jacobi inverse CDF (fidistinv) against the exact one (idistinv) at # random alpha, beta in [-1, 10), with a tolerance upstream itself calls # "unacceptably high" (0.1). It fails because the fast inverse is genuinely # wrong for a small fraction of inputs. In 80 random draws, 5 disagreed by # more than 0.1. In every one the exact inverse reproduced u through idist() # to ~1e-14 and the fast one did not, and twice the fast one returned a point # OUTSIDE the support [-1, 1] (x = 1.104, x = 1.739). It also hits the # uniform case (alpha = beta = 0): at n=1, 1 of 2000 samples was off by 0.54, # at u = 0.4998, just inside a bin edge. The cause is in the algorithm: each # bin stores a degree-9 Chebyshev fit of the inverse times (1 -+ v)^(2/3), # and evaluating divides that back out, amplifying fit error ~80x within # 1e-3 of a bin edge. Unfixed in upstream master. It fails ~15% of builds, # so it cannot gate one, and it is a numerical-method problem for upstream # rather than a packaging change. Tracked in docs/KNOWN-ISSUES.md. %pytest -v tests -k "not test_fidist_jacobi" # # Regression test for Patch3, as an unprivileged user would hit it: copy the # installed package into a read-only tree, and require the default PCE # sampler to work for both a Beta and a Uniform input. Without Patch3 both # raise PermissionError. The buildroot itself is writable, so the suite # above cannot see this. ro=$(mktemp -d) cp -a %{buildroot}%{python3_sitelib}/%{pypi_name} "$ro/" chmod -R a-w "$ro" (cd / && %{python3} -I - "$ro" <<'EOF' import sys sys.path.insert(0, sys.argv[1]) import numpy as np from UncertainSCI.distributions import BetaDistribution, UniformDistribution from UncertainSCI.pce import PolynomialChaosExpansion assert __import__('UncertainSCI').__file__.startswith(sys.argv[1]), "wrong UncertainSCI imported" for dist in ([BetaDistribution(alpha=0.5, beta=1.), BetaDistribution(alpha=1., beta=0.5)], UniformDistribution(domain=np.array([[0., 0.], [1., 1.]]))): pce = PolynomialChaosExpansion(distribution=dist, order=3) pce.generate_samples() assert pce.samples.shape == (20, 2), pce.samples.shape assert np.all(np.isfinite(pce.samples)) print("read-only install: PCE sampling OK") EOF ) test -z "$(find "$ro" -name data_set)" chmod -R u+w "$ro"; rm -rf "$ro" %files -n python3-uncertainsci -f %{pyproject_files} %doc README.md CITATION.cff %changelog * Wed Oct 07 2026 Morgan Hough - 1.0.1.1-3 - Seed numpy per test in %%check. -2 failed on fedora-44-x86_64 alone (COPR 11091855) on a fifth random-parameter test, test_gq_modification_composite at beta = -0.9907; the other five chroots passed. Verified that the fixture reaches the unittest-style tests (identical draws across runs; different without it), and that the seeded suite is green and order-independent. * Wed Oct 07 2026 Morgan Hough - 1.0.1.1-2 - Fix a third randomly failing test, test_exp_dist: an absolute tolerance on a Monte Carlo mean whose standard error grows without bound as the drawn rate approaches 0. It failed 1 of 18 suite runs; library unaffected. * Wed Oct 07 2026 Morgan Hough - 1.0.1.1-1 - Initial package. Tag v1.0.1.1 plus two upstream commits, for numpy 2 (7c3789b) and flaky test tolerances (e08dfb7). - Declare the dependency on packaging, which the code imports. - Move the fidistinv cache out of site-packages to $XDG_CACHE_HOME. Without this, PCE sampling fails with PermissionError for non-root users. - Fix two randomly failing tests: a relative tolerance for test_derivative_expansion, and no 0-point rule in test_gq. - Deselect test_fidist_jacobi, which catches a real upstream accuracy bug.