Warning: Permanently added '3.80.172.70' (ED25519) to the list of known hosts. You can reproduce this build on your computer by running: sudo dnf install copr-rpmbuild /usr/bin/copr-rpmbuild --verbose --drop-resultdir --task-url https://copr.fedorainfracloud.org/backend/get-build-task/11283289-fedora-44-aarch64 --chroot fedora-44-aarch64 Version: 1.11 PID: 11817 Logging PID: 11819 Task: {'allow_user_ssh': False, 'appstream': False, 'background': False, 'build_id': 11283289, 'buildroot_pkgs': [], 'chroot': 'fedora-44-aarch64', 'enable_net': False, 'fedora_review': False, 'git_hash': '8d50c187fa9c88e50d7f946c5f309e0fa9526e08', 'git_repo': 'https://copr-dist-git.fedorainfracloud.org/git/mhough/neurofedora/python-pyradplan', 'isolation': 'default', 'memory_reqs': 2048, 'package_name': 'python-pyradplan', 'package_version': '0.8.0-1', 'project_dirname': 'neurofedora', 'project_name': 'neurofedora', 'project_owner': 'mhough', 'repo_priority': None, 'repos': [{'baseurl': 'https://download.copr.fedorainfracloud.org/results/mhough/neurofedora/fedora-44-aarch64/', 'id': 'copr_base', 'name': 'Copr repository', 'priority': None, 'repo_gpgcheck': False}], 'sandbox': 'mhough/neurofedora--mhough', 'source_json': {}, 'source_type': None, 'ssh_public_keys': None, 'storage': 1, 'submitter': 'mhough', 'tags': [], 'task_id': '11283289-fedora-44-aarch64', 'timeout': 86400, 'uses_devel_repo': False, 'with_opts': [], 'without_opts': []} Running: git clone https://copr-dist-git.fedorainfracloud.org/git/mhough/neurofedora/python-pyradplan /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan --depth 500 --no-single-branch --recursive cmd: ['git', 'clone', 'https://copr-dist-git.fedorainfracloud.org/git/mhough/neurofedora/python-pyradplan', '/var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan', '--depth', '500', '--no-single-branch', '--recursive'] cwd: . rc: 0 stdout: stderr: Cloning into '/var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan'... Running: git checkout 8d50c187fa9c88e50d7f946c5f309e0fa9526e08 -- cmd: ['git', 'checkout', '8d50c187fa9c88e50d7f946c5f309e0fa9526e08', '--'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan rc: 0 stdout: stderr: Note: switching to '8d50c187fa9c88e50d7f946c5f309e0fa9526e08'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c Or undo this operation with: git switch - Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at 8d50c18 automatic import of python-pyradplan Running: dist-git-client sources cmd: ['dist-git-client', 'sources'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan rc: 0 stdout: stderr: INFO: Reading stdout from command: git rev-parse --abbrev-ref HEAD INFO: Reading stdout from command: git rev-parse HEAD INFO: Reading sources specification file: sources INFO: Downloading pyradplan-0.8.0.tar.gz INFO: Reading stdout from command: curl --help all INFO: Calling: curl -H Pragma: -H 'Accept-Encoding: identity' -o pyradplan-0.8.0.tar.gz --location --connect-timeout 60 --retry 3 --retry-delay 10 --remote-time --show-error --fail --retry-all-errors https://copr-dist-git.fedorainfracloud.org/repo/pkgs/mhough/neurofedora/python-pyradplan/pyradplan-0.8.0.tar.gz/md5/20981edf7484cea480762e9af971343e/pyradplan-0.8.0.tar.gz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 33.80M 100 33.80M 0 0 442.7M 0 0 INFO: Reading stdout from command: md5sum pyradplan-0.8.0.tar.gz tail: /var/lib/copr-rpmbuild/main.log: file truncated Running (timeout=86400): unbuffer mock --spec /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan/python-pyradplan.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1794040424.031981 -r /var/lib/copr-rpmbuild/results/configs/child.cfg INFO: mock.py version 6.9 starting (python version = 3.14.5, NVR = mock-6.9-1.fc44), args: /usr/libexec/mock/mock --spec /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan/python-pyradplan.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1794040424.031981 -r /var/lib/copr-rpmbuild/results/configs/child.cfg Start(bootstrap): init plugins INFO: tmpfs initialized INFO: selinux enabled INFO: chroot_scan: initialized INFO: compress_logs: initialized Finish(bootstrap): init plugins Start: init plugins INFO: tmpfs initialized INFO: selinux enabled INFO: chroot_scan: initialized INFO: compress_logs: initialized Finish: init plugins INFO: Signal handler active Start: run INFO: Start(/var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan/python-pyradplan.spec) Config(fedora-44-aarch64) Start: clean chroot Finish: clean chroot Mock Version: 6.9 INFO: Mock Version: 6.9 Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-44-aarch64-bootstrap-1794040424.031981/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start(bootstrap): cleaning package manager metadata Finish(bootstrap): cleaning package manager metadata INFO: Guessed host environment type: unknown INFO: Using container image: registry.fedoraproject.org/fedora:44 INFO: Pulling image: registry.fedoraproject.org/fedora:44 INFO: Tagging container image as mock-bootstrap-605549de-5e63-4865-93d6-b704c5b97bde INFO: Checking that 7ae77108e07e055ffe24cb699c4ae0b4449f550ac645d185debf3a67c621ab39 image matches host's architecture INFO: Copy content of container 7ae77108e07e055ffe24cb699c4ae0b4449f550ac645d185debf3a67c621ab39 to /var/lib/mock/fedora-44-aarch64-bootstrap-1794040424.031981/root INFO: mounting 7ae77108e07e055ffe24cb699c4ae0b4449f550ac645d185debf3a67c621ab39 with podman image mount INFO: image 7ae77108e07e055ffe24cb699c4ae0b4449f550ac645d185debf3a67c621ab39 as /var/lib/containers/storage/overlay/984fd31702ef95a47582f03380de3842e6594ff420de1593ea8da3ed483f1f53/merged INFO: umounting image 7ae77108e07e055ffe24cb699c4ae0b4449f550ac645d185debf3a67c621ab39 (/var/lib/containers/storage/overlay/984fd31702ef95a47582f03380de3842e6594ff420de1593ea8da3ed483f1f53/merged) with podman image umount INFO: Removing image mock-bootstrap-605549de-5e63-4865-93d6-b704c5b97bde INFO: Package manager dnf5 detected and used (fallback) INFO: Not updating bootstrap chroot, bootstrap_image_ready=True Start(bootstrap): creating root cache Finish(bootstrap): creating root cache Finish(bootstrap): chroot init Start: chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-44-aarch64-1794040424.031981/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start: cleaning package manager metadata Finish: cleaning package manager metadata INFO: enabled HW Info plugin INFO: Package manager dnf5 detected and used (direct choice) INFO: Buildroot is handled by package management downloaded with a bootstrap image: rpm-6.0.2-1.fc44.aarch64 rpm-sequoia-1.10.3-1.fc44.aarch64 dnf5-5.4.6.0-1.fc44.aarch64 dnf5-plugins-5.4.6.0-1.fc44.aarch64 Start: installing minimal buildroot with dnf5 Updating and loading repositories: updates 100% | 13.4 MiB/s | 12.5 MiB | 00m01s Copr repository 100% | 910.4 KiB/s | 809.3 KiB | 00m01s fedora 100% | 27.4 MiB/s | 36.3 MiB | 00m01s Repositories loaded. Package Arch Version Repository Size Installing group/module packages: bash aarch64 0:5.3.9-3.fc44 fedora 8.4 MiB bzip2 aarch64 0:1.0.8-23.fc44 fedora 171.1 KiB coreutils aarch64 0:9.10-5.fc44 updates 8.2 MiB cpio aarch64 0:2.15-9.fc44 fedora 1.1 MiB diffutils aarch64 0:3.12-5.fc44 fedora 1.6 MiB fedora-release-common noarch 0:44-18 updates 20.6 KiB findutils aarch64 1:4.10.0-7.fc44 fedora 1.9 MiB gawk aarch64 0:5.3.2-3.fc44 fedora 2.6 MiB glibc-minimal-langpack aarch64 0:2.43-9.fc44 updates 0.0 B grep aarch64 0:3.12-3.fc44 fedora 1.0 MiB gzip aarch64 0:1.14-2.fc44 fedora 437.5 KiB info aarch64 0:7.2-9.fc44 fedora 421.5 KiB patch aarch64 0:2.8-4.fc44 fedora 262.4 KiB redhat-rpm-config noarch 0:344-2.fc44 updates 183.7 KiB rpm-build aarch64 0:6.0.2-1.fc44 updates 598.7 KiB sed aarch64 0:4.9-7.fc44 fedora 873.1 KiB shadow-utils aarch64 2:4.19.0-7.fc44 updates 4.4 MiB tar aarch64 2:1.35-9.fc44 updates 3.0 MiB unzip aarch64 0:6.0-69.fc44 fedora 533.8 KiB util-linux aarch64 0:2.41.6-1.fc44 updates 6.8 MiB which aarch64 0:2.25-1.fc44 updates 123.6 KiB xz aarch64 1:5.8.2-2.fc44 fedora 1.4 MiB Installing dependencies: R-srpm-macros noarch 0:1.3.7-2.fc44 updates 3.5 KiB add-determinism aarch64 0:0.7.3-2.fc44 updates 2.0 MiB alternatives aarch64 0:1.33-5.fc44 fedora 90.1 KiB ansible-srpm-macros noarch 0:1-20.1.fc44 fedora 35.7 KiB audit-libs aarch64 0:4.2.1-1.fc44 updates 486.7 KiB binutils aarch64 0:2.46.1-1.fc44 updates 31.5 MiB build-reproducibility-srpm-macros noarch 0:0.7.3-2.fc44 updates 1.2 KiB bzip2-libs aarch64 0:1.0.8-23.fc44 fedora 72.5 KiB ca-certificates noarch 0:2026.2.92_v9.0.319-2.fc44 updates 2.7 MiB cmake-srpm-macros noarch 0:4.3.0-1.fc44 fedora 524.0 B coreutils-common aarch64 0:9.10-5.fc44 updates 10.7 MiB crypto-policies noarch 0:20251128-3.git19878fe.fc44 fedora 132.6 KiB curl aarch64 0:8.18.0-14.fc44 updates 464.2 KiB cyrus-sasl-lib aarch64 0:2.1.28-35.fc44 fedora 2.4 MiB debugedit aarch64 0:5.3-2.fc44 updates 320.9 KiB dwz aarch64 0:0.16-3.fc44 fedora 322.4 KiB ed aarch64 0:1.22.5-2.fc44 fedora 157.8 KiB efi-srpm-macros noarch 0:6-6.fc44 fedora 40.2 KiB elfutils aarch64 0:0.197-1.fc44 updates 3.6 MiB elfutils-debuginfod-client aarch64 0:0.197-1.fc44 updates 144.0 KiB elfutils-default-yama-scope noarch 0:0.197-1.fc44 updates 1.8 KiB elfutils-libelf aarch64 0:0.197-1.fc44 updates 1.6 MiB elfutils-libs aarch64 0:0.197-1.fc44 updates 746.7 KiB erlang-srpm-macros noarch 0:0.4.0-1.fc44 updates 2.0 KiB fedora-gpg-keys noarch 0:44-2 updates 257.6 KiB fedora-release noarch 0:44-18 updates 0.0 B fedora-release-identity-basic noarch 0:44-18 updates 629.0 B fedora-repos noarch 0:44-2 updates 4.9 KiB file aarch64 0:5.48-2.fc44 updates 141.9 KiB file-libs aarch64 0:5.48-2.fc44 updates 12.4 MiB filesystem aarch64 0:3.18-52.fc44 fedora 112.0 B filesystem-srpm-macros noarch 0:3.18-52.fc44 fedora 38.2 KiB fonts-srpm-macros noarch 1:5.0.0-2.fc44 fedora 55.8 KiB forge-srpm-macros noarch 0:0.4.0-4.fc44 fedora 38.9 KiB fpc-srpm-macros noarch 0:1.3-16.fc44 fedora 144.0 B gap-srpm-macros noarch 0:2-2.fc44 fedora 2.1 KiB gdb-minimal aarch64 0:18.1-1.fc44 updates 13.8 MiB gdbm-libs aarch64 1:1.23-11.fc44 fedora 233.7 KiB ghc-srpm-macros noarch 0:1.10-1.fc44 fedora 792.0 B glibc aarch64 0:2.43-9.fc44 updates 6.4 MiB glibc-common aarch64 0:2.43-9.fc44 updates 1.3 MiB glibc-gconv-extra aarch64 0:2.43-9.fc44 updates 18.5 MiB gmp aarch64 1:6.3.0-5.fc44 fedora 657.9 KiB gnat-srpm-macros noarch 0:7-2.fc44 fedora 1.0 KiB gnome-srpm-macros noarch 0:1.0-1.fc44 updates 3.5 KiB gnulib-l10n noarch 0:20241231-2.fc44 fedora 655.0 KiB gnupg2 aarch64 0:2.4.9-16.fc44 updates 6.4 MiB gnupg2-dirmngr aarch64 0:2.4.9-16.fc44 updates 646.1 KiB gnupg2-gpg-agent aarch64 0:2.4.9-16.fc44 updates 846.9 KiB gnupg2-gpgconf aarch64 0:2.4.9-16.fc44 updates 321.8 KiB gnupg2-keyboxd aarch64 0:2.4.9-16.fc44 updates 233.3 KiB gnupg2-verify aarch64 0:2.4.9-16.fc44 updates 364.3 KiB gnutls aarch64 0:3.8.13-1.fc44 updates 3.7 MiB go-srpm-macros noarch 0:3.8.0-2.fc44 fedora 61.9 KiB gpgverify noarch 0:2.2-4.fc44 fedora 8.7 KiB ima-evm-utils-libs aarch64 0:1.6.2-8.fc44 fedora 92.6 KiB jansson aarch64 0:2.14-4.fc44 fedora 93.0 KiB java-srpm-macros noarch 0:1-8.fc44 fedora 870.0 B json-c aarch64 0:0.18-8.fc44 fedora 138.5 KiB kernel-srpm-macros noarch 0:1.0-28.fc44 fedora 1.9 KiB keyutils-libs aarch64 0:1.6.3-7.fc44 fedora 98.2 KiB krb5-libs aarch64 0:1.22.2-4.fc44 updates 2.5 MiB libacl aarch64 0:2.4.0-1.fc44 updates 67.9 KiB libarchive aarch64 0:3.8.7-1.fc44 updates 975.5 KiB libassuan aarch64 0:2.5.7-5.fc44 fedora 215.8 KiB libattr aarch64 0:2.6.0-1.fc44 updates 68.4 KiB libblkid aarch64 0:2.41.6-1.fc44 updates 290.3 KiB libbrotli aarch64 0:1.2.1-1.fc44 updates 909.2 KiB libcap aarch64 0:2.78-1.fc44 updates 508.4 KiB libcap-ng aarch64 0:0.9.6-1.fc44 updates 160.9 KiB libcbor aarch64 0:0.13.0-2.fc44 fedora 139.5 KiB libcom_err aarch64 0:1.47.3-4.fc44 fedora 111.0 KiB libcurl aarch64 0:8.18.0-14.fc44 updates 980.9 KiB libeconf aarch64 0:0.7.9-3.fc44 fedora 80.8 KiB libevent aarch64 0:2.1.13-1.fc44 updates 1.1 MiB libfdisk aarch64 0:2.41.6-1.fc44 updates 418.8 KiB libffi aarch64 0:3.5.2-2.fc44 fedora 155.7 KiB libfido2 aarch64 0:1.16.0-5.fc44 fedora 278.6 KiB libfsverity aarch64 0:1.6-4.fc44 fedora 68.4 KiB libgcc aarch64 0:16.2.1-3.fc44 updates 222.3 KiB libgcrypt aarch64 0:1.12.2-1.fc44 updates 1.2 MiB libgomp aarch64 0:16.2.1-3.fc44 updates 592.9 KiB libgpg-error aarch64 0:1.58-2.fc44 fedora 989.6 KiB libidn2 aarch64 0:2.3.8-3.fc44 fedora 560.4 KiB libksba aarch64 0:1.6.7-5.fc44 fedora 398.3 KiB liblastlog2 aarch64 0:2.41.6-1.fc44 updates 137.8 KiB libmount aarch64 0:2.41.6-1.fc44 updates 420.2 KiB libnghttp2 aarch64 0:1.68.0-5.fc44 updates 197.9 KiB libnghttp3 aarch64 0:1.18.0-1.fc44 updates 206.8 KiB libpfm aarch64 0:4.14.1-2.fc44 updates 513.2 KiB libpkgconf aarch64 0:2.5.1-1.fc44 fedora 134.1 KiB libpsl aarch64 0:0.21.5-7.fc44 fedora 132.3 KiB libselinux aarch64 0:3.11-2.fc44 updates 265.2 KiB libselinux-utils aarch64 0:3.11-2.fc44 updates 1.3 MiB libsemanage aarch64 0:3.11-1.fc44 updates 360.1 KiB libsepol aarch64 0:3.11-1.fc44 updates 809.9 KiB libsmartcols aarch64 0:2.41.6-1.fc44 updates 224.4 KiB libssh aarch64 0:0.12.2-1.fc44 updates 721.3 KiB libssh-config noarch 0:0.12.2-1.fc44 updates 277.0 B libstdc++ aarch64 0:16.2.1-3.fc44 updates 3.0 MiB libtasn1 aarch64 0:4.21.0-1.fc44 fedora 220.7 KiB libtool-ltdl aarch64 0:2.5.4-10.fc44 fedora 93.9 KiB libunistring aarch64 0:1.1-11.fc44 fedora 1.7 MiB libusb1 aarch64 0:1.0.30-1.fc44 updates 179.7 KiB libuuid aarch64 0:2.41.6-1.fc44 updates 69.3 KiB libverto aarch64 0:0.3.2-12.fc44 fedora 69.3 KiB libxcrypt aarch64 0:4.5.2-3.fc44 fedora 273.2 KiB libxml2 aarch64 0:2.12.10-6.fc44 fedora 1.9 MiB libzstd aarch64 0:1.5.7-5.fc44 fedora 860.2 KiB linkdupes aarch64 0:0.7.3-2.fc44 updates 713.7 KiB lua-libs aarch64 0:5.4.8-5.fc44 fedora 329.8 KiB lua-srpm-macros noarch 0:1-17.fc44 fedora 1.3 KiB lz4-libs aarch64 0:1.10.0-4.fc44 fedora 197.3 KiB mpfr aarch64 0:4.2.2-3.fc44 fedora 755.4 KiB ncurses-base noarch 0:6.6-1.fc44 fedora 329.7 KiB ncurses-libs aarch64 0:6.6-1.fc44 fedora 1.2 MiB nettle aarch64 0:3.10.1-3.fc44 fedora 765.0 KiB ngtcp2 aarch64 0:1.22.1-1.fc44 updates 341.1 KiB ngtcp2-crypto-ossl aarch64 0:1.22.1-1.fc44 updates 67.5 KiB npth aarch64 0:1.8-4.fc44 fedora 93.3 KiB ocaml-srpm-macros noarch 0:11-3.fc44 fedora 1.9 KiB openblas-srpm-macros noarch 0:2-21.fc44 fedora 112.0 B openldap aarch64 0:2.6.16-1.fc44 updates 766.1 KiB openssl-libs aarch64 1:3.5.9-1.fc44 updates 7.5 MiB p11-kit aarch64 0:0.26.5-1.fc44 updates 2.8 MiB p11-kit-trust aarch64 0:0.26.5-1.fc44 updates 530.1 KiB package-notes-srpm-macros noarch 0:0.20-1.fc44 updates 1.6 KiB pam-libs aarch64 0:1.7.2-2.fc44 updates 222.7 KiB pcre2 aarch64 0:10.47-1.fc44.1 fedora 714.3 KiB pcre2-syntax noarch 0:10.47-1.fc44.1 fedora 281.9 KiB perl-srpm-macros noarch 0:1-61.fc44 fedora 861.0 B pkgconf aarch64 0:2.5.1-1.fc44 fedora 116.8 KiB pkgconf-m4 noarch 0:2.5.1-1.fc44 fedora 14.3 KiB pkgconf-pkg-config aarch64 0:2.5.1-1.fc44 fedora 990.0 B policycoreutils aarch64 0:3.11-2.fc44 updates 1.5 MiB popt aarch64 0:1.19-10.fc44 fedora 144.6 KiB publicsuffix-list-dafsa noarch 0:20260116-1.fc44 fedora 70.4 KiB pyproject-srpm-macros noarch 0:1.24.0-1.fc44 updates 3.4 KiB python-srpm-macros noarch 0:3.14-12.fc44 fedora 51.6 KiB qt5-srpm-macros noarch 0:5.15.18-2.fc44 fedora 500.0 B qt6-srpm-macros noarch 0:6.11.2-1.fc44 updates 472.0 B readline aarch64 0:8.3-4.fc44 fedora 563.5 KiB rpm aarch64 0:6.0.2-1.fc44 updates 3.3 MiB rpm-build-libs aarch64 0:6.0.2-1.fc44 updates 264.1 KiB rpm-libs aarch64 0:6.0.2-1.fc44 updates 995.2 KiB rpm-plugin-selinux aarch64 0:6.0.2-1.fc44 updates 67.9 KiB rpm-sequoia aarch64 0:1.10.3-1.fc44 updates 2.3 MiB rpm-sign-libs aarch64 0:6.0.2-1.fc44 updates 67.7 KiB rust-srpm-macros noarch 0:28.5-1.fc44 updates 5.5 KiB selinux-policy noarch 0:44.11-1.fc44 updates 32.1 KiB selinux-policy-targeted noarch 0:44.11-1.fc44 updates 18.6 MiB setup noarch 0:2.15.0-28.fc44 fedora 724.9 KiB sqlite-libs aarch64 0:3.51.2-2.fc44 updates 1.6 MiB systemd-libs aarch64 0:259.10-1.fc44 updates 2.5 MiB systemd-standalone-sysusers aarch64 0:259.10-1.fc44 updates 329.6 KiB tpm2-tss aarch64 0:4.1.5-1.fc44 updates 2.1 MiB tree-sitter-srpm-macros noarch 0:0.4.2-2.fc44 fedora 8.3 KiB util-linux-core aarch64 0:2.41.6-1.fc44 updates 2.4 MiB xxhash-libs aarch64 0:0.8.4-2.fc44 updates 85.8 KiB xz-libs aarch64 1:5.8.2-2.fc44 fedora 265.4 KiB zig-srpm-macros noarch 0:1-8.fc44 fedora 1.3 KiB zip aarch64 0:3.0-45.fc44 fedora 762.0 KiB zlib-ng-compat aarch64 0:2.3.3-3.fc44 fedora 133.4 KiB zstd aarch64 0:1.5.7-5.fc44 fedora 562.2 KiB Installing groups: Buildsystem building group Transaction Summary: Installing: 186 packages Total size of inbound packages is 67 MiB. Need to download 67 MiB. After this operation, 252 MiB extra will be used (install 252 MiB, remove 0 B). [ 1/186] bzip2-0:1.0.8-23.fc44.aarch64 100% | 4.6 MiB/s | 51.9 KiB | 00m00s [ 2/186] cpio-0:2.15-9.fc44.aarch64 100% | 15.7 MiB/s | 289.7 KiB | 00m00s [ 3/186] diffutils-0:3.12-5.fc44.aarch 100% | 54.7 MiB/s | 391.9 KiB | 00m00s [ 4/186] bash-0:5.3.9-3.fc44.aarch64 100% | 83.7 MiB/s | 1.8 MiB | 00m00s [ 5/186] findutils-1:4.10.0-7.fc44.aar 100% | 89.9 MiB/s | 552.0 KiB | 00m00s [ 6/186] gawk-0:5.3.2-3.fc44.aarch64 100% | 159.6 MiB/s | 1.1 MiB | 00m00s [ 7/186] grep-0:3.12-3.fc44.aarch64 100% | 57.9 MiB/s | 296.3 KiB | 00m00s [ 8/186] gzip-0:1.14-2.fc44.aarch64 100% | 56.2 MiB/s | 172.8 KiB | 00m00s [ 9/186] info-0:7.2-9.fc44.aarch64 100% | 58.3 MiB/s | 179.0 KiB | 00m00s [ 10/186] patch-0:2.8-4.fc44.aarch64 100% | 36.2 MiB/s | 111.1 KiB | 00m00s [ 11/186] sed-0:4.9-7.fc44.aarch64 100% | 102.5 MiB/s | 314.8 KiB | 00m00s [ 12/186] unzip-0:6.0-69.fc44.aarch64 100% | 65.4 MiB/s | 200.9 KiB | 00m00s [ 13/186] xz-1:5.8.2-2.fc44.aarch64 100% | 148.1 MiB/s | 606.6 KiB | 00m00s [ 14/186] fedora-release-common-0:44-18 100% | 4.6 MiB/s | 23.6 KiB | 00m00s [ 15/186] coreutils-0:9.10-5.fc44.aarch 100% | 125.0 MiB/s | 1.1 MiB | 00m00s [ 16/186] glibc-minimal-langpack-0:2.43 100% | 16.7 MiB/s | 85.4 KiB | 00m00s [ 17/186] redhat-rpm-config-0:344-2.fc4 100% | 25.4 MiB/s | 78.1 KiB | 00m00s [ 18/186] rpm-build-0:6.0.2-1.fc44.aarc 100% | 63.8 MiB/s | 130.6 KiB | 00m00s [ 19/186] tar-2:1.35-9.fc44.aarch64 100% | 119.4 MiB/s | 855.9 KiB | 00m00s [ 20/186] util-linux-0:2.41.6-1.fc44.aa 100% | 131.8 MiB/s | 1.2 MiB | 00m00s [ 21/186] shadow-utils-2:4.19.0-7.fc44. 100% | 99.3 MiB/s | 1.3 MiB | 00m00s [ 22/186] which-0:2.25-1.fc44.aarch64 100% | 10.1 MiB/s | 41.6 KiB | 00m00s [ 23/186] ncurses-libs-0:6.6-1.fc44.aar 100% | 79.3 MiB/s | 324.8 KiB | 00m00s [ 24/186] filesystem-0:3.18-52.fc44.aar 100% | 166.7 MiB/s | 1.3 MiB | 00m00s [ 25/186] bzip2-libs-0:1.0.8-23.fc44.aa 100% | 6.7 MiB/s | 41.2 KiB | 00m00s [ 26/186] gmp-1:6.3.0-5.fc44.aarch64 100% | 88.2 MiB/s | 271.0 KiB | 00m00s [ 27/186] mpfr-0:4.2.2-3.fc44.aarch64 100% | 104.2 MiB/s | 320.0 KiB | 00m00s [ 28/186] readline-0:8.3-4.fc44.aarch64 100% | 72.0 MiB/s | 221.1 KiB | 00m00s [ 29/186] pcre2-0:10.47-1.fc44.1.aarch6 100% | 81.5 MiB/s | 250.2 KiB | 00m00s [ 30/186] ed-0:1.22.5-2.fc44.aarch64 100% | 27.2 MiB/s | 83.5 KiB | 00m00s [ 31/186] xz-libs-1:5.8.2-2.fc44.aarch6 100% | 36.3 MiB/s | 111.7 KiB | 00m00s [ 32/186] glibc-0:2.43-9.fc44.aarch64 100% | 162.5 MiB/s | 2.0 MiB | 00m00s [ 33/186] coreutils-common-0:9.10-5.fc4 100% | 133.2 MiB/s | 2.1 MiB | 00m00s [ 34/186] glibc-common-0:2.43-9.fc44.aa 100% | 23.5 MiB/s | 360.3 KiB | 00m00s [ 35/186] gnome-srpm-macros-0:1.0-1.fc4 100% | 2.1 MiB/s | 8.7 KiB | 00m00s [ 36/186] ansible-srpm-macros-0:1-20.1. 100% | 4.9 MiB/s | 20.1 KiB | 00m00s [ 37/186] cmake-srpm-macros-0:4.3.0-1.f 100% | 3.4 MiB/s | 10.4 KiB | 00m00s [ 38/186] dwz-0:0.16-3.fc44.aarch64 100% | 32.1 MiB/s | 131.3 KiB | 00m00s [ 39/186] efi-srpm-macros-0:6-6.fc44.no 100% | 7.3 MiB/s | 22.6 KiB | 00m00s [ 40/186] fonts-srpm-macros-1:5.0.0-2.f 100% | 8.9 MiB/s | 27.4 KiB | 00m00s [ 41/186] filesystem-srpm-macros-0:3.18 100% | 6.5 MiB/s | 26.6 KiB | 00m00s [ 42/186] fpc-srpm-macros-0:1.3-16.fc44 100% | 1.9 MiB/s | 7.9 KiB | 00m00s [ 43/186] gap-srpm-macros-0:2-2.fc44.no 100% | 2.2 MiB/s | 9.1 KiB | 00m00s [ 44/186] forge-srpm-macros-0:0.4.0-4.f 100% | 3.3 MiB/s | 20.0 KiB | 00m00s [ 45/186] ghc-srpm-macros-0:1.10-1.fc44 100% | 4.3 MiB/s | 8.8 KiB | 00m00s [ 46/186] gnat-srpm-macros-0:7-2.fc44.n 100% | 4.3 MiB/s | 8.7 KiB | 00m00s [ 47/186] go-srpm-macros-0:3.8.0-2.fc44 100% | 13.8 MiB/s | 28.2 KiB | 00m00s [ 48/186] java-srpm-macros-0:1-8.fc44.n 100% | 4.0 MiB/s | 8.1 KiB | 00m00s [ 49/186] kernel-srpm-macros-0:1.0-28.f 100% | 4.4 MiB/s | 9.0 KiB | 00m00s [ 50/186] lua-srpm-macros-0:1-17.fc44.n 100% | 4.3 MiB/s | 8.9 KiB | 00m00s [ 51/186] ocaml-srpm-macros-0:11-3.fc44 100% | 4.5 MiB/s | 9.3 KiB | 00m00s [ 52/186] openblas-srpm-macros-0:2-21.f 100% | 3.8 MiB/s | 7.8 KiB | 00m00s [ 53/186] perl-srpm-macros-0:1-61.fc44. 100% | 4.1 MiB/s | 8.4 KiB | 00m00s [ 54/186] qt5-srpm-macros-0:5.15.18-2.f 100% | 8.5 MiB/s | 8.7 KiB | 00m00s [ 55/186] python-srpm-macros-0:3.14-12. 100% | 11.7 MiB/s | 24.0 KiB | 00m00s [ 56/186] tree-sitter-srpm-macros-0:0.4 100% | 6.6 MiB/s | 13.5 KiB | 00m00s [ 57/186] zig-srpm-macros-0:1-8.fc44.no 100% | 8.6 MiB/s | 8.8 KiB | 00m00s [ 58/186] rpm-0:6.0.2-1.fc44.aarch64 100% | 187.3 MiB/s | 575.3 KiB | 00m00s [ 59/186] pkgconf-pkg-config-0:2.5.1-1. 100% | 4.6 MiB/s | 9.4 KiB | 00m00s [ 60/186] zip-0:3.0-45.fc44.aarch64 100% | 51.9 MiB/s | 265.6 KiB | 00m00s [ 61/186] zstd-0:1.5.7-5.fc44.aarch64 100% | 89.4 MiB/s | 183.1 KiB | 00m00s [ 62/186] popt-0:1.19-10.fc44.aarch64 100% | 21.2 MiB/s | 65.2 KiB | 00m00s [ 63/186] libeconf-0:0.7.9-3.fc44.aarch 100% | 17.1 MiB/s | 35.0 KiB | 00m00s [ 64/186] libxcrypt-0:4.5.2-3.fc44.aarc 100% | 61.1 MiB/s | 125.1 KiB | 00m00s [ 65/186] libblkid-0:2.41.6-1.fc44.aarc 100% | 39.9 MiB/s | 122.5 KiB | 00m00s [ 66/186] setup-0:2.15.0-28.fc44.noarch 100% | 38.4 MiB/s | 157.2 KiB | 00m00s [ 67/186] libfdisk-0:2.41.6-1.fc44.aarc 100% | 50.5 MiB/s | 155.2 KiB | 00m00s [ 68/186] liblastlog2-0:2.41.6-1.fc44.a 100% | 11.9 MiB/s | 24.4 KiB | 00m00s [ 69/186] libmount-0:2.41.6-1.fc44.aarc 100% | 52.2 MiB/s | 160.2 KiB | 00m00s [ 70/186] libsmartcols-0:2.41.6-1.fc44. 100% | 27.1 MiB/s | 83.1 KiB | 00m00s [ 71/186] libuuid-0:2.41.6-1.fc44.aarch 100% | 12.9 MiB/s | 26.5 KiB | 00m00s [ 72/186] zlib-ng-compat-0:2.3.3-3.fc44 100% | 35.4 MiB/s | 72.4 KiB | 00m00s [ 73/186] util-linux-core-0:2.41.6-1.fc 100% | 132.7 MiB/s | 543.7 KiB | 00m00s [ 74/186] ncurses-base-0:6.6-1.fc44.noa 100% | 28.6 MiB/s | 88.0 KiB | 00m00s [ 75/186] pcre2-syntax-0:10.47-1.fc44.1 100% | 40.2 MiB/s | 164.7 KiB | 00m00s [ 76/186] gnulib-l10n-0:20241231-2.fc44 100% | 48.9 MiB/s | 150.3 KiB | 00m00s [ 77/186] pkgconf-0:2.5.1-1.fc44.aarch6 100% | 9.4 MiB/s | 48.2 KiB | 00m00s [ 78/186] glibc-gconv-extra-0:2.43-9.fc 100% | 156.4 MiB/s | 1.7 MiB | 00m00s [ 79/186] pkgconf-m4-0:2.5.1-1.fc44.noa 100% | 1.7 MiB/s | 13.8 KiB | 00m00s [ 80/186] libzstd-0:1.5.7-5.fc44.aarch6 100% | 80.4 MiB/s | 329.2 KiB | 00m00s [ 81/186] rpm-libs-0:6.0.2-1.fc44.aarch 100% | 183.9 MiB/s | 376.6 KiB | 00m00s [ 82/186] libpkgconf-0:2.5.1-1.fc44.aar 100% | 6.6 MiB/s | 40.7 KiB | 00m00s [ 83/186] rpm-build-libs-0:6.0.2-1.fc44 100% | 37.5 MiB/s | 115.1 KiB | 00m00s [ 84/186] lua-libs-0:5.4.8-5.fc44.aarch 100% | 21.1 MiB/s | 129.4 KiB | 00m00s [ 85/186] rpm-sign-libs-0:6.0.2-1.fc44. 100% | 24.4 MiB/s | 25.0 KiB | 00m00s [ 86/186] ima-evm-utils-libs-0:1.6.2-8. 100% | 14.4 MiB/s | 29.5 KiB | 00m00s [ 87/186] libfsverity-0:1.6-4.fc44.aarc 100% | 9.2 MiB/s | 18.7 KiB | 00m00s [ 88/186] libgcc-0:16.2.1-3.fc44.aarch6 100% | 59.2 MiB/s | 121.3 KiB | 00m00s [ 89/186] libacl-0:2.4.0-1.fc44.aarch64 100% | 25.9 MiB/s | 26.5 KiB | 00m00s [ 90/186] libselinux-0:3.11-2.fc44.aarc 100% | 48.7 MiB/s | 99.7 KiB | 00m00s [ 91/186] libstdc++-0:16.2.1-3.fc44.aar 100% | 180.5 MiB/s | 924.0 KiB | 00m00s [ 92/186] libattr-0:2.6.0-1.fc44.aarch6 100% | 8.6 MiB/s | 17.5 KiB | 00m00s [ 93/186] libsepol-0:3.11-1.fc44.aarch6 100% | 63.7 MiB/s | 325.9 KiB | 00m00s [ 94/186] crypto-policies-0:20251128-3. 100% | 32.0 MiB/s | 98.3 KiB | 00m00s [ 95/186] tpm2-tss-0:4.1.5-1.fc44.aarch 100% | 78.8 MiB/s | 403.3 KiB | 00m00s [ 96/186] json-c-0:0.18-8.fc44.aarch64 100% | 11.0 MiB/s | 44.9 KiB | 00m00s [ 97/186] elfutils-libelf-0:0.197-1.fc4 100% | 64.1 MiB/s | 262.4 KiB | 00m00s [ 98/186] openssl-libs-1:3.5.9-1.fc44.a 100% | 154.7 MiB/s | 2.5 MiB | 00m00s [ 99/186] elfutils-libs-0:0.197-1.fc44. 100% | 32.5 MiB/s | 265.8 KiB | 00m00s [100/186] elfutils-0:0.197-1.fc44.aarch 100% | 84.6 MiB/s | 606.2 KiB | 00m00s [101/186] systemd-libs-0:259.10-1.fc44. 100% | 193.5 MiB/s | 792.4 KiB | 00m00s [102/186] elfutils-debuginfod-client-0: 100% | 9.0 MiB/s | 45.9 KiB | 00m00s [103/186] audit-libs-0:4.2.1-1.fc44.aar 100% | 46.1 MiB/s | 141.8 KiB | 00m00s [104/186] libcap-ng-0:0.9.6-1.fc44.aarc 100% | 17.1 MiB/s | 35.1 KiB | 00m00s [105/186] pam-libs-0:1.7.2-2.fc44.aarch 100% | 27.6 MiB/s | 56.5 KiB | 00m00s [106/186] libusb1-0:1.0.30-1.fc44.aarch 100% | 38.6 MiB/s | 79.0 KiB | 00m00s [107/186] libsemanage-0:3.11-1.fc44.aar 100% | 58.3 MiB/s | 119.3 KiB | 00m00s [108/186] gpgverify-0:2.2-4.fc44.noarch 100% | 5.5 MiB/s | 11.2 KiB | 00m00s [109/186] gnupg2-dirmngr-0:2.4.9-16.fc4 100% | 85.6 MiB/s | 262.9 KiB | 00m00s [110/186] gnupg2-gpg-agent-0:2.4.9-16.f 100% | 64.9 MiB/s | 265.8 KiB | 00m00s [111/186] gnupg2-0:2.4.9-16.fc44.aarch6 100% | 179.0 MiB/s | 1.6 MiB | 00m00s [112/186] gnupg2-gpgconf-0:2.4.9-16.fc4 100% | 27.7 MiB/s | 113.5 KiB | 00m00s [113/186] gnupg2-keyboxd-0:2.4.9-16.fc4 100% | 29.5 MiB/s | 90.6 KiB | 00m00s [114/186] gnupg2-verify-0:2.4.9-16.fc44 100% | 79.5 MiB/s | 162.8 KiB | 00m00s [115/186] libassuan-0:2.5.7-5.fc44.aarc 100% | 32.6 MiB/s | 66.9 KiB | 00m00s [116/186] libgpg-error-0:1.58-2.fc44.aa 100% | 60.6 MiB/s | 248.3 KiB | 00m00s [117/186] npth-0:1.8-4.fc44.aarch64 100% | 12.2 MiB/s | 25.0 KiB | 00m00s [118/186] libksba-0:1.6.7-5.fc44.aarch6 100% | 51.4 MiB/s | 157.8 KiB | 00m00s [119/186] libcap-0:2.78-1.fc44.aarch64 100% | 28.6 MiB/s | 87.8 KiB | 00m00s [120/186] rpm-sequoia-0:1.10.3-1.fc44.a 100% | 144.0 MiB/s | 884.8 KiB | 00m00s [121/186] sqlite-libs-0:3.51.2-2.fc44.a 100% | 104.6 MiB/s | 749.6 KiB | 00m00s [122/186] file-libs-0:5.48-2.fc44.aarch 100% | 122.4 MiB/s | 877.5 KiB | 00m00s [123/186] file-0:5.48-2.fc44.aarch64 100% | 12.2 MiB/s | 50.1 KiB | 00m00s [124/186] libgomp-0:16.2.1-3.fc44.aarch 100% | 125.0 MiB/s | 384.1 KiB | 00m00s [125/186] alternatives-0:1.33-5.fc44.aa 100% | 19.7 MiB/s | 40.4 KiB | 00m00s [126/186] jansson-0:2.14-4.fc44.aarch64 100% | 15.1 MiB/s | 46.5 KiB | 00m00s [127/186] debugedit-0:5.3-2.fc44.aarch6 100% | 28.2 MiB/s | 86.7 KiB | 00m00s [128/186] libxml2-0:2.12.10-6.fc44.aarc 100% | 133.2 MiB/s | 682.0 KiB | 00m00s [129/186] libarchive-0:3.8.7-1.fc44.aar 100% | 58.0 MiB/s | 416.0 KiB | 00m00s [130/186] lz4-libs-0:1.10.0-4.fc44.aarc 100% | 18.7 MiB/s | 76.6 KiB | 00m00s [131/186] curl-0:8.18.0-14.fc44.aarch64 100% | 57.5 MiB/s | 235.4 KiB | 00m00s [132/186] R-srpm-macros-0:1.3.7-2.fc44. 100% | 3.6 MiB/s | 11.0 KiB | 00m00s [133/186] build-reproducibility-srpm-ma 100% | 6.5 MiB/s | 13.3 KiB | 00m00s [134/186] binutils-0:2.46.1-1.fc44.aarc 100% | 229.6 MiB/s | 6.4 MiB | 00m00s [135/186] linkdupes-0:0.7.3-2.fc44.aarc 100% | 35.6 MiB/s | 328.1 KiB | 00m00s [136/186] erlang-srpm-macros-0:0.4.0-1. 100% | 4.9 MiB/s | 10.0 KiB | 00m00s [137/186] package-notes-srpm-macros-0:0 100% | 10.1 MiB/s | 10.4 KiB | 00m00s [138/186] add-determinism-0:0.7.3-2.fc4 100% | 60.1 MiB/s | 800.6 KiB | 00m00s [139/186] pyproject-srpm-macros-0:1.24. 100% | 15.1 MiB/s | 15.4 KiB | 00m00s [140/186] qt6-srpm-macros-0:6.11.2-1.fc 100% | 8.9 MiB/s | 9.1 KiB | 00m00s [141/186] rust-srpm-macros-0:28.5-1.fc4 100% | 10.9 MiB/s | 11.2 KiB | 00m00s [142/186] ca-certificates-0:2026.2.92_v 100% | 319.1 MiB/s | 980.4 KiB | 00m00s [143/186] libffi-0:3.5.2-2.fc44.aarch64 100% | 9.7 MiB/s | 39.6 KiB | 00m00s [144/186] libgcrypt-0:1.12.2-1.fc44.aar 100% | 104.7 MiB/s | 535.9 KiB | 00m00s [145/186] libidn2-0:2.3.8-3.fc44.aarch6 100% | 56.8 MiB/s | 174.6 KiB | 00m00s [146/186] libtasn1-0:4.21.0-1.fc44.aarc 100% | 14.3 MiB/s | 73.4 KiB | 00m00s [147/186] gnutls-0:3.8.13-1.fc44.aarch6 100% | 130.1 MiB/s | 1.3 MiB | 00m00s [148/186] libunistring-0:1.1-11.fc44.aa 100% | 75.1 MiB/s | 538.3 KiB | 00m00s [149/186] nettle-0:3.10.1-3.fc44.aarch6 100% | 83.1 MiB/s | 425.5 KiB | 00m00s [150/186] openldap-0:2.6.16-1.fc44.aarc 100% | 82.3 MiB/s | 252.8 KiB | 00m00s [151/186] cyrus-sasl-lib-0:2.1.28-35.fc 100% | 151.0 MiB/s | 772.9 KiB | 00m00s [152/186] libtool-ltdl-0:2.5.4-10.fc44. 100% | 8.7 MiB/s | 35.6 KiB | 00m00s [153/186] gdbm-libs-1:1.23-11.fc44.aarc 100% | 18.3 MiB/s | 56.3 KiB | 00m00s [154/186] fedora-repos-0:44-2.noarch 100% | 8.9 MiB/s | 9.1 KiB | 00m00s [155/186] elfutils-default-yama-scope-0 100% | 11.2 MiB/s | 11.5 KiB | 00m00s [156/186] fedora-gpg-keys-0:44-2.noarch 100% | 91.6 MiB/s | 187.6 KiB | 00m00s [157/186] libpfm-0:4.14.1-2.fc44.aarch6 100% | 40.5 MiB/s | 82.9 KiB | 00m00s [158/186] p11-kit-0:0.26.5-1.fc44.aarch 100% | 173.9 MiB/s | 534.2 KiB | 00m00s [159/186] p11-kit-trust-0:0.26.5-1.fc44 100% | 34.0 MiB/s | 139.4 KiB | 00m00s [160/186] libevent-0:2.1.13-1.fc44.aarc 100% | 88.7 MiB/s | 272.6 KiB | 00m00s [161/186] fedora-release-0:44-18.noarch 100% | 4.1 MiB/s | 12.5 KiB | 00m00s [162/186] systemd-standalone-sysusers-0 100% | 46.0 MiB/s | 141.3 KiB | 00m00s [163/186] xxhash-libs-0:0.8.4-2.fc44.aa 100% | 11.1 MiB/s | 34.0 KiB | 00m00s [164/186] fedora-release-identity-basic 100% | 3.2 MiB/s | 13.2 KiB | 00m00s [165/186] libcurl-0:8.18.0-14.fc44.aarc 100% | 69.2 MiB/s | 424.9 KiB | 00m00s [166/186] libnghttp3-0:1.18.0-1.fc44.aa 100% | 13.7 MiB/s | 70.1 KiB | 00m00s [167/186] libssh-0:0.12.2-1.fc44.aarch6 100% | 54.1 MiB/s | 277.1 KiB | 00m00s [168/186] ngtcp2-0:1.22.1-1.fc44.aarch6 100% | 28.8 MiB/s | 147.2 KiB | 00m00s [169/186] gdb-minimal-0:18.1-1.fc44.aar 100% | 175.7 MiB/s | 4.4 MiB | 00m00s [170/186] libssh-config-0:0.12.2-1.fc44 100% | 1.2 MiB/s | 8.9 KiB | 00m00s [171/186] libpsl-0:0.21.5-7.fc44.aarch6 100% | 7.9 MiB/s | 64.9 KiB | 00m00s [172/186] libfido2-0:1.16.0-5.fc44.aarc 100% | 47.0 MiB/s | 96.2 KiB | 00m00s [173/186] publicsuffix-list-dafsa-0:202 100% | 29.4 MiB/s | 60.3 KiB | 00m00s [174/186] libcbor-0:0.13.0-2.fc44.aarch 100% | 11.2 MiB/s | 34.4 KiB | 00m00s [175/186] ngtcp2-crypto-ossl-0:1.22.1-1 100% | 5.1 MiB/s | 26.0 KiB | 00m00s [176/186] selinux-policy-0:44.11-1.fc44 100% | 4.4 MiB/s | 27.0 KiB | 00m00s [177/186] rpm-plugin-selinux-0:6.0.2-1. 100% | 3.3 MiB/s | 17.1 KiB | 00m00s [178/186] policycoreutils-0:3.11-2.fc44 100% | 50.9 MiB/s | 260.6 KiB | 00m00s [179/186] libselinux-utils-0:3.11-2.fc4 100% | 17.2 MiB/s | 123.4 KiB | 00m00s [180/186] krb5-libs-0:1.22.2-4.fc44.aar 100% | 92.9 MiB/s | 761.3 KiB | 00m00s [181/186] keyutils-libs-0:1.6.3-7.fc44. 100% | 6.1 MiB/s | 31.5 KiB | 00m00s [182/186] libcom_err-0:1.47.3-4.fc44.aa 100% | 5.3 MiB/s | 27.0 KiB | 00m00s [183/186] libverto-0:0.3.2-12.fc44.aarc 100% | 3.3 MiB/s | 20.5 KiB | 00m00s [184/186] libbrotli-0:1.2.1-1.fc44.aarc 100% | 68.1 MiB/s | 348.6 KiB | 00m00s [185/186] selinux-policy-targeted-0:44. 100% | 161.6 MiB/s | 6.8 MiB | 00m00s [186/186] libnghttp2-0:1.68.0-5.fc44.aa 100% | 6.6 MiB/s | 74.0 KiB | 00m00s -------------------------------------------------------------------------------- [186/186] Total 100% | 191.5 MiB/s | 66.8 MiB | 00m00s Running transaction Importing OpenPGP key 0x6D9F90A6: UserID : "Fedora (44) " Fingerprint: 36F612DCF27F7D1A48A835E4DBFCF71C6D9F90A6 From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-44-primary The key was successfully imported. [ 1/188] Verify package files 100% | 771.0 B/s | 186.0 B | 00m00s [ 2/188] Prepare transaction 100% | 2.5 KiB/s | 186.0 B | 00m00s [ 3/188] Installing libgcc-0:16.2.1-3. 100% | 109.4 MiB/s | 224.0 KiB | 00m00s [ 4/188] Installing publicsuffix-list- 100% | 69.4 MiB/s | 71.1 KiB | 00m00s [ 5/188] Installing libssh-config-0:0. 100% | 0.0 B/s | 816.0 B | 00m00s [ 6/188] Installing fedora-release-ide 100% | 867.2 KiB/s | 888.0 B | 00m00s [ 7/188] Installing fedora-gpg-keys-0: 100% | 31.5 MiB/s | 355.3 KiB | 00m00s [ 8/188] Installing fedora-repos-0:44- 100% | 0.0 B/s | 5.7 KiB | 00m00s [ 9/188] Installing fedora-release-com 100% | 24.3 MiB/s | 24.9 KiB | 00m00s [ 10/188] Installing fedora-release-0:4 100% | 17.3 KiB/s | 124.0 B | 00m00s >>> Running sysusers scriptlet: setup-0:2.15.0-28.fc44.noarch >>> Finished sysusers scriptlet: setup-0:2.15.0-28.fc44.noarch >>> Scriptlet output: >>> Creating group 'adm' with GID 4. >>> Creating group 'audio' with GID 63. >>> Creating group 'cdrom' with GID 11. >>> Creating group 'clock' with GID 103. >>> Creating group 'dialout' with GID 18. >>> Creating group 'disk' with GID 6. >>> Creating group 'floppy' with GID 19. >>> Creating group 'ftp' with GID 50. >>> Creating group 'games' with GID 20. >>> Creating group 'input' with GID 104. >>> Creating group 'kmem' with GID 9. >>> Creating group 'kvm' with GID 36. >>> Creating group 'lock' with GID 54. >>> Creating group 'lp' with GID 7. >>> Creating group 'mail' with GID 12. >>> Creating group 'man' with GID 15. >>> Creating group 'mem' with GID 8. >>> Creating group 'nobody' with GID 65534. >>> Creating group 'render' with GID 105. >>> Creating group 'root' with GID 0. >>> Creating group 'sgx' with GID 106. >>> Creating group 'sys' with GID 3. >>> Creating group 'tape' with GID 33. >>> Creating group 'tty' with GID 5. >>> Creating group 'users' with GID 100. >>> Creating group 'utmp' with GID 22. >>> Creating group 'video' with GID 39. >>> Creating group 'wheel' with GID 10. >>> Creating user 'adm' (adm) with UID 3 and GID 4. >>> Creating group 'bin' with GID 1. >>> Creating user 'bin' (bin) with UID 1 and GID 1. >>> Creating group 'daemon' with GID 2. >>> Creating user 'daemon' (daemon) with UID 2 and GID 2. >>> Creating user 'ftp' (FTP User) with UID 14 and GID 50. >>> Creating user 'games' (games) with UID 12 and GID 100. >>> Creating user 'halt' (halt) with UID 7 and GID 0. >>> Creating user 'lp' (lp) with UID 4 and GID 7. >>> Creating user 'mail' (mail) with UID 8 and GID 12. >>> Creating user 'nobody' (Kernel Overflow User) with UID 65534 and GID 65534. >>> Creating user 'operator' (operator) with UID 11 and GID 0. >>> Creating user 'root' (Super User) with UID 0 and GID 0. >>> Creating user 'shutdown' (shutdown) with UID 6 and GID 0. >>> Creating user 'sync' (sync) with UID 5 and GID 0. >>> [ 11/188] Installing setup-0:2.15.0-28. 100% | 37.5 MiB/s | 730.6 KiB | 00m00s >>> [RPM] /etc/hosts created as /etc/hosts.rpmnew [ 12/188] Installing filesystem-0:3.18- 100% | 2.0 MiB/s | 212.8 KiB | 00m00s [ 13/188] Installing rust-srpm-macros-0 100% | 6.2 MiB/s | 6.4 KiB | 00m00s [ 14/188] Installing qt6-srpm-macros-0: 100% | 0.0 B/s | 748.0 B | 00m00s [ 15/188] Installing package-notes-srpm 100% | 0.0 B/s | 2.1 KiB | 00m00s [ 16/188] Installing pkgconf-m4-0:2.5.1 100% | 14.4 MiB/s | 14.7 KiB | 00m00s [ 17/188] Installing gnulib-l10n-0:2024 100% | 129.3 MiB/s | 661.9 KiB | 00m00s [ 18/188] Installing coreutils-common-0 100% | 314.3 MiB/s | 10.7 MiB | 00m00s [ 19/188] Installing pcre2-syntax-0:10. 100% | 138.8 MiB/s | 284.3 KiB | 00m00s [ 20/188] Installing ncurses-base-0:6.6 100% | 57.8 MiB/s | 355.3 KiB | 00m00s [ 21/188] Installing bash-0:5.3.9-3.fc4 100% | 216.2 MiB/s | 8.4 MiB | 00m00s [ 22/188] Installing glibc-common-0:2.4 100% | 60.2 MiB/s | 1.3 MiB | 00m00s [ 23/188] Installing glibc-gconv-extra- 100% | 396.5 MiB/s | 18.6 MiB | 00m00s [ 24/188] Installing glibc-0:2.43-9.fc4 100% | 148.5 MiB/s | 6.4 MiB | 00m00s [ 25/188] Installing ncurses-libs-0:6.6 100% | 249.2 MiB/s | 1.2 MiB | 00m00s [ 26/188] Installing glibc-minimal-lang 100% | 0.0 B/s | 124.0 B | 00m00s [ 27/188] Installing zlib-ng-compat-0:2 100% | 131.1 MiB/s | 134.2 KiB | 00m00s [ 28/188] Installing bzip2-libs-0:1.0.8 100% | 71.9 MiB/s | 73.6 KiB | 00m00s [ 29/188] Installing libgpg-error-0:1.5 100% | 48.6 MiB/s | 995.5 KiB | 00m00s [ 30/188] Installing libstdc++-0:16.2.1 100% | 330.1 MiB/s | 3.0 MiB | 00m00s [ 31/188] Installing libassuan-0:2.5.7- 100% | 212.6 MiB/s | 217.7 KiB | 00m00s [ 32/188] Installing libgcrypt-0:1.12.2 100% | 240.0 MiB/s | 1.2 MiB | 00m00s [ 33/188] Installing readline-0:8.3-4.f 100% | 276.2 MiB/s | 565.6 KiB | 00m00s [ 34/188] Installing gmp-1:6.3.0-5.fc44 100% | 214.9 MiB/s | 660.1 KiB | 00m00s [ 35/188] Installing xz-libs-1:5.8.2-2. 100% | 260.2 MiB/s | 266.5 KiB | 00m00s [ 36/188] Installing libuuid-0:2.41.6-1 100% | 68.7 MiB/s | 70.3 KiB | 00m00s [ 37/188] Installing libzstd-0:1.5.7-5. 100% | 280.4 MiB/s | 861.5 KiB | 00m00s [ 38/188] Installing elfutils-libelf-0: 100% | 329.6 MiB/s | 1.6 MiB | 00m00s [ 39/188] Installing libacl-0:2.4.0-1.f 100% | 67.1 MiB/s | 68.8 KiB | 00m00s [ 40/188] Installing popt-0:1.19-10.fc4 100% | 49.2 MiB/s | 151.3 KiB | 00m00s [ 41/188] Installing systemd-libs-0:259 100% | 307.7 MiB/s | 2.5 MiB | 00m00s [ 42/188] Installing npth-0:1.8-4.fc44. 100% | 92.2 MiB/s | 94.4 KiB | 00m00s [ 43/188] Installing libblkid-0:2.41.6- 100% | 284.5 MiB/s | 291.3 KiB | 00m00s [ 44/188] Installing libxcrypt-0:4.5.2- 100% | 134.7 MiB/s | 275.9 KiB | 00m00s [ 45/188] Installing libsepol-0:3.11-1. 100% | 264.0 MiB/s | 810.9 KiB | 00m00s [ 46/188] Installing sqlite-libs-0:3.51 100% | 261.2 MiB/s | 1.6 MiB | 00m00s [ 47/188] Installing gnupg2-gpgconf-0:2 100% | 18.6 MiB/s | 323.9 KiB | 00m00s [ 48/188] Installing pcre2-0:10.47-1.fc 100% | 233.0 MiB/s | 715.7 KiB | 00m00s [ 49/188] Installing libselinux-0:3.11- 100% | 130.1 MiB/s | 266.4 KiB | 00m00s [ 50/188] Installing grep-0:3.12-3.fc44 100% | 47.2 MiB/s | 1.0 MiB | 00m00s [ 51/188] Installing sed-0:4.9-7.fc44.a 100% | 41.0 MiB/s | 881.3 KiB | 00m00s [ 52/188] Installing findutils-1:4.10.0 100% | 80.0 MiB/s | 1.9 MiB | 00m00s [ 53/188] Installing json-c-0:0.18-8.fc 100% | 136.5 MiB/s | 139.7 KiB | 00m00s [ 54/188] Installing libtasn1-0:4.21.0- 100% | 217.3 MiB/s | 222.5 KiB | 00m00s [ 55/188] Installing libunistring-0:1.1 100% | 291.0 MiB/s | 1.7 MiB | 00m00s [ 56/188] Installing libidn2-0:2.3.8-3. 100% | 55.3 MiB/s | 566.6 KiB | 00m00s [ 57/188] Installing crypto-policies-0: 100% | 22.0 MiB/s | 157.7 KiB | 00m00s [ 58/188] Installing xz-1:5.8.2-2.fc44. 100% | 57.9 MiB/s | 1.4 MiB | 00m00s [ 59/188] Installing libmount-0:2.41.6- 100% | 205.7 MiB/s | 421.3 KiB | 00m00s [ 60/188] Installing gnupg2-verify-0:2. 100% | 21.0 MiB/s | 365.7 KiB | 00m00s [ 61/188] Installing dwz-0:0.16-3.fc44. 100% | 18.6 MiB/s | 323.8 KiB | 00m00s [ 62/188] Installing mpfr-0:4.2.2-3.fc4 100% | 184.8 MiB/s | 757.1 KiB | 00m00s [ 63/188] Installing gawk-0:5.3.2-3.fc4 100% | 107.5 MiB/s | 2.6 MiB | 00m00s [ 64/188] Installing libksba-0:1.6.7-5. 100% | 195.7 MiB/s | 400.8 KiB | 00m00s [ 65/188] Installing unzip-0:6.0-69.fc4 100% | 29.2 MiB/s | 537.3 KiB | 00m00s [ 66/188] Installing file-libs-0:5.48-2 100% | 618.0 MiB/s | 12.4 MiB | 00m00s [ 67/188] Installing file-0:5.48-2.fc44 100% | 8.2 MiB/s | 143.4 KiB | 00m00s [ 68/188] Installing diffutils-0:3.12-5 100% | 70.6 MiB/s | 1.6 MiB | 00m00s [ 69/188] Installing libeconf-0:0.7.9-3 100% | 80.5 MiB/s | 82.5 KiB | 00m00s [ 70/188] Installing libsmartcols-0:2.4 100% | 220.1 MiB/s | 225.4 KiB | 00m00s [ 71/188] Installing lua-libs-0:5.4.8-5 100% | 161.7 MiB/s | 331.3 KiB | 00m00s [ 72/188] Installing libattr-0:2.6.0-1. 100% | 67.7 MiB/s | 69.3 KiB | 00m00s [ 73/188] Installing libcap-ng-0:0.9.6- 100% | 159.0 MiB/s | 162.8 KiB | 00m00s [ 74/188] Installing audit-libs-0:4.2.1 100% | 238.9 MiB/s | 489.3 KiB | 00m00s [ 75/188] Installing pam-libs-0:1.7.2-2 100% | 219.7 MiB/s | 225.0 KiB | 00m00s [ 76/188] Installing libcap-0:2.78-1.fc 100% | 27.9 MiB/s | 513.5 KiB | 00m00s [ 77/188] Installing libsemanage-0:3.11 100% | 176.7 MiB/s | 361.8 KiB | 00m00s [ 78/188] Installing alternatives-0:1.3 100% | 5.3 MiB/s | 91.6 KiB | 00m00s [ 79/188] Installing libffi-0:3.5.2-2.f 100% | 153.4 MiB/s | 157.1 KiB | 00m00s [ 80/188] Installing p11-kit-0:0.26.5-1 100% | 100.0 MiB/s | 2.8 MiB | 00m00s [ 81/188] Installing p11-kit-trust-0:0. 100% | 21.6 MiB/s | 531.9 KiB | 00m00s [ 82/188] Installing ngtcp2-0:1.22.1-1. 100% | 167.3 MiB/s | 342.7 KiB | 00m00s [ 83/188] Installing openssl-libs-1:3.5 100% | 325.4 MiB/s | 7.5 MiB | 00m00s [ 84/188] Installing coreutils-0:9.10-5 100% | 182.7 MiB/s | 8.2 MiB | 00m00s [ 85/188] Installing ca-certificates-0: 100% | 1.5 MiB/s | 2.5 MiB | 00m02s [ 86/188] Installing gzip-0:1.14-2.fc44 100% | 22.8 MiB/s | 443.0 KiB | 00m00s [ 87/188] Installing libfsverity-0:1.6- 100% | 67.7 MiB/s | 69.3 KiB | 00m00s [ 88/188] Installing rpm-sequoia-0:1.10 100% | 286.5 MiB/s | 2.3 MiB | 00m00s [ 89/188] Installing libevent-0:2.1.13- 100% | 271.7 MiB/s | 1.1 MiB | 00m00s [ 90/188] Installing ngtcp2-crypto-ossl 100% | 66.7 MiB/s | 68.3 KiB | 00m00s [ 91/188] Installing liblastlog2-0:2.41 100% | 22.8 MiB/s | 139.8 KiB | 00m00s [ 92/188] Installing util-linux-core-0: 100% | 94.8 MiB/s | 2.5 MiB | 00m00s [ 93/188] Installing zip-0:3.0-45.fc44. 100% | 39.4 MiB/s | 765.8 KiB | 00m00s [ 94/188] Installing gnupg2-keyboxd-0:2 100% | 38.2 MiB/s | 234.5 KiB | 00m00s [ 95/188] Installing libpsl-0:0.21.5-7. 100% | 130.3 MiB/s | 133.4 KiB | 00m00s [ 96/188] Installing tar-2:1.35-9.fc44. 100% | 111.3 MiB/s | 3.0 MiB | 00m00s [ 97/188] Installing linkdupes-0:0.7.3- 100% | 36.8 MiB/s | 715.1 KiB | 00m00s [ 98/188] Installing libselinux-utils-0 100% | 64.6 MiB/s | 1.4 MiB | 00m00s [ 99/188] Installing systemd-standalone 100% | 19.0 MiB/s | 330.2 KiB | 00m00s [100/188] Installing rpm-libs-0:6.0.2-1 100% | 243.3 MiB/s | 996.7 KiB | 00m00s [101/188] Installing libfdisk-0:2.41.6- 100% | 136.7 MiB/s | 419.9 KiB | 00m00s [102/188] Installing util-linux-0:2.41. 100% | 145.9 MiB/s | 6.9 MiB | 00m00s [103/188] Installing policycoreutils-0: 100% | 45.0 MiB/s | 1.5 MiB | 00m00s [104/188] Installing selinux-policy-0:4 100% | 1.5 MiB/s | 34.5 KiB | 00m00s [105/188] Installing selinux-policy-tar 100% | 142.0 MiB/s | 14.9 MiB | 00m00s [106/188] Installing libusb1-0:1.0.30-1 100% | 19.7 MiB/s | 181.4 KiB | 00m00s >>> Running sysusers scriptlet: tpm2-tss-0:4.1.5-1.fc44.aarch64 >>> Finished sysusers scriptlet: tpm2-tss-0:4.1.5-1.fc44.aarch64 >>> Scriptlet output: >>> Creating group 'tss' with GID 59. >>> Creating user 'tss' (Account used for TPM access) with UID 59 and GID 59. >>> [107/188] Installing tpm2-tss-0:4.1.5-1 100% | 270.0 MiB/s | 2.2 MiB | 00m00s [108/188] Installing ima-evm-utils-libs 100% | 91.7 MiB/s | 93.9 KiB | 00m00s [109/188] Installing gnupg2-gpg-agent-0 100% | 32.0 MiB/s | 850.9 KiB | 00m00s [110/188] Installing zstd-0:1.5.7-5.fc4 100% | 29.1 MiB/s | 565.8 KiB | 00m00s [111/188] Installing libxml2-0:2.12.10- 100% | 82.2 MiB/s | 1.9 MiB | 00m00s [112/188] Installing nettle-0:3.10.1-3. 100% | 250.1 MiB/s | 768.2 KiB | 00m00s [113/188] Installing gnutls-0:3.8.13-1. 100% | 309.1 MiB/s | 3.7 MiB | 00m00s [114/188] Installing bzip2-0:1.0.8-23.f 100% | 10.1 MiB/s | 175.6 KiB | 00m00s [115/188] Installing add-determinism-0: 100% | 89.6 MiB/s | 2.0 MiB | 00m00s [116/188] Installing build-reproducibil 100% | 1.5 MiB/s | 1.5 KiB | 00m00s [117/188] Installing cpio-0:2.15-9.fc44 100% | 52.2 MiB/s | 1.1 MiB | 00m00s [118/188] Installing ed-0:1.22.5-2.fc44 100% | 9.2 MiB/s | 160.1 KiB | 00m00s [119/188] Installing patch-0:2.8-4.fc44 100% | 15.2 MiB/s | 263.9 KiB | 00m00s [120/188] Installing libpkgconf-0:2.5.1 100% | 132.0 MiB/s | 135.2 KiB | 00m00s [121/188] Installing pkgconf-0:2.5.1-1. 100% | 6.9 MiB/s | 119.3 KiB | 00m00s [122/188] Installing pkgconf-pkg-config 100% | 110.8 KiB/s | 1.8 KiB | 00m00s [123/188] Installing libgomp-0:16.2.1-3 100% | 290.2 MiB/s | 594.3 KiB | 00m00s [124/188] Installing jansson-0:2.14-4.f 100% | 92.2 MiB/s | 94.4 KiB | 00m00s [125/188] Installing lz4-libs-0:1.10.0- 100% | 193.7 MiB/s | 198.4 KiB | 00m00s [126/188] Installing libarchive-0:3.8.7 100% | 238.7 MiB/s | 977.5 KiB | 00m00s [127/188] Installing libtool-ltdl-0:2.5 100% | 92.8 MiB/s | 95.0 KiB | 00m00s [128/188] Installing gdbm-libs-1:1.23-1 100% | 229.9 MiB/s | 235.4 KiB | 00m00s [129/188] Installing cyrus-sasl-lib-0:2 100% | 100.7 MiB/s | 2.4 MiB | 00m00s [130/188] Installing openldap-0:2.6.16- 100% | 188.0 MiB/s | 769.9 KiB | 00m00s [131/188] Installing gnupg2-dirmngr-0:2 100% | 26.4 MiB/s | 648.9 KiB | 00m00s [132/188] Installing gnupg2-0:2.4.9-16. 100% | 174.5 MiB/s | 6.5 MiB | 00m00s [133/188] Installing rpm-sign-libs-0:6. 100% | 66.9 MiB/s | 68.5 KiB | 00m00s [134/188] Installing gpgverify-0:2.2-4. 100% | 9.2 MiB/s | 9.4 KiB | 00m00s [135/188] Installing libpfm-0:4.14.1-2. 100% | 251.3 MiB/s | 514.6 KiB | 00m00s [136/188] Installing xxhash-libs-0:0.8. 100% | 85.1 MiB/s | 87.2 KiB | 00m00s [137/188] Installing libnghttp3-0:1.18. 100% | 203.3 MiB/s | 208.2 KiB | 00m00s [138/188] Installing libcbor-0:0.13.0-2 100% | 137.6 MiB/s | 140.9 KiB | 00m00s [139/188] Installing libfido2-0:1.16.0- 100% | 136.8 MiB/s | 280.1 KiB | 00m00s [140/188] Installing keyutils-libs-0:1. 100% | 97.3 MiB/s | 99.6 KiB | 00m00s [141/188] Installing libcom_err-0:1.47. 100% | 109.5 MiB/s | 112.1 KiB | 00m00s [142/188] Installing libverto-0:0.3.2-1 100% | 69.4 MiB/s | 71.1 KiB | 00m00s [143/188] Installing krb5-libs-0:1.22.2 100% | 253.4 MiB/s | 2.5 MiB | 00m00s [144/188] Installing libssh-0:0.12.2-1. 100% | 235.5 MiB/s | 723.4 KiB | 00m00s [145/188] Installing libbrotli-0:1.2.1- 100% | 222.5 MiB/s | 911.5 KiB | 00m00s [146/188] Installing libnghttp2-0:1.68. 100% | 194.4 MiB/s | 199.1 KiB | 00m00s [147/188] Installing libcurl-0:8.18.0-1 100% | 239.8 MiB/s | 982.0 KiB | 00m00s [148/188] Installing curl-0:8.18.0-14.f 100% | 16.9 MiB/s | 466.8 KiB | 00m00s [149/188] Installing rpm-0:6.0.2-1.fc44 100% | 68.1 MiB/s | 2.8 MiB | 00m00s [150/188] Installing cmake-srpm-macros- 100% | 785.2 KiB/s | 804.0 B | 00m00s [151/188] Installing efi-srpm-macros-0: 100% | 40.2 MiB/s | 41.2 KiB | 00m00s [152/188] Installing java-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [153/188] Installing lua-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [154/188] Installing tree-sitter-srpm-m 100% | 9.1 MiB/s | 9.3 KiB | 00m00s [155/188] Installing zig-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [156/188] Installing filesystem-srpm-ma 100% | 38.0 MiB/s | 38.9 KiB | 00m00s [157/188] Installing elfutils-default-y 100% | 408.6 KiB/s | 2.0 KiB | 00m00s [158/188] Installing elfutils-libs-0:0. 100% | 182.7 MiB/s | 748.5 KiB | 00m00s [159/188] Installing elfutils-debuginfo 100% | 7.9 MiB/s | 146.1 KiB | 00m00s [160/188] Installing elfutils-0:0.197-1 100% | 135.5 MiB/s | 3.7 MiB | 00m00s [161/188] Installing binutils-0:2.46.1- 100% | 300.0 MiB/s | 31.5 MiB | 00m00s [162/188] Installing gdb-minimal-0:18.1 100% | 241.9 MiB/s | 13.8 MiB | 00m00s [163/188] Installing debugedit-0:5.3-2. 100% | 17.6 MiB/s | 324.2 KiB | 00m00s [164/188] Installing rpm-build-libs-0:6 100% | 129.4 MiB/s | 264.9 KiB | 00m00s [165/188] Installing qt5-srpm-macros-0: 100% | 0.0 B/s | 776.0 B | 00m00s [166/188] Installing perl-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [167/188] Installing openblas-srpm-macr 100% | 0.0 B/s | 392.0 B | 00m00s [168/188] Installing ocaml-srpm-macros- 100% | 0.0 B/s | 2.1 KiB | 00m00s [169/188] Installing kernel-srpm-macros 100% | 0.0 B/s | 2.3 KiB | 00m00s [170/188] Installing gnat-srpm-macros-0 100% | 0.0 B/s | 1.3 KiB | 00m00s [171/188] Installing ghc-srpm-macros-0: 100% | 0.0 B/s | 1.0 KiB | 00m00s [172/188] Installing gap-srpm-macros-0: 100% | 0.0 B/s | 2.7 KiB | 00m00s [173/188] Installing fpc-srpm-macros-0: 100% | 0.0 B/s | 420.0 B | 00m00s [174/188] Installing ansible-srpm-macro 100% | 0.0 B/s | 36.2 KiB | 00m00s [175/188] Installing gnome-srpm-macros- 100% | 4.0 MiB/s | 4.1 KiB | 00m00s [176/188] Installing redhat-rpm-config- 100% | 92.7 MiB/s | 189.9 KiB | 00m00s [177/188] Installing forge-srpm-macros- 100% | 39.3 MiB/s | 40.3 KiB | 00m00s [178/188] Installing rpm-build-0:6.0.2- 100% | 29.7 MiB/s | 607.8 KiB | 00m00s [179/188] Installing erlang-srpm-macros 100% | 2.5 MiB/s | 2.6 KiB | 00m00s [180/188] Installing pyproject-srpm-mac 100% | 665.4 KiB/s | 4.0 KiB | 00m00s [181/188] Installing fonts-srpm-macros- 100% | 55.7 MiB/s | 57.0 KiB | 00m00s [182/188] Installing go-srpm-macros-0:3 100% | 61.6 MiB/s | 63.0 KiB | 00m00s [183/188] Installing python-srpm-macros 100% | 51.7 MiB/s | 52.9 KiB | 00m00s [184/188] Installing R-srpm-macros-0:1. 100% | 4.3 MiB/s | 4.4 KiB | 00m00s [185/188] Installing rpm-plugin-selinux 100% | 67.3 MiB/s | 68.9 KiB | 00m00s [186/188] Installing which-0:2.25-1.fc4 100% | 6.5 MiB/s | 125.8 KiB | 00m00s [187/188] Installing shadow-utils-2:4.1 100% | 109.6 MiB/s | 4.5 MiB | 00m00s [188/188] Installing info-0:7.2-9.fc44. 100% | 50.4 KiB/s | 421.9 KiB | 00m08s Complete! Finish: installing minimal buildroot with dnf5 Start: creating root cache Finish: creating root cache Finish: chroot init INFO: Installed packages: INFO: R-srpm-macros-1.3.7-2.fc44.noarch add-determinism-0.7.3-2.fc44.aarch64 alternatives-1.33-5.fc44.aarch64 ansible-srpm-macros-1-20.1.fc44.noarch audit-libs-4.2.1-1.fc44.aarch64 bash-5.3.9-3.fc44.aarch64 binutils-2.46.1-1.fc44.aarch64 build-reproducibility-srpm-macros-0.7.3-2.fc44.noarch bzip2-1.0.8-23.fc44.aarch64 bzip2-libs-1.0.8-23.fc44.aarch64 ca-certificates-2026.2.92_v9.0.319-2.fc44.noarch cmake-srpm-macros-4.3.0-1.fc44.noarch coreutils-9.10-5.fc44.aarch64 coreutils-common-9.10-5.fc44.aarch64 cpio-2.15-9.fc44.aarch64 crypto-policies-20251128-3.git19878fe.fc44.noarch curl-8.18.0-14.fc44.aarch64 cyrus-sasl-lib-2.1.28-35.fc44.aarch64 debugedit-5.3-2.fc44.aarch64 diffutils-3.12-5.fc44.aarch64 dwz-0.16-3.fc44.aarch64 ed-1.22.5-2.fc44.aarch64 efi-srpm-macros-6-6.fc44.noarch elfutils-0.197-1.fc44.aarch64 elfutils-debuginfod-client-0.197-1.fc44.aarch64 elfutils-default-yama-scope-0.197-1.fc44.noarch elfutils-libelf-0.197-1.fc44.aarch64 elfutils-libs-0.197-1.fc44.aarch64 erlang-srpm-macros-0.4.0-1.fc44.noarch fedora-gpg-keys-44-2.noarch fedora-release-44-18.noarch fedora-release-common-44-18.noarch fedora-release-identity-basic-44-18.noarch fedora-repos-44-2.noarch file-5.48-2.fc44.aarch64 file-libs-5.48-2.fc44.aarch64 filesystem-3.18-52.fc44.aarch64 filesystem-srpm-macros-3.18-52.fc44.noarch findutils-4.10.0-7.fc44.aarch64 fonts-srpm-macros-5.0.0-2.fc44.noarch forge-srpm-macros-0.4.0-4.fc44.noarch fpc-srpm-macros-1.3-16.fc44.noarch gap-srpm-macros-2-2.fc44.noarch gawk-5.3.2-3.fc44.aarch64 gdb-minimal-18.1-1.fc44.aarch64 gdbm-libs-1.23-11.fc44.aarch64 ghc-srpm-macros-1.10-1.fc44.noarch glibc-2.43-9.fc44.aarch64 glibc-common-2.43-9.fc44.aarch64 glibc-gconv-extra-2.43-9.fc44.aarch64 glibc-minimal-langpack-2.43-9.fc44.aarch64 gmp-6.3.0-5.fc44.aarch64 gnat-srpm-macros-7-2.fc44.noarch gnome-srpm-macros-1.0-1.fc44.noarch gnulib-l10n-20241231-2.fc44.noarch gnupg2-2.4.9-16.fc44.aarch64 gnupg2-dirmngr-2.4.9-16.fc44.aarch64 gnupg2-gpg-agent-2.4.9-16.fc44.aarch64 gnupg2-gpgconf-2.4.9-16.fc44.aarch64 gnupg2-keyboxd-2.4.9-16.fc44.aarch64 gnupg2-verify-2.4.9-16.fc44.aarch64 gnutls-3.8.13-1.fc44.aarch64 go-srpm-macros-3.8.0-2.fc44.noarch gpg-pubkey-36f612dcf27f7d1a48a835e4dbfcf71c6d9f90a6-6786af3b gpgverify-2.2-4.fc44.noarch grep-3.12-3.fc44.aarch64 gzip-1.14-2.fc44.aarch64 ima-evm-utils-libs-1.6.2-8.fc44.aarch64 info-7.2-9.fc44.aarch64 jansson-2.14-4.fc44.aarch64 java-srpm-macros-1-8.fc44.noarch json-c-0.18-8.fc44.aarch64 kernel-srpm-macros-1.0-28.fc44.noarch keyutils-libs-1.6.3-7.fc44.aarch64 krb5-libs-1.22.2-4.fc44.aarch64 libacl-2.4.0-1.fc44.aarch64 libarchive-3.8.7-1.fc44.aarch64 libassuan-2.5.7-5.fc44.aarch64 libattr-2.6.0-1.fc44.aarch64 libblkid-2.41.6-1.fc44.aarch64 libbrotli-1.2.1-1.fc44.aarch64 libcap-2.78-1.fc44.aarch64 libcap-ng-0.9.6-1.fc44.aarch64 libcbor-0.13.0-2.fc44.aarch64 libcom_err-1.47.3-4.fc44.aarch64 libcurl-8.18.0-14.fc44.aarch64 libeconf-0.7.9-3.fc44.aarch64 libevent-2.1.13-1.fc44.aarch64 libfdisk-2.41.6-1.fc44.aarch64 libffi-3.5.2-2.fc44.aarch64 libfido2-1.16.0-5.fc44.aarch64 libfsverity-1.6-4.fc44.aarch64 libgcc-16.2.1-3.fc44.aarch64 libgcrypt-1.12.2-1.fc44.aarch64 libgomp-16.2.1-3.fc44.aarch64 libgpg-error-1.58-2.fc44.aarch64 libidn2-2.3.8-3.fc44.aarch64 libksba-1.6.7-5.fc44.aarch64 liblastlog2-2.41.6-1.fc44.aarch64 libmount-2.41.6-1.fc44.aarch64 libnghttp2-1.68.0-5.fc44.aarch64 libnghttp3-1.18.0-1.fc44.aarch64 libpfm-4.14.1-2.fc44.aarch64 libpkgconf-2.5.1-1.fc44.aarch64 libpsl-0.21.5-7.fc44.aarch64 libselinux-3.11-2.fc44.aarch64 libselinux-utils-3.11-2.fc44.aarch64 libsemanage-3.11-1.fc44.aarch64 libsepol-3.11-1.fc44.aarch64 libsmartcols-2.41.6-1.fc44.aarch64 libssh-0.12.2-1.fc44.aarch64 libssh-config-0.12.2-1.fc44.noarch libstdc++-16.2.1-3.fc44.aarch64 libtasn1-4.21.0-1.fc44.aarch64 libtool-ltdl-2.5.4-10.fc44.aarch64 libunistring-1.1-11.fc44.aarch64 libusb1-1.0.30-1.fc44.aarch64 libuuid-2.41.6-1.fc44.aarch64 libverto-0.3.2-12.fc44.aarch64 libxcrypt-4.5.2-3.fc44.aarch64 libxml2-2.12.10-6.fc44.aarch64 libzstd-1.5.7-5.fc44.aarch64 linkdupes-0.7.3-2.fc44.aarch64 lua-libs-5.4.8-5.fc44.aarch64 lua-srpm-macros-1-17.fc44.noarch lz4-libs-1.10.0-4.fc44.aarch64 mpfr-4.2.2-3.fc44.aarch64 ncurses-base-6.6-1.fc44.noarch ncurses-libs-6.6-1.fc44.aarch64 nettle-3.10.1-3.fc44.aarch64 ngtcp2-1.22.1-1.fc44.aarch64 ngtcp2-crypto-ossl-1.22.1-1.fc44.aarch64 npth-1.8-4.fc44.aarch64 ocaml-srpm-macros-11-3.fc44.noarch openblas-srpm-macros-2-21.fc44.noarch openldap-2.6.16-1.fc44.aarch64 openssl-libs-3.5.9-1.fc44.aarch64 p11-kit-0.26.5-1.fc44.aarch64 p11-kit-trust-0.26.5-1.fc44.aarch64 package-notes-srpm-macros-0.20-1.fc44.noarch pam-libs-1.7.2-2.fc44.aarch64 patch-2.8-4.fc44.aarch64 pcre2-10.47-1.fc44.1.aarch64 pcre2-syntax-10.47-1.fc44.1.noarch perl-srpm-macros-1-61.fc44.noarch pkgconf-2.5.1-1.fc44.aarch64 pkgconf-m4-2.5.1-1.fc44.noarch pkgconf-pkg-config-2.5.1-1.fc44.aarch64 policycoreutils-3.11-2.fc44.aarch64 popt-1.19-10.fc44.aarch64 publicsuffix-list-dafsa-20260116-1.fc44.noarch pyproject-srpm-macros-1.24.0-1.fc44.noarch python-srpm-macros-3.14-12.fc44.noarch qt5-srpm-macros-5.15.18-2.fc44.noarch qt6-srpm-macros-6.11.2-1.fc44.noarch readline-8.3-4.fc44.aarch64 redhat-rpm-config-344-2.fc44.noarch rpm-6.0.2-1.fc44.aarch64 rpm-build-6.0.2-1.fc44.aarch64 rpm-build-libs-6.0.2-1.fc44.aarch64 rpm-libs-6.0.2-1.fc44.aarch64 rpm-plugin-selinux-6.0.2-1.fc44.aarch64 rpm-sequoia-1.10.3-1.fc44.aarch64 rpm-sign-libs-6.0.2-1.fc44.aarch64 rust-srpm-macros-28.5-1.fc44.noarch sed-4.9-7.fc44.aarch64 selinux-policy-44.11-1.fc44.noarch selinux-policy-targeted-44.11-1.fc44.noarch setup-2.15.0-28.fc44.noarch shadow-utils-4.19.0-7.fc44.aarch64 sqlite-libs-3.51.2-2.fc44.aarch64 systemd-libs-259.10-1.fc44.aarch64 systemd-standalone-sysusers-259.10-1.fc44.aarch64 tar-1.35-9.fc44.aarch64 tpm2-tss-4.1.5-1.fc44.aarch64 tree-sitter-srpm-macros-0.4.2-2.fc44.noarch unzip-6.0-69.fc44.aarch64 util-linux-2.41.6-1.fc44.aarch64 util-linux-core-2.41.6-1.fc44.aarch64 which-2.25-1.fc44.aarch64 xxhash-libs-0.8.4-2.fc44.aarch64 xz-5.8.2-2.fc44.aarch64 xz-libs-5.8.2-2.fc44.aarch64 zig-srpm-macros-1-8.fc44.noarch zip-3.0-45.fc44.aarch64 zlib-ng-compat-2.3.3-3.fc44.aarch64 zstd-1.5.7-5.fc44.aarch64 Start: buildsrpm Start: rpmbuild -bs Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.src.rpm Finish: rpmbuild -bs INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-44-aarch64-1794040424.031981/root/var/log/dnf5.log INFO: chroot_scan: creating tarball /var/lib/copr-rpmbuild/results/chroot_scan.tar.gz /bin/tar: Removing leading `/' from member names Finish: buildsrpm INFO: Done(/var/lib/copr-rpmbuild/workspace/workdir-wcmlgyjl/python-pyradplan/python-pyradplan.spec) Config(child) 0 minutes 30 seconds INFO: Results and/or logs in: /var/lib/copr-rpmbuild/results INFO: Cleaning up build root ('cleanup_on_success=True') Start: clean chroot INFO: unmounting tmpfs. Finish: clean chroot INFO: Start(/var/lib/copr-rpmbuild/results/python-pyradplan-0.8.0-1.fc44.src.rpm) Config(fedora-44-aarch64) Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-44-aarch64-bootstrap-1794040424.031981/root. INFO: reusing tmpfs at /var/lib/mock/fedora-44-aarch64-bootstrap-1794040424.031981/root. INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start(bootstrap): cleaning package manager metadata Finish(bootstrap): cleaning package manager metadata Finish(bootstrap): chroot init Start: chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-44-aarch64-1794040424.031981/root. INFO: calling preinit hooks INFO: enabled root cache Start: unpacking root cache Finish: unpacking root cache INFO: enabled package manager cache Start: cleaning package manager metadata Finish: cleaning package manager metadata INFO: enabled HW Info plugin INFO: Buildroot is handled by package management downloaded with a bootstrap image: rpm-6.0.2-1.fc44.aarch64 rpm-sequoia-1.10.3-1.fc44.aarch64 dnf5-5.4.6.0-1.fc44.aarch64 dnf5-plugins-5.4.6.0-1.fc44.aarch64 Finish: chroot init Start: build phase for python-pyradplan-0.8.0-1.fc44.src.rpm Start: build setup for python-pyradplan-0.8.0-1.fc44.src.rpm Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.src.rpm Updating and loading repositories: updates 100% | 7.5 KiB/s | 5.3 KiB | 00m01s fedora 100% | 13.2 KiB/s | 9.3 KiB | 00m01s Copr repository 100% | 3.2 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package Arch Version Repository Size Installing: pyproject-rpm-macros noarch 0:1.24.0-1.fc44 updates 169.0 KiB python3-devel aarch64 0:3.14.10-1.fc44 updates 2.0 MiB python3-pytest noarch 0:8.4.2-2.fc44 fedora 22.5 MiB Installing dependencies: expat aarch64 0:2.9.0-1.fc44 updates 389.5 KiB mpdecimal aarch64 0:4.0.1-3.fc44 fedora 281.1 KiB python-pip-wheel noarch 0:26.0.1-3.fc44 updates 1.2 MiB python-rpm-macros noarch 0:3.14-12.fc44 fedora 28.0 KiB python3 aarch64 0:3.14.10-1.fc44 updates 84.7 KiB python3-iniconfig noarch 0:2.3.0-2.fc44 fedora 49.8 KiB python3-libs aarch64 0:3.14.10-1.fc44 updates 45.8 MiB python3-packaging noarch 0:25.0-8.fc44 fedora 607.4 KiB python3-pluggy noarch 0:1.6.0-5.fc44 fedora 211.5 KiB python3-pygments noarch 0:2.19.1-9.fc44 fedora 11.3 MiB python3-rpm-generators noarch 0:14-14.fc44 fedora 81.7 KiB python3-rpm-macros noarch 0:3.14-12.fc44 fedora 6.5 KiB tzdata noarch 0:2026f-1.fc44 updates 1.3 MiB Transaction Summary: Installing: 16 packages Total size of inbound packages is 18 MiB. Need to download 18 MiB. After this operation, 86 MiB extra will be used (install 86 MiB, remove 0 B). [ 1/16] pyproject-rpm-macros-0:1.24.0-1 100% | 4.4 MiB/s | 58.1 KiB | 00m00s [ 2/16] python3-iniconfig-0:2.3.0-2.fc4 100% | 8.6 MiB/s | 26.3 KiB | 00m00s [ 3/16] python3-packaging-0:25.0-8.fc44 100% | 22.5 MiB/s | 161.2 KiB | 00m00s [ 4/16] python3-pytest-0:8.4.2-2.fc44.n 100% | 74.7 MiB/s | 2.3 MiB | 00m00s [ 5/16] python3-pluggy-0:1.6.0-5.fc44.n 100% | 10.0 MiB/s | 61.6 KiB | 00m00s [ 6/16] python-rpm-macros-0:3.14-12.fc4 100% | 9.7 MiB/s | 20.0 KiB | 00m00s [ 7/16] python3-rpm-macros-0:3.14-12.fc 100% | 6.1 MiB/s | 12.4 KiB | 00m00s [ 8/16] python3-0:3.14.10-1.fc44.aarch6 100% | 9.7 MiB/s | 29.8 KiB | 00m00s [ 9/16] python3-libs-0:3.14.10-1.fc44.a 100% | 261.2 MiB/s | 9.9 MiB | 00m00s [10/16] expat-0:2.9.0-1.fc44.aarch64 100% | 64.0 MiB/s | 131.1 KiB | 00m00s [11/16] mpdecimal-0:4.0.1-3.fc44.aarch6 100% | 46.6 MiB/s | 95.4 KiB | 00m00s [12/16] python-pip-wheel-0:26.0.1-3.fc4 100% | 191.6 MiB/s | 1.1 MiB | 00m00s [13/16] tzdata-0:2026f-1.fc44.noarch 100% | 174.2 MiB/s | 713.6 KiB | 00m00s [14/16] python3-rpm-generators-0:14-14. 100% | 9.3 MiB/s | 28.6 KiB | 00m00s [15/16] python3-pygments-0:2.19.1-9.fc4 100% | 28.4 MiB/s | 2.7 MiB | 00m00s [16/16] python3-devel-0:3.14.10-1.fc44. 100% | 3.2 MiB/s | 448.1 KiB | 00m00s -------------------------------------------------------------------------------- [16/16] Total 100% | 130.0 MiB/s | 17.8 MiB | 00m00s Running transaction [ 1/18] Verify package files 100% | 280.0 B/s | 16.0 B | 00m00s [ 2/18] Prepare transaction 100% | 313.0 B/s | 16.0 B | 00m00s [ 3/18] Installing python-rpm-macros-0: 100% | 28.2 MiB/s | 28.9 KiB | 00m00s [ 4/18] Installing python3-rpm-macros-0 100% | 6.6 MiB/s | 6.8 KiB | 00m00s [ 5/18] Installing pyproject-rpm-macros 100% | 27.9 MiB/s | 171.5 KiB | 00m00s [ 6/18] Installing tzdata-0:2026f-1.fc4 100% | 31.1 MiB/s | 1.5 MiB | 00m00s [ 7/18] Installing python-pip-wheel-0:2 100% | 407.8 MiB/s | 1.2 MiB | 00m00s [ 8/18] Installing mpdecimal-0:4.0.1-3. 100% | 138.0 MiB/s | 282.6 KiB | 00m00s [ 9/18] Installing expat-0:2.9.0-1.fc44 100% | 15.9 MiB/s | 391.6 KiB | 00m00s [10/18] Installing python3-libs-0:3.14. 100% | 266.8 MiB/s | 46.2 MiB | 00m00s [11/18] Installing python3-0:3.14.10-1. 100% | 5.0 MiB/s | 86.5 KiB | 00m00s [12/18] Installing python3-packaging-0: 100% | 151.3 MiB/s | 619.9 KiB | 00m00s [13/18] Installing python3-rpm-generato 100% | 81.0 MiB/s | 82.9 KiB | 00m00s [14/18] Installing python3-iniconfig-0: 100% | 26.4 MiB/s | 54.1 KiB | 00m00s [15/18] Installing python3-pluggy-0:1.6 100% | 53.2 MiB/s | 217.9 KiB | 00m00s [16/18] Installing python3-pygments-0:2 100% | 161.8 MiB/s | 11.5 MiB | 00m00s [17/18] Installing python3-pytest-0:8.4 100% | 283.5 MiB/s | 22.7 MiB | 00m00s [18/18] Installing python3-devel-0:3.14 100% | 35.3 MiB/s | 2.0 MiB | 00m00s Complete! Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.src.rpm Updating and loading repositories: updates 100% | 20.4 KiB/s | 5.3 KiB | 00m00s fedora 100% | 35.8 KiB/s | 9.3 KiB | 00m00s Copr repository 100% | 8.7 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.10-1.fc44.aarch64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Nothing to do. Finish: build setup for python-pyradplan-0.8.0-1.fc44.src.rpm Start: rpmbuild python-pyradplan-0.8.0-1.fc44.src.rpm Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%mkbuilddir): /bin/sh -e /var/tmp/rpm-tmp.CBaJfg Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.uMEISt + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + rm -rf pyradplan-0.8.0 + /usr/lib/rpm/rpmuncompress -x /builddir/build/SOURCES/pyradplan-0.8.0.tar.gz + STATUS=0 + '[' 0 -ne 0 ']' + cd pyradplan-0.8.0 + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + sed -i -e '/"pydantic_ai/d' -e '/"types-array-api"/d' -e 's/"numpy>=2.0,<2.4"/"numpy>=2.0"/' pyproject.toml + grep -q '"numpy>=2.0"' pyproject.toml + grep -E '"pydantic_ai|"types-array-api' pyproject.toml + sed -i -e '/^import pyRadPlan\.ai\.agents$/d' -e 's/\[pyRadPlan, pyRadPlan\.ai\.agents\]/[pyRadPlan]/' test/test_lazy_imports.py + grep -n 'ai\.agents' test/test_lazy_imports.py + RPM_EC=0 ++ jobs -p + exit 0 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.bMiHWY + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + cd pyradplan-0.8.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + RPM_TOXENV=py314 + FEDORA=44 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement not satisfied: setuptools>=64 Handling setuptools-scm>=8 from build-system.requires Requirement not satisfied: setuptools-scm>=8 Exiting dependency generation pass: build backend + cat /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires + rm -rfv '*.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 22.8 KiB/s | 5.3 KiB | 00m00s fedora 100% | 40.0 KiB/s | 9.3 KiB | 00m00s Copr repository 100% | 11.3 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.10-1.fc44.aarch64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package Arch Version Repository Size Installing: python3-pip noarch 0:26.0.1-3.fc44 updates 11.5 MiB python3-setuptools noarch 0:80.10.2-3.fc44 fedora 7.5 MiB python3-setuptools_scm noarch 0:9.2.2-5.fc44 fedora 502.5 KiB Transaction Summary: Installing: 3 packages Total size of inbound packages is 5 MiB. Need to download 5 MiB. After this operation, 19 MiB extra will be used (install 19 MiB, remove 0 B). [1/3] python3-setuptools_scm-0:9.2.2-5. 100% | 8.6 MiB/s | 159.4 KiB | 00m00s [2/3] python3-setuptools-0:80.10.2-3.fc 100% | 70.2 MiB/s | 1.8 MiB | 00m00s [3/3] python3-pip-0:26.0.1-3.fc44.noarc 100% | 91.8 MiB/s | 2.7 MiB | 00m00s -------------------------------------------------------------------------------- [3/3] Total 100% | 152.4 MiB/s | 4.6 MiB | 00m00s Running transaction [1/5] Verify package files 100% | 200.0 B/s | 3.0 B | 00m00s [2/5] Prepare transaction 100% | 93.0 B/s | 3.0 B | 00m00s [3/5] Installing python3-setuptools-0:8 100% | 139.1 MiB/s | 7.7 MiB | 00m00s [4/5] Installing python3-setuptools_scm 100% | 19.0 MiB/s | 526.4 KiB | 00m00s [5/5] Installing python3-pip-0:26.0.1-3 100% | 99.5 MiB/s | 11.7 MiB | 00m00s Complete! Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.uqEUdV + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + cd pyradplan-0.8.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + RPM_TOXENV=py314 + FEDORA=44 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 80.10.2) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 9.2.2) toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running egg_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running dist_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/pyradplan-0.8.0.dist-info' Handling scipy>=1.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: scipy>=1.13.0 Handling numpy>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: numpy>=2.0 Handling array_api_compat from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: array_api_compat Handling array_api_strict from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: array_api_strict Handling array_api_extra from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: array_api_extra Handling ipax>=0.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: ipax>=0.13.0 Handling pymatreader>=1.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: pymatreader>=1.0.0 Handling h5py>=3.11.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: h5py>=3.11.0 Handling regex>=2024.5.15 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: regex>=2024.5.15 Handling pydicom>=2.4.4 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: pydicom>=2.4.4 Handling matplotlib>=3.9.2 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: matplotlib>=3.9.2 Handling pydantic<2.20,>=2.10 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: pydantic<2.20,>=2.10 Handling pydantic-settings<3.0,>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: pydantic-settings<3.0,>=2.0 Handling numpydantic>=1.6.9 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: numpydantic>=1.6.9 Handling SimpleITK>=2.4.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: SimpleITK>=2.4.0 Handling tqdm>=4.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: tqdm>=4.0.0 Handling pint>=0.24.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: pint>=0.24.0 Handling jinja2 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: jinja2 Handling huggingface_hub>=0.23 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: huggingface_hub>=0.23 Handling safetensors from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: safetensors Handling matlabengine; extra == "matlab" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: matlabengine; extra == "matlab" Handling oct2py; extra == "octave" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: oct2py; extra == "octave" Handling pyside6-essentials<6.12,>=6.4; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyside6-essentials<6.12,>=6.4; extra == "gui" Handling pyqtgraph>=0.12.0; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyqtgraph>=0.12.0; extra == "gui" Handling contourpy>=1.0.1; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: contourpy>=1.0.1; extra == "gui" Handling numba>=0.61.0; extra == "numba" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numba>=0.61.0; extra == "numba" Handling torch>=2.0; extra == "torch" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: torch>=2.0; extra == "torch" Handling cupy>=13.0; extra == "cupy" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: cupy>=13.0; extra == "cupy" Handling jax>=0.4.35; extra == "jax" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jax>=0.4.35; extra == "jax" Handling line_profiler>=4.0; extra == "profiling" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: line_profiler>=4.0; extra == "profiling" Handling pytest; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest; extra == "dev" Handling coverage; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: coverage; extra == "dev" Handling pytest-cov; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-cov; extra == "dev" Handling pytest-benchmark; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-benchmark; extra == "dev" Handling pre-commit; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pre-commit; extra == "dev" Handling ruff<0.18; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: ruff<0.18; extra == "dev" Handling sphinx; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx; extra == "dev" Handling numpydoc; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numpydoc; extra == "dev" Handling pydata-sphinx-theme; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pydata-sphinx-theme; extra == "dev" Handling sphinx-design; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-design; extra == "dev" Handling autodoc_pydantic; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: autodoc_pydantic; extra == "dev" Handling sphinx-autodoc-typehints; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-autodoc-typehints; extra == "dev" Handling myst-nb; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: myst-nb; extra == "dev" Handling jupytext; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jupytext; extra == "dev" + cat /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires + rm -rfv pyradplan-0.8.0.dist-info/ removed 'pyradplan-0.8.0.dist-info/licenses/LICENSE' removed directory 'pyradplan-0.8.0.dist-info/licenses' removed 'pyradplan-0.8.0.dist-info/METADATA' removed 'pyradplan-0.8.0.dist-info/entry_points.txt' removed 'pyradplan-0.8.0.dist-info/top_level.txt' removed directory 'pyradplan-0.8.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 15.7 KiB/s | 5.3 KiB | 00m00s fedora 100% | 27.5 KiB/s | 9.3 KiB | 00m00s Copr repository 100% | 6.6 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.10-1.fc44.aarch64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package "python3-pip-26.0.1-3.fc44.noarch" is already installed. Package "python3-setuptools-80.10.2-3.fc44.noarch" is already installed. Package "python3-setuptools_scm-9.2.2-5.fc44.noarch" is already installed. Package Arch Version Repository Size Installing: python3-array-api-compat noarch 0:1.15.0-1.fc44 copr_base 506.6 KiB python3-array-api-extra noarch 0:0.11.5-1.fc44 copr_base 1.4 MiB python3-array-api-strict noarch 0:2.0.1-8.fc44 fedora 694.1 KiB python3-h5py aarch64 0:3.15.1-3.fc44 fedora 4.5 MiB python3-huggingface-hub noarch 0:1.24.0-1.fc44 updates 6.5 MiB python3-ipax noarch 0:0.13.0-1.fc44 copr_base 3.0 MiB python3-jinja2 noarch 0:3.1.6-7.fc44 fedora 3.1 MiB python3-matplotlib aarch64 0:3.10.8-2.fc44 fedora 31.8 MiB python3-numpy aarch64 1:2.4.6-1.fc44 updates 36.3 MiB python3-numpydantic noarch 0:2.0.0-1.fc44 copr_base 621.5 KiB python3-pint noarch 0:0.25.2-2.fc44 fedora 3.4 MiB python3-pydantic noarch 0:2.12.5-4.fc44 updates 5.1 MiB python3-pydantic-settings noarch 0:2.15.0-1.fc44 updates 557.0 KiB python3-pydicom noarch 0:3.0.2-1.fc44 updates 13.9 MiB python3-pymatreader noarch 0:1.3.1-1.fc44 copr_base 65.9 KiB python3-regex aarch64 0:2026.9.10-1.fc44 updates 2.1 MiB python3-safetensors aarch64 0:0.7.0-1.fc44 updates 926.2 KiB python3-scipy aarch64 0:1.16.2-3.fc44 fedora 63.3 MiB python3-simpleitk aarch64 0:2.5.5-12.fc44 copr_base 15.0 MiB python3-tqdm noarch 0:4.69.0-2.fc44 updates 578.4 KiB Installing dependencies: CharLS aarch64 0:2.4.3-2.fc44 fedora 346.8 KiB InsightToolkit5 aarch64 0:5.4.7-24.fc44 copr_base 32.6 MiB abattis-cantarell-vf-fonts noarch 0:0.301-17.fc44 fedora 192.7 KiB abseil-cpp aarch64 0:20260107.1-1.fc44 fedora 6.5 MiB armadillo12 aarch64 0:12.8.1-1.fc44 copr_base 146.0 KiB arpack aarch64 0:3.9.1-9.fc44 fedora 553.6 KiB blosc aarch64 0:1.21.6-10.fc44 fedora 129.8 KiB boost-container aarch64 0:1.90.0-7.fc44 fedora 69.3 KiB boost-program-options aarch64 0:1.90.0-7.fc44 fedora 267.1 KiB cairo aarch64 0:1.18.6-1.fc44 updates 1.8 MiB cfitsio aarch64 0:4.6.3-2.fc44 fedora 1.7 MiB dcmtk aarch64 0:3.7.0^20260922git8d68392-1.fc44 copr_base 43.1 MiB default-fonts-core-sans noarch 0:4.3-1.fc44 fedora 11.9 KiB dejavu-sans-fonts noarch 0:2.37-29.fc44 fedora 5.5 MiB double-conversion aarch64 0:3.4.0-3.fc44 fedora 141.1 KiB expatpp aarch64 0:0-0.39.20120624svn6.fc44 fedora 77.8 KiB fftw-libs-double aarch64 0:3.3.10-17.fc44 fedora 1.8 MiB fftw-libs-single aarch64 0:3.3.10-17.fc44 fedora 1.9 MiB flexiblas aarch64 0:3.5.0-2.fc44 fedora 38.0 KiB flexiblas-netlib aarch64 0:3.5.0-2.fc44 fedora 14.2 MiB flexiblas-netlib64 aarch64 0:3.5.0-2.fc44 fedora 14.0 MiB flexiblas-openblas-openmp aarch64 0:3.5.0-2.fc44 fedora 67.2 KiB flexiblas-openblas-openmp64 aarch64 0:3.5.0-2.fc44 fedora 67.2 KiB fmt aarch64 0:11.2.0-4.fc44 fedora 262.3 KiB fontconfig aarch64 0:2.17.0-4.fc44 fedora 1.2 MiB fonts-filesystem noarch 1:5.0.0-2.fc44 fedora 0.0 B freetype aarch64 0:2.14.3-1.fc44 updates 878.6 KiB freexl aarch64 0:2.0.0-20.fc44 fedora 93.3 KiB fribidi aarch64 0:1.0.16-4.fc44 fedora 246.0 KiB gdal-libs aarch64 0:3.12.4-1.fc44 updates 30.3 MiB gdcm aarch64 0:3.0.24-17.fc44 fedora 8.2 MiB geos aarch64 0:3.14.1-2.fc44 fedora 4.0 MiB giflib aarch64 0:6.1.3-2.fc44 updates 138.2 KiB glib2 aarch64 0:2.88.4-1.fc44 updates 15.9 MiB google-noto-fonts-common noarch 0:20251201-2.fc44 fedora 17.7 KiB google-noto-sans-vf-fonts noarch 0:20251201-2.fc44 fedora 1.4 MiB gpgme aarch64 0:2.0.1-5.fc44 updates 761.4 KiB gpgmepp aarch64 0:2.0.1-5.fc44 updates 458.5 KiB graphite2 aarch64 0:1.3.14-20.fc44 fedora 239.3 KiB harfbuzz aarch64 0:14.1.0-2.fc44 updates 2.7 MiB hdf-libs aarch64 0:4.3.0-5.fc44 fedora 722.6 KiB hdf5 aarch64 0:1.14.6-7.fc44 fedora 7.0 MiB imath aarch64 0:3.1.12-6.fc44 fedora 387.6 KiB jbigkit-libs aarch64 0:2.1-33.fc44 fedora 181.2 KiB jsoncpp aarch64 0:1.9.6-3.fc44 fedora 271.7 KiB lcms2 aarch64 0:2.16-7.fc44 fedora 484.7 KiB libX11 aarch64 0:1.8.13-3.fc44 updates 1.3 MiB libX11-common noarch 0:1.8.13-3.fc44 updates 1.1 MiB libXau aarch64 0:1.0.12-4.fc44 fedora 120.8 KiB libXext aarch64 0:1.3.6-5.fc44 fedora 145.7 KiB libXrender aarch64 0:0.9.12-4.fc44 fedora 69.9 KiB libaec aarch64 0:1.1.5-1.fc44 fedora 154.3 KiB libarrow aarch64 0:23.0.1-1.fc44 fedora 11.4 MiB libarrow-acero-libs aarch64 0:23.0.1-1.fc44 fedora 1.3 MiB libarrow-compute-libs aarch64 0:23.0.1-1.fc44 fedora 11.0 MiB libarrow-dataset-libs aarch64 0:23.0.1-1.fc44 fedora 1.4 MiB libarrow-doc noarch 0:23.0.1-1.fc44 fedora 119.1 KiB libdc1394 aarch64 0:2.2.7-9.fc44 fedora 378.7 KiB libdeflate aarch64 0:1.26-1.fc44 updates 163.9 KiB libgeotiff aarch64 0:1.7.4-5.fc44 fedora 517.6 KiB libgfortran aarch64 0:16.2.1-3.fc44 updates 1.7 MiB libgta aarch64 0:1.2.1-17.fc44 fedora 94.0 KiB libharu aarch64 0:2.4.5-2.fc44 fedora 1.7 MiB libicu aarch64 0:77.1-3.fc44 updates 36.5 MiB libimagequant aarch64 0:4.1.0-2.fc44 fedora 672.1 KiB libjpeg-turbo aarch64 0:3.1.3-1.fc44 fedora 677.7 KiB libkml aarch64 0:1.3.0-58.fc44 updates 1.2 MiB liblerc aarch64 0:4.3.0-1.fc44 updates 547.7 KiB liblzf aarch64 0:3.6-34.fc44 fedora 153.3 KiB libminc aarch64 0:2.4.03-31.fc44 updates 668.9 KiB libogg aarch64 2:1.3.6-2.fc44 fedora 77.7 KiB liborc2 aarch64 0:2.2.2-2.fc44 fedora 1.9 MiB libpng aarch64 2:1.6.59-1.fc44 updates 269.8 KiB libpq aarch64 0:18.0-4.fc44 fedora 1.0 MiB libqhull_r aarch64 1:8.0.2-8.fc44 fedora 455.3 KiB libraqm aarch64 0:0.10.1-4.fc44 fedora 68.5 KiB libraw1394 aarch64 0:2.1.2-25.fc44 fedora 310.2 KiB librttopo aarch64 0:1.1.0-19.fc44 fedora 544.5 KiB libspatialite aarch64 0:5.1.0-12.fc44 fedora 15.0 MiB libtheora aarch64 1:1.1.1-41.fc44 fedora 468.3 KiB libtiff aarch64 0:4.7.2-3.fc44 updates 659.4 KiB libtirpc aarch64 0:1.3.8-0.fc44 updates 212.0 KiB libwebp aarch64 0:1.6.0-3.fc44 fedora 816.8 KiB libxcb aarch64 0:1.17.0-7.fc44 fedora 2.1 MiB libyaml aarch64 0:0.2.5-18.fc44 fedora 134.3 KiB libzip aarch64 0:1.11.4-3.fc44 fedora 135.6 KiB lzo aarch64 0:2.10-16.fc44 fedora 162.8 KiB mariadb-connector-c aarch64 0:3.4.9-2.fc44 updates 993.9 KiB mariadb-connector-c-config noarch 0:3.4.9-2.fc44 updates 26.4 KiB minizip-ng-compat aarch64 0:4.1.0-1.fc44 fedora 198.4 KiB muParser aarch64 0:2.3.5-5.fc44 fedora 552.6 KiB netcdf aarch64 0:4.9.3-2.fc44 fedora 3.1 MiB nspr aarch64 0:4.39.0-7.fc44 updates 419.4 KiB nss aarch64 0:3.131.0-1.fc44 updates 2.0 MiB nss-softokn aarch64 0:3.131.0-1.fc44 updates 2.3 MiB nss-softokn-freebl aarch64 0:3.131.0-1.fc44 updates 1.0 MiB nss-sysinit aarch64 0:3.131.0-1.fc44 updates 70.0 KiB nss-util aarch64 0:3.131.0-1.fc44 updates 216.8 KiB openblas aarch64 0:0.3.29-2.fc43 fedora 111.7 KiB openblas-openmp aarch64 0:0.3.29-2.fc43 fedora 20.4 MiB openblas-openmp64 aarch64 0:0.3.29-2.fc43 fedora 20.2 MiB openexr-libs aarch64 0:3.2.4-7.fc44 fedora 6.6 MiB openjpeg aarch64 0:2.5.4-5.fc44 updates 412.3 KiB parquet-libs aarch64 0:23.0.1-1.fc44 fedora 3.5 MiB pixman aarch64 0:0.46.2-3.fc44 fedora 654.3 KiB poppler aarch64 0:26.01.0-3.fc44 fedora 3.6 MiB poppler-data noarch 0:0.4.11-11.fc44 fedora 12.3 MiB proj aarch64 0:9.8.1-1.fc44 updates 4.3 MiB proj-data noarch 0:9.8.1-1.fc44 updates 10.0 MiB protobuf aarch64 0:3.19.6-20.fc44 fedora 3.1 MiB pugixml aarch64 0:1.16-1.fc44 updates 265.3 KiB python3-annotated-types noarch 0:0.7.0-9.fc44 fedora 85.1 KiB python3-anyio noarch 0:4.13.0-2.fc44 updates 1.5 MiB python3-cached_property noarch 0:2.0.1-7.fc44 fedora 35.2 KiB python3-cairo aarch64 0:1.28.0-5.fc44 fedora 516.6 KiB python3-certifi noarch 0:2026.01.04-1.fc44 fedora 7.4 KiB python3-charset-normalizer noarch 0:3.4.4-2.fc44 fedora 356.2 KiB python3-click noarch 1:8.3.3-1.fc44 updates 1.2 MiB python3-contourpy aarch64 0:1.4.0-1.fc44 updates 860.5 KiB python3-cycler noarch 0:0.11.0-20.fc44 fedora 37.8 KiB python3-dateutil noarch 1:2.9.0.post0-7.fc44 fedora 878.0 KiB python3-dotenv noarch 0:1.2.2-1.fc44 updates 149.4 KiB python3-filelock noarch 0:3.15.4-11.fc44 fedora 97.5 KiB python3-flexcache noarch 0:0.3-11.fc44 fedora 57.0 KiB python3-flexparser noarch 0:0.4-7.fc44 fedora 263.5 KiB python3-fonttools aarch64 0:4.62.1-1.fc44 updates 19.4 MiB python3-fsspec noarch 0:2026.9.0-1.fc44 updates 2.0 MiB python3-h11 noarch 0:0.16.0-6.fc44 fedora 279.9 KiB python3-httpcore noarch 0:1.0.9-6.fc44 fedora 853.9 KiB python3-httpx noarch 0:0.28.1-11.fc44 fedora 992.1 KiB python3-idna noarch 0:3.18-1.fc44 updates 522.3 KiB python3-kiwisolver aarch64 0:1.5.1-1.fc44 updates 161.1 KiB python3-markupsafe aarch64 0:3.0.2-7.fc44 fedora 117.4 KiB python3-matplotlib-data-fonts aarch64 0:3.10.8-2.fc44 fedora 7.9 MiB python3-numpy-f2py aarch64 1:2.4.6-1.fc44 updates 2.1 MiB python3-olefile noarch 0:0.47-13.fc44 fedora 346.5 KiB python3-pillow aarch64 0:12.3.0-7.fc44 updates 4.6 MiB python3-platformdirs noarch 0:4.9.1-1.fc44 fedora 236.5 KiB python3-pooch noarch 0:1.9.0-1.fc44 fedora 657.1 KiB python3-pydantic-core aarch64 0:2.41.5-11.fc44 updates 4.9 MiB python3-pyparsing noarch 0:3.1.2-15.fc44 fedora 1.0 MiB python3-pyyaml aarch64 0:6.0.3-3.fc44 fedora 797.1 KiB python3-requests noarch 0:2.33.1-1.fc44 updates 477.3 KiB python3-six noarch 0:1.17.0-8.fc44 fedora 118.0 KiB python3-typing-extensions noarch 0:4.16.0-4.fc44 updates 552.0 KiB python3-typing-inspection noarch 0:0.4.4-1.fc44 updates 93.4 KiB python3-urllib3 noarch 0:2.8.0-3.fc44 updates 1.2 MiB python3-xmltodict noarch 0:0.14.2-5.fc44 fedora 56.0 KiB re2 aarch64 2:20251105-4.fc44 fedora 598.8 KiB rply aarch64 0:1.1.4-11.fc44 updates 315.7 KiB simpleitk aarch64 0:2.5.5-12.fc44 copr_base 278.8 MiB snappy aarch64 0:1.2.2-4.fc44 fedora 83.6 KiB thrift aarch64 0:0.20.0-9.fc44 fedora 4.8 MiB unixODBC aarch64 0:2.3.14-3.fc44 fedora 1.3 MiB uriparser aarch64 0:1.0.3-1.fc44 updates 243.3 KiB utf8proc aarch64 0:2.11.3-2.fc44 fedora 413.5 KiB viskores aarch64 0:1.2.0-3.fc44 copr_base 117.8 MiB vtk aarch64 0:9.7.0-6.fc44 copr_base 242.4 MiB vxl aarch64 0:3.5.0-20.fc44 updates 56.3 MiB xerces-c aarch64 0:3.3.0-9.fc44 fedora 3.8 MiB xml-common noarch 0:0.6.3-68.fc44 fedora 78.4 KiB Transaction Summary: Installing: 181 packages Total size of inbound packages is 254 MiB. Need to download 254 MiB. After this operation, 1 GiB extra will be used (install 1 GiB, remove 0 B). [ 1/181] python3-array-api-strict-0:2. 100% | 9.4 MiB/s | 164.1 KiB | 00m00s [ 2/181] python3-h5py-0:3.15.1-3.fc44. 100% | 94.9 MiB/s | 1.0 MiB | 00m00s [ 3/181] python3-array-api-extra-0:0.1 100% | 985.9 KiB/s | 272.1 KiB | 00m00s [ 4/181] python3-jinja2-0:3.1.6-7.fc44 100% | 71.9 MiB/s | 515.5 KiB | 00m00s [ 5/181] python3-array-api-compat-0:1. 100% | 338.3 KiB/s | 123.1 KiB | 00m00s [ 6/181] python3-ipax-0:0.13.0-1.fc44. 100% | 1.6 MiB/s | 574.2 KiB | 00m00s [ 7/181] python3-pint-0:0.25.2-2.fc44. 100% | 48.2 MiB/s | 740.8 KiB | 00m00s [ 8/181] python3-matplotlib-0:3.10.8-2 100% | 43.9 MiB/s | 7.9 MiB | 00m00s [ 9/181] python3-numpydantic-0:2.0.0-1 100% | 754.9 KiB/s | 186.5 KiB | 00m00s [ 10/181] python3-pydantic-0:2.12.5-4.f 100% | 66.1 MiB/s | 1.0 MiB | 00m00s [ 11/181] python3-scipy-0:1.16.2-3.fc44 100% | 61.0 MiB/s | 15.2 MiB | 00m00s [ 12/181] python3-pydantic-settings-0:2 100% | 10.0 MiB/s | 173.8 KiB | 00m00s [ 13/181] python3-numpy-1:2.4.6-1.fc44. 100% | 232.0 MiB/s | 7.0 MiB | 00m00s [ 14/181] python3-huggingface-hub-0:1.2 100% | 42.1 MiB/s | 1.4 MiB | 00m00s [ 15/181] python3-pydicom-0:3.0.2-1.fc4 100% | 105.5 MiB/s | 3.1 MiB | 00m00s [ 16/181] python3-regex-0:2026.9.10-1.f 100% | 44.7 MiB/s | 411.5 KiB | 00m00s [ 17/181] python3-safetensors-0:0.7.0-1 100% | 72.5 MiB/s | 371.4 KiB | 00m00s [ 18/181] python3-tqdm-0:4.69.0-2.fc44. 100% | 34.9 MiB/s | 178.7 KiB | 00m00s [ 19/181] python3-simpleitk-0:2.5.5-12. 100% | 6.1 MiB/s | 1.7 MiB | 00m00s [ 20/181] liblzf-0:3.6-34.fc44.aarch64 100% | 9.0 MiB/s | 27.7 KiB | 00m00s [ 21/181] python3-cached_property-0:2.0 100% | 6.7 MiB/s | 20.5 KiB | 00m00s [ 22/181] python3-six-0:1.17.0-8.fc44.n 100% | 20.5 MiB/s | 42.0 KiB | 00m00s [ 23/181] python3-markupsafe-0:3.0.2-7. 100% | 10.3 MiB/s | 31.6 KiB | 00m00s [ 24/181] dejavu-sans-fonts-0:2.37-29.f 100% | 132.5 MiB/s | 1.3 MiB | 00m00s [ 25/181] libqhull_r-1:8.0.2-8.fc44.aar 100% | 47.5 MiB/s | 194.7 KiB | 00m00s [ 26/181] python3-cairo-0:1.28.0-5.fc44 100% | 31.3 MiB/s | 128.2 KiB | 00m00s [ 27/181] python3-cycler-0:0.11.0-20.fc 100% | 10.7 MiB/s | 22.0 KiB | 00m00s [ 28/181] python3-dateutil-1:2.9.0.post 100% | 112.1 MiB/s | 344.3 KiB | 00m00s [ 29/181] hdf5-0:1.14.6-7.fc44.aarch64 100% | 27.7 MiB/s | 1.8 MiB | 00m00s [ 30/181] python3-pyparsing-0:3.1.2-15. 100% | 56.0 MiB/s | 286.8 KiB | 00m00s [ 31/181] python3-flexcache-0:0.3-11.fc 100% | 5.3 MiB/s | 27.2 KiB | 00m00s [ 32/181] python3-matplotlib-data-fonts 100% | 111.5 MiB/s | 2.3 MiB | 00m00s [ 33/181] python3-flexparser-0:0.4-7.fc 100% | 6.7 MiB/s | 54.9 KiB | 00m00s [ 34/181] flexiblas-netlib-0:3.5.0-2.fc 100% | 222.0 MiB/s | 4.0 MiB | 00m00s [ 35/181] python3-platformdirs-0:4.9.1- 100% | 3.0 MiB/s | 59.1 KiB | 00m00s [ 36/181] python3-pooch-0:1.9.0-1.fc44. 100% | 17.8 MiB/s | 145.9 KiB | 00m00s [ 37/181] python3-annotated-types-0:0.7 100% | 4.4 MiB/s | 31.4 KiB | 00m00s [ 38/181] python3-click-1:8.3.3-1.fc44. 100% | 53.0 MiB/s | 271.1 KiB | 00m00s [ 39/181] python3-filelock-0:3.15.4-11. 100% | 14.7 MiB/s | 45.1 KiB | 00m00s [ 40/181] python3-httpx-0:0.28.1-11.fc4 100% | 51.8 MiB/s | 212.4 KiB | 00m00s [ 41/181] python3-pyyaml-0:6.0.3-3.fc44 100% | 110.7 MiB/s | 226.6 KiB | 00m00s [ 42/181] python3-numpy-f2py-1:2.4.6-1. 100% | 166.8 MiB/s | 512.5 KiB | 00m00s [ 43/181] python3-xmltodict-0:0.14.2-5. 100% | 8.7 MiB/s | 26.7 KiB | 00m00s [ 44/181] libaec-0:1.1.5-1.fc44.aarch64 100% | 12.0 MiB/s | 36.7 KiB | 00m00s [ 45/181] fonts-filesystem-1:5.0.0-2.fc 100% | 4.3 MiB/s | 8.9 KiB | 00m00s [ 46/181] flexiblas-0:3.5.0-2.fc44.aarc 100% | 22.5 MiB/s | 23.0 KiB | 00m00s [ 47/181] flexiblas-openblas-openmp-0:3 100% | 15.9 MiB/s | 16.3 KiB | 00m00s [ 48/181] python3-pymatreader-0:1.3.1-1 100% | 90.5 KiB/s | 27.5 KiB | 00m00s [ 49/181] python3-certifi-0:2026.01.04- 100% | 4.9 MiB/s | 14.9 KiB | 00m00s [ 50/181] python3-httpcore-0:1.0.9-6.fc 100% | 38.4 MiB/s | 157.1 KiB | 00m00s [ 51/181] libyaml-0:0.2.5-18.fc44.aarch 100% | 28.3 MiB/s | 57.9 KiB | 00m00s [ 52/181] openblas-openmp-0:0.3.29-2.fc 100% | 215.3 MiB/s | 3.9 MiB | 00m00s [ 53/181] double-conversion-0:3.4.0-3.f 100% | 24.1 MiB/s | 49.3 KiB | 00m00s [ 54/181] fftw-libs-double-0:3.3.10-17. 100% | 162.0 MiB/s | 663.7 KiB | 00m00s [ 55/181] fftw-libs-single-0:3.3.10-17. 100% | 168.4 MiB/s | 689.8 KiB | 00m00s [ 56/181] gdcm-0:3.0.24-17.fc44.aarch64 100% | 108.9 MiB/s | 1.4 MiB | 00m00s [ 57/181] libjpeg-turbo-0:3.1.3-1.fc44. 100% | 81.8 MiB/s | 251.2 KiB | 00m00s [ 58/181] InsightToolkit5-0:5.4.7-24.fc 100% | 22.1 MiB/s | 4.7 MiB | 00m00s [ 59/181] dcmtk-0:3.7.0^20260922git8d68 100% | 14.8 MiB/s | 7.3 MiB | 00m00s [ 60/181] python3-h11-0:0.16.0-6.fc44.n 100% | 26.4 MiB/s | 81.0 KiB | 00m00s [ 61/181] openblas-0:0.3.29-2.fc43.aarc 100% | 41.2 MiB/s | 42.2 KiB | 00m00s [ 62/181] CharLS-0:2.4.3-2.fc44.aarch64 100% | 39.9 MiB/s | 122.6 KiB | 00m00s [ 63/181] fmt-0:11.2.0-4.fc44.aarch64 100% | 47.9 MiB/s | 98.0 KiB | 00m00s [ 64/181] jsoncpp-0:1.9.6-3.fc44.aarch6 100% | 92.6 MiB/s | 94.8 KiB | 00m00s [ 65/181] libharu-0:2.4.5-2.fc44.aarch6 100% | 93.8 MiB/s | 576.5 KiB | 00m00s [ 66/181] libogg-2:1.3.6-2.fc44.aarch64 100% | 32.7 MiB/s | 33.4 KiB | 00m00s [ 67/181] libtheora-1:1.1.1-41.fc44.aar 100% | 76.2 MiB/s | 156.1 KiB | 00m00s [ 68/181] netcdf-0:4.9.3-2.fc44.aarch64 100% | 132.8 MiB/s | 815.7 KiB | 00m00s [ 69/181] simpleitk-0:2.5.5-12.fc44.aar 100% | 35.2 MiB/s | 37.6 MiB | 00m01s [ 70/181] blosc-0:1.21.6-10.fc44.aarch6 100% | 15.9 MiB/s | 48.8 KiB | 00m00s [ 71/181] libzip-0:1.11.4-3.fc44.aarch6 100% | 22.7 MiB/s | 69.8 KiB | 00m00s [ 72/181] snappy-0:1.2.2-4.fc44.aarch64 100% | 20.4 MiB/s | 41.8 KiB | 00m00s [ 73/181] freetype-0:2.14.3-1.fc44.aarc 100% | 135.3 MiB/s | 415.7 KiB | 00m00s [ 74/181] vtk-0:9.7.0-6.fc44.aarch64 100% | 40.1 MiB/s | 37.7 MiB | 00m01s [ 75/181] viskores-0:1.2.0-3.fc44.aarch 100% | 30.7 MiB/s | 14.8 MiB | 00m00s [ 76/181] cfitsio-0:4.6.3-2.fc44.aarch6 100% | 28.4 MiB/s | 581.2 KiB | 00m00s [ 77/181] freexl-0:2.0.0-20.fc44.aarch6 100% | 6.4 MiB/s | 45.6 KiB | 00m00s [ 78/181] imath-0:3.1.12-6.fc44.aarch64 100% | 23.2 MiB/s | 94.9 KiB | 00m00s [ 79/181] geos-0:3.14.1-2.fc44.aarch64 100% | 106.9 MiB/s | 1.2 MiB | 00m00s [ 80/181] libarrow-compute-libs-0:23.0. 100% | 108.7 MiB/s | 2.4 MiB | 00m00s [ 81/181] libarrow-0:23.0.1-1.fc44.aarc 100% | 98.8 MiB/s | 3.1 MiB | 00m00s [ 82/181] libarrow-dataset-libs-0:23.0. 100% | 76.8 MiB/s | 471.8 KiB | 00m00s [ 83/181] libgeotiff-0:1.7.4-5.fc44.aar 100% | 31.7 MiB/s | 97.2 KiB | 00m00s [ 84/181] libpq-0:18.0-4.fc44.aarch64 100% | 131.0 MiB/s | 268.2 KiB | 00m00s [ 85/181] libgta-0:1.2.1-17.fc44.aarch6 100% | 8.6 MiB/s | 35.2 KiB | 00m00s [ 86/181] libwebp-0:1.6.0-3.fc44.aarch6 100% | 84.7 MiB/s | 260.3 KiB | 00m00s [ 87/181] muParser-0:2.3.5-5.fc44.aarch 100% | 22.2 MiB/s | 159.0 KiB | 00m00s [ 88/181] libspatialite-0:5.1.0-12.fc44 100% | 105.8 MiB/s | 2.8 MiB | 00m00s [ 89/181] openexr-libs-0:3.2.4-7.fc44.a 100% | 66.3 MiB/s | 1.1 MiB | 00m00s [ 90/181] poppler-0:26.01.0-3.fc44.aarc 100% | 93.3 MiB/s | 1.2 MiB | 00m00s [ 91/181] gdal-libs-0:3.12.4-1.fc44.aar 100% | 42.9 MiB/s | 10.1 MiB | 00m00s [ 92/181] unixODBC-0:2.3.14-3.fc44.aarc 100% | 35.0 MiB/s | 394.3 KiB | 00m00s [ 93/181] minizip-ng-compat-0:4.1.0-1.f 100% | 7.3 MiB/s | 66.9 KiB | 00m00s [ 94/181] libarrow-doc-0:23.0.1-1.fc44. 100% | 9.6 MiB/s | 29.5 KiB | 00m00s [ 95/181] parquet-libs-0:23.0.1-1.fc44. 100% | 22.0 MiB/s | 1.0 MiB | 00m00s [ 96/181] re2-2:20251105-4.fc44.aarch64 100% | 35.1 MiB/s | 215.5 KiB | 00m00s [ 97/181] utf8proc-0:2.11.3-2.fc44.aarc 100% | 40.6 MiB/s | 83.1 KiB | 00m00s [ 98/181] libarrow-acero-libs-0:23.0.1- 100% | 76.0 MiB/s | 467.2 KiB | 00m00s [ 99/181] librttopo-0:1.1.0-19.fc44.aar 100% | 39.7 MiB/s | 203.1 KiB | 00m00s [100/181] boost-program-options-0:1.90. 100% | 50.3 MiB/s | 103.1 KiB | 00m00s [101/181] liborc2-0:2.2.2-2.fc44.aarch6 100% | 17.6 MiB/s | 539.9 KiB | 00m00s [102/181] fontconfig-0:2.17.0-4.fc44.aa 100% | 133.8 MiB/s | 274.0 KiB | 00m00s [103/181] lcms2-0:2.16-7.fc44.aarch64 100% | 44.2 MiB/s | 181.0 KiB | 00m00s [104/181] xerces-c-0:3.3.0-9.fc44.aarch 100% | 17.8 MiB/s | 984.0 KiB | 00m00s [105/181] protobuf-0:3.19.6-20.fc44.aar 100% | 149.3 MiB/s | 917.3 KiB | 00m00s [106/181] thrift-0:0.20.0-9.fc44.aarch6 100% | 88.1 MiB/s | 1.6 MiB | 00m00s [107/181] boost-container-0:1.90.0-7.fc 100% | 12.4 MiB/s | 38.0 KiB | 00m00s [108/181] default-fonts-core-sans-0:4.3 100% | 14.3 MiB/s | 29.2 KiB | 00m00s [109/181] poppler-data-0:0.4.11-11.fc44 100% | 93.6 MiB/s | 2.0 MiB | 00m00s [110/181] xml-common-0:0.6.3-68.fc44.no 100% | 7.6 MiB/s | 31.1 KiB | 00m00s [111/181] abattis-cantarell-vf-fonts-0: 100% | 58.8 MiB/s | 120.4 KiB | 00m00s [112/181] google-noto-sans-vf-fonts-0:2 100% | 150.1 MiB/s | 614.9 KiB | 00m00s [113/181] google-noto-fonts-common-0:20 100% | 8.7 MiB/s | 17.7 KiB | 00m00s [114/181] libpng-2:1.6.59-1.fc44.aarch6 100% | 57.5 MiB/s | 117.8 KiB | 00m00s [115/181] libtiff-0:4.7.2-3.fc44.aarch6 100% | 69.8 MiB/s | 214.5 KiB | 00m00s [116/181] jbigkit-libs-0:2.1-33.fc44.aa 100% | 10.4 MiB/s | 53.1 KiB | 00m00s [117/181] proj-0:9.8.1-1.fc44.aarch64 100% | 97.4 MiB/s | 1.5 MiB | 00m00s [118/181] abseil-cpp-0:20260107.1-1.fc4 100% | 18.0 MiB/s | 756.6 KiB | 00m00s [119/181] pugixml-0:1.16-1.fc44.aarch64 100% | 19.9 MiB/s | 102.0 KiB | 00m00s [120/181] proj-data-0:9.8.1-1.fc44.noar 100% | 68.7 MiB/s | 1.4 MiB | 00m00s [121/181] expatpp-0:0-0.39.20120624svn6 100% | 4.3 MiB/s | 21.8 KiB | 00m00s [122/181] libdc1394-0:2.2.7-9.fc44.aarc 100% | 31.7 MiB/s | 129.9 KiB | 00m00s [123/181] libraw1394-0:2.1.2-25.fc44.aa 100% | 12.5 MiB/s | 64.2 KiB | 00m00s [124/181] libminc-0:2.4.03-31.fc44.aarc 100% | 12.8 MiB/s | 262.9 KiB | 00m00s [125/181] libgfortran-0:16.2.1-3.fc44.a 100% | 41.9 MiB/s | 472.0 KiB | 00m00s [126/181] python3-requests-0:2.33.1-1.f 100% | 14.3 MiB/s | 160.6 KiB | 00m00s [127/181] libicu-0:77.1-3.fc44.aarch64 100% | 200.1 MiB/s | 10.6 MiB | 00m00s [128/181] python3-charset-normalizer-0: 100% | 8.2 MiB/s | 117.3 KiB | 00m00s [129/181] python3-typing-extensions-0:4 100% | 18.6 MiB/s | 114.1 KiB | 00m00s [130/181] python3-contourpy-0:1.4.0-1.f 100% | 17.3 MiB/s | 283.7 KiB | 00m00s [131/181] python3-kiwisolver-0:1.5.1-1. 100% | 10.5 MiB/s | 64.5 KiB | 00m00s [132/181] python3-fonttools-0:4.62.1-1. 100% | 92.7 MiB/s | 3.2 MiB | 00m00s [133/181] python3-pillow-0:12.3.0-7.fc4 100% | 57.1 MiB/s | 1.0 MiB | 00m00s [134/181] libimagequant-0:4.1.0-2.fc44. 100% | 58.6 MiB/s | 300.1 KiB | 00m00s [135/181] libraqm-0:0.10.1-4.fc44.aarch 100% | 5.5 MiB/s | 22.4 KiB | 00m00s [136/181] libxcb-0:1.17.0-7.fc44.aarch6 100% | 78.5 MiB/s | 241.3 KiB | 00m00s [137/181] vxl-0:3.5.0-20.fc44.aarch64 100% | 100.0 MiB/s | 13.0 MiB | 00m00s [138/181] fribidi-0:1.0.16-4.fc44.aarch 100% | 3.7 MiB/s | 53.6 KiB | 00m00s [139/181] python3-olefile-0:0.47-13.fc4 100% | 4.6 MiB/s | 75.0 KiB | 00m00s [140/181] libXau-0:1.0.12-4.fc44.aarch6 100% | 32.9 MiB/s | 33.7 KiB | 00m00s [141/181] python3-idna-0:3.18-1.fc44.no 100% | 50.8 MiB/s | 104.1 KiB | 00m00s [142/181] cairo-0:1.18.6-1.fc44.aarch64 100% | 171.5 MiB/s | 702.4 KiB | 00m00s [143/181] libXext-0:1.3.6-5.fc44.aarch6 100% | 12.6 MiB/s | 38.6 KiB | 00m00s [144/181] libXrender-0:0.9.12-4.fc44.aa 100% | 13.1 MiB/s | 26.8 KiB | 00m00s [145/181] python3-anyio-0:4.13.0-2.fc44 100% | 38.6 MiB/s | 316.0 KiB | 00m00s [146/181] lzo-0:2.10-16.fc44.aarch64 100% | 21.1 MiB/s | 64.8 KiB | 00m00s [147/181] pixman-0:0.46.2-3.fc44.aarch6 100% | 103.7 MiB/s | 212.4 KiB | 00m00s [148/181] gpgme-0:2.0.1-5.fc44.aarch64 100% | 108.6 MiB/s | 222.4 KiB | 00m00s [149/181] gpgmepp-0:2.0.1-5.fc44.aarch6 100% | 32.3 MiB/s | 132.4 KiB | 00m00s [150/181] nspr-0:4.39.0-7.fc44.aarch64 100% | 26.6 MiB/s | 136.0 KiB | 00m00s [151/181] nss-util-0:3.131.0-1.fc44.aar 100% | 21.3 MiB/s | 87.4 KiB | 00m00s [152/181] nss-0:3.131.0-1.fc44.aarch64 100% | 69.0 MiB/s | 706.1 KiB | 00m00s [153/181] nss-softokn-freebl-0:3.131.0- 100% | 58.7 MiB/s | 360.7 KiB | 00m00s [154/181] nss-sysinit-0:3.131.0-1.fc44. 100% | 5.0 MiB/s | 20.3 KiB | 00m00s [155/181] openjpeg-0:2.5.4-5.fc44.aarch 100% | 59.8 MiB/s | 183.6 KiB | 00m00s [156/181] libdeflate-0:1.26-1.fc44.aarc 100% | 20.8 MiB/s | 63.8 KiB | 00m00s [157/181] nss-softokn-0:3.131.0-1.fc44. 100% | 23.6 MiB/s | 435.4 KiB | 00m00s [158/181] harfbuzz-0:14.1.0-2.fc44.aarc 100% | 209.9 MiB/s | 1.0 MiB | 00m00s [159/181] graphite2-0:1.3.14-20.fc44.aa 100% | 17.9 MiB/s | 91.7 KiB | 00m00s [160/181] libX11-0:1.8.13-3.fc44.aarch6 100% | 105.7 MiB/s | 649.6 KiB | 00m00s [161/181] libX11-common-0:1.8.13-3.fc44 100% | 57.1 MiB/s | 175.3 KiB | 00m00s [162/181] python3-urllib3-0:2.8.0-3.fc4 100% | 101.1 MiB/s | 310.7 KiB | 00m00s [163/181] rply-0:1.1.4-11.fc44.aarch64 100% | 9.1 MiB/s | 46.4 KiB | 00m00s [164/181] python3-dotenv-0:1.2.2-1.fc44 100% | 14.0 MiB/s | 57.5 KiB | 00m00s [165/181] python3-typing-inspection-0:0 100% | 11.0 MiB/s | 33.7 KiB | 00m00s [166/181] liblerc-0:4.3.0-1.fc44.aarch6 100% | 27.5 MiB/s | 197.2 KiB | 00m00s [167/181] python3-fsspec-0:2026.9.0-1.f 100% | 49.9 MiB/s | 510.8 KiB | 00m00s [168/181] python3-pydantic-core-0:2.41. 100% | 99.7 MiB/s | 1.6 MiB | 00m00s [169/181] glib2-0:2.88.4-1.fc44.aarch64 100% | 235.5 MiB/s | 3.1 MiB | 00m00s [170/181] giflib-0:6.1.3-2.fc44.aarch64 100% | 4.8 MiB/s | 54.3 KiB | 00m00s [171/181] libkml-0:1.3.0-58.fc44.aarch6 100% | 32.6 MiB/s | 333.9 KiB | 00m00s [172/181] mariadb-connector-c-0:3.4.9-2 100% | 98.9 MiB/s | 202.6 KiB | 00m00s [173/181] mariadb-connector-c-config-0: 100% | 10.5 MiB/s | 21.6 KiB | 00m00s [174/181] uriparser-0:1.0.3-1.fc44.aarc 100% | 13.9 MiB/s | 71.1 KiB | 00m00s [175/181] libtirpc-0:1.3.8-0.fc44.aarch 100% | 22.8 MiB/s | 93.4 KiB | 00m00s [176/181] hdf-libs-0:4.3.0-5.fc44.aarch 100% | 45.2 MiB/s | 277.7 KiB | 00m00s [177/181] arpack-0:3.9.1-9.fc44.aarch64 100% | 42.9 MiB/s | 175.9 KiB | 00m00s [178/181] flexiblas-openblas-openmp64-0 100% | 5.3 MiB/s | 16.3 KiB | 00m00s [179/181] flexiblas-netlib64-0:3.5.0-2. 100% | 128.2 MiB/s | 3.8 MiB | 00m00s [180/181] openblas-openmp64-0:0.3.29-2. 100% | 129.8 MiB/s | 3.8 MiB | 00m00s [181/181] armadillo12-0:12.8.1-1.fc44.a 100% | 137.1 KiB/s | 28.5 KiB | 00m00s -------------------------------------------------------------------------------- [181/181] Total 100% | 94.8 MiB/s | 254.1 MiB | 00m03s Running transaction [ 1/183] Verify package files 100% | 206.0 B/s | 181.0 B | 00m01s [ 2/183] Prepare transaction 100% | 1.3 KiB/s | 181.0 B | 00m00s [ 3/183] Installing libpng-2:1.6.59-1. 100% | 132.3 MiB/s | 271.0 KiB | 00m00s [ 4/183] Installing libjpeg-turbo-0:3. 100% | 221.2 MiB/s | 679.4 KiB | 00m00s [ 5/183] Installing python3-typing-ext 100% | 270.6 MiB/s | 554.3 KiB | 00m00s [ 6/183] Installing libgfortran-0:16.2 100% | 342.3 MiB/s | 1.7 MiB | 00m00s [ 7/183] Installing nspr-0:4.39.0-7.fc 100% | 205.6 MiB/s | 421.1 KiB | 00m00s [ 8/183] Installing libarrow-doc-0:23. 100% | 117.1 MiB/s | 119.9 KiB | 00m00s [ 9/183] Installing nss-util-0:3.131.0 100% | 212.7 MiB/s | 217.8 KiB | 00m00s [ 10/183] Installing openjpeg-0:2.5.4-5 100% | 134.9 MiB/s | 414.3 KiB | 00m00s [ 11/183] Installing python3-idna-0:3.1 100% | 25.9 MiB/s | 530.2 KiB | 00m00s [ 12/183] Installing fonts-filesystem-1 100% | 769.5 KiB/s | 788.0 B | 00m00s [ 13/183] Installing libaec-0:1.1.5-1.f 100% | 76.5 MiB/s | 156.7 KiB | 00m00s [ 14/183] Installing hdf5-0:1.14.6-7.fc 100% | 175.3 MiB/s | 7.0 MiB | 00m00s [ 15/183] Installing minizip-ng-compat- 100% | 97.3 MiB/s | 199.3 KiB | 00m00s [ 16/183] Installing libwebp-0:1.6.0-3. 100% | 200.4 MiB/s | 820.9 KiB | 00m00s [ 17/183] Installing geos-0:3.14.1-2.fc 100% | 136.4 MiB/s | 4.0 MiB | 00m00s [ 18/183] Installing snappy-0:1.2.2-4.f 100% | 83.2 MiB/s | 85.2 KiB | 00m00s [ 19/183] Installing blosc-0:1.21.6-10. 100% | 64.8 MiB/s | 132.6 KiB | 00m00s [ 20/183] Installing freexl-0:2.0.0-20. 100% | 92.2 MiB/s | 94.4 KiB | 00m00s [ 21/183] Installing python3-typing-ins 100% | 47.6 MiB/s | 97.5 KiB | 00m00s [ 22/183] Installing liblerc-0:4.3.0-1. 100% | 178.8 MiB/s | 549.2 KiB | 00m00s [ 23/183] Installing libdeflate-0:1.26- 100% | 161.5 MiB/s | 165.3 KiB | 00m00s [ 24/183] Installing lcms2-0:2.16-7.fc4 100% | 158.3 MiB/s | 486.3 KiB | 00m00s [ 25/183] Installing imath-0:3.1.12-6.f 100% | 126.9 MiB/s | 389.7 KiB | 00m00s [ 26/183] Installing libogg-2:1.3.6-2.f 100% | 77.3 MiB/s | 79.2 KiB | 00m00s [ 27/183] Installing openblas-0:0.3.29- 100% | 110.8 MiB/s | 113.5 KiB | 00m00s [ 28/183] Installing python3-certifi-0: 100% | 10.9 MiB/s | 11.2 KiB | 00m00s [ 29/183] Installing python3-platformdi 100% | 118.9 MiB/s | 243.4 KiB | 00m00s [ 30/183] Installing libqhull_r-1:8.0.2 100% | 222.7 MiB/s | 456.1 KiB | 00m00s [ 31/183] Installing python3-six-0:1.17 100% | 58.7 MiB/s | 120.3 KiB | 00m00s [ 32/183] Installing python3-array-api- 100% | 86.2 MiB/s | 529.3 KiB | 00m00s [ 33/183] Installing python3-array-api- 100% | 142.2 MiB/s | 1.4 MiB | 00m00s [ 34/183] Installing python3-dateutil-1 100% | 174.1 MiB/s | 891.5 KiB | 00m00s [ 35/183] Installing openblas-openmp-0: 100% | 416.1 MiB/s | 20.4 MiB | 00m00s [ 36/183] Installing flexiblas-netlib-0 100% | 244.7 MiB/s | 14.2 MiB | 00m00s [ 37/183] Installing flexiblas-0:3.5.0- 100% | 38.2 MiB/s | 39.2 KiB | 00m00s [ 38/183] Installing flexiblas-openblas 100% | 13.3 MiB/s | 68.0 KiB | 00m00s [ 39/183] Installing python3-numpy-1:2. 100% | 233.3 MiB/s | 36.6 MiB | 00m00s [ 40/183] Installing python3-numpy-f2py 100% | 64.1 MiB/s | 2.2 MiB | 00m00s [ 41/183] Installing python3-contourpy- 100% | 142.2 MiB/s | 873.5 KiB | 00m00s [ 42/183] Installing openblas-openmp64- 100% | 421.0 MiB/s | 20.2 MiB | 00m00s [ 43/183] Installing flexiblas-openblas 100% | 66.5 MiB/s | 68.0 KiB | 00m00s [ 44/183] Installing flexiblas-netlib64 100% | 245.7 MiB/s | 14.0 MiB | 00m00s [ 45/183] Installing arpack-0:3.9.1-9.f 100% | 180.9 MiB/s | 555.7 KiB | 00m00s [ 46/183] Installing armadillo12-0:12.8 100% | 143.8 MiB/s | 147.3 KiB | 00m00s [ 47/183] Installing libtheora-1:1.1.1- 100% | 229.9 MiB/s | 470.8 KiB | 00m00s [ 48/183] Installing openexr-libs-0:3.2 100% | 388.1 MiB/s | 6.6 MiB | 00m00s [ 49/183] Installing librttopo-0:1.1.0- 100% | 177.9 MiB/s | 546.4 KiB | 00m00s [ 50/183] Installing dejavu-sans-fonts- 100% | 367.2 MiB/s | 5.5 MiB | 00m00s [ 51/183] Installing abattis-cantarell- 100% | 94.9 MiB/s | 194.4 KiB | 00m00s [ 52/183] Installing python3-anyio-0:4. 100% | 165.1 MiB/s | 1.5 MiB | 00m00s [ 53/183] Installing python3-urllib3-0: 100% | 147.5 MiB/s | 1.2 MiB | 00m00s [ 54/183] Installing nss-softokn-freebl 100% | 245.0 MiB/s | 1.0 MiB | 00m00s [ 55/183] Installing nss-softokn-0:3.13 100% | 327.5 MiB/s | 2.3 MiB | 00m00s [ 56/183] Installing nss-sysinit-0:3.13 100% | 3.9 MiB/s | 71.1 KiB | 00m00s [ 57/183] Installing nss-0:3.131.0-1.fc 100% | 151.9 MiB/s | 2.0 MiB | 00m00s [ 58/183] Installing python3-flexcache- 100% | 29.6 MiB/s | 60.6 KiB | 00m00s [ 59/183] Installing python3-flexparser 100% | 130.4 MiB/s | 267.1 KiB | 00m00s [ 60/183] Installing python3-pydantic-c 100% | 307.8 MiB/s | 4.9 MiB | 00m00s [ 61/183] Installing libharu-0:2.4.5-2. 100% | 176.1 MiB/s | 1.8 MiB | 00m00s [ 62/183] Installing libtirpc-0:1.3.8-0 100% | 104.5 MiB/s | 214.0 KiB | 00m00s [ 63/183] Installing hdf-libs-0:4.3.0-5 100% | 235.6 MiB/s | 723.7 KiB | 00m00s [ 64/183] Installing uriparser-0:1.0.3- 100% | 13.3 MiB/s | 245.4 KiB | 00m00s [ 65/183] Installing libkml-0:1.3.0-58. 100% | 246.1 MiB/s | 1.2 MiB | 00m00s [ 66/183] Installing mariadb-connector- 100% | 26.6 MiB/s | 27.2 KiB | 00m00s [ 67/183] Installing mariadb-connector- 100% | 244.0 MiB/s | 1.0 MiB | 00m00s [ 68/183] Installing giflib-0:6.1.3-2.f 100% | 68.3 MiB/s | 139.8 KiB | 00m00s [ 69/183] Installing glib2-0:2.88.4-1.f 100% | 241.1 MiB/s | 15.9 MiB | 00m00s [ 70/183] Installing python3-fsspec-0:2 100% | 187.7 MiB/s | 2.1 MiB | 00m00s [ 71/183] Installing python3-dotenv-0:1 100% | 76.2 MiB/s | 156.0 KiB | 00m00s [ 72/183] Installing rply-0:1.1.4-11.fc 100% | 16.4 MiB/s | 318.7 KiB | 00m00s [ 73/183] Installing libX11-common-0:1. 100% | 91.2 MiB/s | 1.2 MiB | 00m00s [ 74/183] Installing graphite2-0:1.3.14 100% | 12.4 MiB/s | 241.5 KiB | 00m00s [ 75/183] Installing freetype-0:2.14.3- 100% | 171.9 MiB/s | 880.3 KiB | 00m00s [ 76/183] Installing harfbuzz-0:14.1.0- 100% | 267.3 MiB/s | 2.7 MiB | 00m00s [ 77/183] Installing gpgme-0:2.0.1-5.fc 100% | 37.3 MiB/s | 764.4 KiB | 00m00s [ 78/183] Installing gpgmepp-0:2.0.1-5. 100% | 224.4 MiB/s | 459.6 KiB | 00m00s [ 79/183] Installing pixman-0:0.46.2-3. 100% | 213.4 MiB/s | 655.4 KiB | 00m00s [ 80/183] Installing lzo-0:2.10-16.fc44 100% | 160.6 MiB/s | 164.4 KiB | 00m00s [ 81/183] Installing libXau-0:1.0.12-4. 100% | 119.5 MiB/s | 122.3 KiB | 00m00s [ 82/183] Installing libxcb-0:1.17.0-7. 100% | 270.4 MiB/s | 2.2 MiB | 00m00s [ 83/183] Installing libX11-0:1.8.13-3. 100% | 268.6 MiB/s | 1.3 MiB | 00m00s [ 84/183] Installing libXext-0:1.3.6-5. 100% | 143.5 MiB/s | 147.0 KiB | 00m00s [ 85/183] Installing libXrender-0:0.9.1 100% | 69.5 MiB/s | 71.1 KiB | 00m00s [ 86/183] Installing fribidi-0:1.0.16-4 100% | 13.5 MiB/s | 248.5 KiB | 00m00s [ 87/183] Installing libraqm-0:0.10.1-4 100% | 68.0 MiB/s | 69.6 KiB | 00m00s [ 88/183] Installing python3-olefile-0: 100% | 170.8 MiB/s | 349.8 KiB | 00m00s [ 89/183] Installing libimagequant-0:4. 100% | 219.3 MiB/s | 673.7 KiB | 00m00s [ 90/183] Installing python3-kiwisolver 100% | 32.3 MiB/s | 165.2 KiB | 00m00s [ 91/183] Installing python3-fonttools- 100% | 254.4 MiB/s | 19.6 MiB | 00m00s [ 92/183] Installing python3-charset-no 100% | 17.9 MiB/s | 366.4 KiB | 00m00s [ 93/183] Installing python3-requests-0 100% | 119.5 MiB/s | 489.5 KiB | 00m00s [ 94/183] Installing python3-pooch-0:1. 100% | 59.8 MiB/s | 673.1 KiB | 00m00s [ 95/183] Installing python3-scipy-0:1. 100% | 265.7 MiB/s | 63.8 MiB | 00m00s [ 96/183] Installing libicu-0:77.1-3.fc 100% | 335.2 MiB/s | 36.5 MiB | 00m00s [ 97/183] Installing libraw1394-0:2.1.2 100% | 16.1 MiB/s | 313.6 KiB | 00m00s [ 98/183] Installing libdc1394-0:2.2.7- 100% | 185.8 MiB/s | 380.6 KiB | 00m00s [ 99/183] Installing expatpp-0:0-0.39.2 100% | 77.3 MiB/s | 79.2 KiB | 00m00s [100/183] Installing pugixml-0:1.16-1.f 100% | 130.2 MiB/s | 266.7 KiB | 00m00s [101/183] Installing proj-data-0:9.8.1- 100% | 456.8 MiB/s | 10.1 MiB | 00m00s [102/183] Installing jbigkit-libs-0:2.1 100% | 178.9 MiB/s | 183.2 KiB | 00m00s [103/183] Installing libtiff-0:4.7.2-3. 100% | 215.4 MiB/s | 661.7 KiB | 00m00s [104/183] Installing proj-0:9.8.1-1.fc4 100% | 140.2 MiB/s | 4.3 MiB | 00m00s [105/183] Installing libgeotiff-0:1.7.4 100% | 24.2 MiB/s | 521.1 KiB | 00m00s [106/183] Installing vxl-0:3.5.0-20.fc4 100% | 288.1 MiB/s | 56.5 MiB | 00m00s [107/183] Installing libspatialite-0:5. 100% | 394.2 MiB/s | 15.0 MiB | 00m00s [108/183] Installing dcmtk-0:3.7.0^2026 100% | 322.2 MiB/s | 43.2 MiB | 00m00s [109/183] Installing python3-pillow-0:1 100% | 213.8 MiB/s | 4.7 MiB | 00m00s [110/183] Installing google-noto-fonts- 100% | 18.1 MiB/s | 18.5 KiB | 00m00s [111/183] Installing google-noto-sans-v 100% | 231.9 MiB/s | 1.4 MiB | 00m00s [112/183] Installing default-fonts-core 100% | 2.5 MiB/s | 18.2 KiB | 00m00s [113/183] Installing xml-common-0:0.6.3 100% | 39.6 MiB/s | 81.1 KiB | 00m00s [114/183] Installing fontconfig-0:2.17. 100% | 1.2 MiB/s | 1.2 MiB | 00m01s [115/183] Installing cairo-0:1.18.6-1.f 100% | 255.0 MiB/s | 1.8 MiB | 00m00s [116/183] Installing python3-cairo-0:1. 100% | 169.3 MiB/s | 520.1 KiB | 00m00s [117/183] Installing boost-container-0: 100% | 68.7 MiB/s | 70.3 KiB | 00m00s [118/183] Installing boost-program-opti 100% | 130.9 MiB/s | 268.2 KiB | 00m00s [119/183] Installing abseil-cpp-0:20260 100% | 312.9 MiB/s | 6.6 MiB | 00m00s [120/183] Installing re2-2:20251105-4.f 100% | 195.4 MiB/s | 600.2 KiB | 00m00s [121/183] Installing protobuf-0:3.19.6- 100% | 311.9 MiB/s | 3.1 MiB | 00m00s [122/183] Installing liborc2-0:2.2.2-2. 100% | 310.7 MiB/s | 1.9 MiB | 00m00s [123/183] Installing libarrow-0:23.0.1- 100% | 355.6 MiB/s | 11.4 MiB | 00m00s [124/183] Installing poppler-data-0:0.4 100% | 288.1 MiB/s | 12.4 MiB | 00m00s [125/183] Installing poppler-0:26.01.0- 100% | 301.3 MiB/s | 3.6 MiB | 00m00s [126/183] Installing thrift-0:0.20.0-9. 100% | 144.2 MiB/s | 4.8 MiB | 00m00s [127/183] Installing parquet-libs-0:23. 100% | 353.2 MiB/s | 3.5 MiB | 00m00s [128/183] Installing utf8proc-0:2.11.3- 100% | 202.6 MiB/s | 414.9 KiB | 00m00s [129/183] Installing libarrow-compute-l 100% | 407.4 MiB/s | 11.0 MiB | 00m00s [130/183] Installing libarrow-acero-lib 100% | 257.8 MiB/s | 1.3 MiB | 00m00s [131/183] Installing libarrow-dataset-l 100% | 271.4 MiB/s | 1.4 MiB | 00m00s [132/183] Installing xerces-c-0:3.3.0-9 100% | 345.3 MiB/s | 3.8 MiB | 00m00s [133/183] Installing unixODBC-0:2.3.14- 100% | 44.3 MiB/s | 1.3 MiB | 00m00s [134/183] Installing muParser-0:2.3.5-5 100% | 180.4 MiB/s | 554.1 KiB | 00m00s [135/183] Installing libpq-0:18.0-4.fc4 100% | 205.5 MiB/s | 1.0 MiB | 00m00s [136/183] Installing libgta-0:1.2.1-17. 100% | 93.1 MiB/s | 95.3 KiB | 00m00s [137/183] Installing cfitsio-0:4.6.3-2. 100% | 290.8 MiB/s | 1.7 MiB | 00m00s [138/183] Installing libzip-0:1.11.4-3. 100% | 133.5 MiB/s | 136.7 KiB | 00m00s [139/183] Installing netcdf-0:4.9.3-2.f 100% | 112.0 MiB/s | 3.1 MiB | 00m00s [140/183] Installing gdal-libs-0:3.12.4 100% | 288.4 MiB/s | 30.3 MiB | 00m00s [141/183] Installing libminc-0:2.4.03-3 100% | 163.9 MiB/s | 671.4 KiB | 00m00s [142/183] Installing viskores-0:1.2.0-3 100% | 486.6 MiB/s | 117.8 MiB | 00m00s [143/183] Installing jsoncpp-0:1.9.6-3. 100% | 133.4 MiB/s | 273.3 KiB | 00m00s [144/183] Installing fmt-0:11.2.0-4.fc4 100% | 85.9 MiB/s | 263.9 KiB | 00m00s [145/183] Installing vtk-0:9.7.0-6.fc44 100% | 433.7 MiB/s | 242.4 MiB | 00m01s [146/183] Installing CharLS-0:2.4.3-2.f 100% | 170.1 MiB/s | 348.5 KiB | 00m00s [147/183] Installing gdcm-0:3.0.24-17.f 100% | 372.2 MiB/s | 8.2 MiB | 00m00s [148/183] Installing python3-h11-0:0.16 100% | 93.7 MiB/s | 287.9 KiB | 00m00s [149/183] Installing python3-httpcore-0 100% | 142.3 MiB/s | 874.4 KiB | 00m00s [150/183] Installing python3-httpx-0:0. 100% | 196.8 MiB/s | 1.0 MiB | 00m00s [151/183] Installing fftw-libs-single-0 100% | 265.4 MiB/s | 1.9 MiB | 00m00s [152/183] Installing fftw-libs-double-0 100% | 256.5 MiB/s | 1.8 MiB | 00m00s [153/183] Installing double-conversion- 100% | 69.7 MiB/s | 142.8 KiB | 00m00s [154/183] Installing InsightToolkit5-0: 100% | 423.2 MiB/s | 32.6 MiB | 00m00s [155/183] Installing simpleitk-0:2.5.5- 100% | 506.0 MiB/s | 278.8 MiB | 00m01s [156/183] Installing libyaml-0:0.2.5-18 100% | 132.5 MiB/s | 135.7 KiB | 00m00s [157/183] Installing python3-pyyaml-0:6 100% | 132.0 MiB/s | 811.0 KiB | 00m00s [158/183] Installing python3-xmltodict- 100% | 57.1 MiB/s | 58.5 KiB | 00m00s [159/183] Installing python3-filelock-0 100% | 50.9 MiB/s | 104.3 KiB | 00m00s [160/183] Installing python3-click-1:8. 100% | 208.0 MiB/s | 1.2 MiB | 00m00s [161/183] Installing python3-annotated- 100% | 43.1 MiB/s | 88.2 KiB | 00m00s [162/183] Installing python3-pydantic-0 100% | 233.3 MiB/s | 5.1 MiB | 00m00s [163/183] Installing python3-pyparsing- 100% | 205.9 MiB/s | 1.0 MiB | 00m00s [164/183] Installing python3-matplotlib 100% | 316.6 MiB/s | 7.9 MiB | 00m00s [165/183] Installing python3-cycler-0:0 100% | 39.3 MiB/s | 40.3 KiB | 00m00s [166/183] Installing python3-markupsafe 100% | 59.4 MiB/s | 121.7 KiB | 00m00s [167/183] Installing python3-cached_pro 100% | 37.3 MiB/s | 38.2 KiB | 00m00s [168/183] Installing liblzf-0:3.6-34.fc 100% | 8.4 MiB/s | 155.6 KiB | 00m00s [169/183] Installing python3-h5py-0:3.1 100% | 252.1 MiB/s | 4.5 MiB | 00m00s [170/183] Installing python3-tqdm-0:4.6 100% | 24.5 MiB/s | 601.2 KiB | 00m00s [171/183] Installing python3-huggingfac 100% | 134.7 MiB/s | 6.6 MiB | 00m00s [172/183] Installing python3-pymatreade 100% | 34.3 MiB/s | 70.2 KiB | 00m00s [173/183] Installing python3-jinja2-0:3 100% | 206.1 MiB/s | 3.1 MiB | 00m00s [174/183] Installing python3-matplotlib 100% | 293.5 MiB/s | 32.0 MiB | 00m00s [175/183] Installing python3-numpydanti 100% | 90.7 MiB/s | 650.0 KiB | 00m00s [176/183] Installing python3-pydantic-s 100% | 111.9 MiB/s | 573.0 KiB | 00m00s [177/183] Installing python3-simpleitk- 100% | 482.7 MiB/s | 15.0 MiB | 00m00s [178/183] Installing python3-pint-0:0.2 100% | 93.7 MiB/s | 3.5 MiB | 00m00s [179/183] Installing python3-array-api- 100% | 100.1 MiB/s | 717.6 KiB | 00m00s [180/183] Installing python3-ipax-0:0.1 100% | 214.4 MiB/s | 3.0 MiB | 00m00s [181/183] Installing python3-safetensor 100% | 181.8 MiB/s | 931.0 KiB | 00m00s [182/183] Installing python3-regex-0:20 100% | 262.1 MiB/s | 2.1 MiB | 00m00s [183/183] Installing python3-pydicom-0: 100% | 67.2 MiB/s | 14.0 MiB | 00m00s Warning: skipped OpenPGP checks for 12 packages from repository: copr_base Complete! Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.PGHMMx + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + cd pyradplan-0.8.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + RPM_TOXENV=py314 + FEDORA=44 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 80.10.2) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 9.2.2) toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running egg_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running dist_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/pyradplan-0.8.0.dist-info' Handling scipy>=1.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: scipy>=1.13.0 (installed: scipy 1.16.2) Handling numpy>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: numpy>=2.0 (installed: numpy 2.4.6) Handling array_api_compat from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_compat (installed: array_api_compat 1.15.0) Handling array_api_strict from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_strict (installed: array_api_strict 2.0.1) Handling array_api_extra from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_extra (installed: array_api_extra 0.11.5) Handling ipax>=0.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: ipax>=0.13.0 (installed: ipax 0.13.0) Handling pymatreader>=1.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pymatreader>=1.0.0 (installed: pymatreader 1.3.1) Handling h5py>=3.11.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: h5py>=3.11.0 (installed: h5py 3.15.1) Handling regex>=2024.5.15 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: regex>=2024.5.15 (installed: regex 2026.9.10) Handling pydicom>=2.4.4 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydicom>=2.4.4 (installed: pydicom 3.0.2) Handling matplotlib>=3.9.2 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: matplotlib>=3.9.2 (installed: matplotlib 3.10.8) Handling pydantic<2.20,>=2.10 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydantic<2.20,>=2.10 (installed: pydantic 2.12.5) Handling pydantic-settings<3.0,>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydantic-settings<3.0,>=2.0 (installed: pydantic-settings 2.15.0) Handling numpydantic>=1.6.9 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: numpydantic>=1.6.9 (installed: numpydantic 2.0.0) Handling SimpleITK>=2.4.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: SimpleITK>=2.4.0 Handling tqdm>=4.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: tqdm>=4.0.0 (installed: tqdm 4.69.0) Handling pint>=0.24.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pint>=0.24.0 (installed: pint 0.25.2) Handling jinja2 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: jinja2 (installed: jinja2 3.1.6) Handling huggingface_hub>=0.23 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: huggingface_hub>=0.23 (installed: huggingface_hub 1.24.0) Handling safetensors from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: safetensors (installed: safetensors 0.7.0) Handling matlabengine; extra == "matlab" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: matlabengine; extra == "matlab" Handling oct2py; extra == "octave" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: oct2py; extra == "octave" Handling pyside6-essentials<6.12,>=6.4; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyside6-essentials<6.12,>=6.4; extra == "gui" Handling pyqtgraph>=0.12.0; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyqtgraph>=0.12.0; extra == "gui" Handling contourpy>=1.0.1; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: contourpy>=1.0.1; extra == "gui" Handling numba>=0.61.0; extra == "numba" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numba>=0.61.0; extra == "numba" Handling torch>=2.0; extra == "torch" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: torch>=2.0; extra == "torch" Handling cupy>=13.0; extra == "cupy" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: cupy>=13.0; extra == "cupy" Handling jax>=0.4.35; extra == "jax" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jax>=0.4.35; extra == "jax" Handling line_profiler>=4.0; extra == "profiling" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: line_profiler>=4.0; extra == "profiling" Handling pytest; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest; extra == "dev" Handling coverage; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: coverage; extra == "dev" Handling pytest-cov; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-cov; extra == "dev" Handling pytest-benchmark; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-benchmark; extra == "dev" Handling pre-commit; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pre-commit; extra == "dev" Handling ruff<0.18; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: ruff<0.18; extra == "dev" Handling sphinx; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx; extra == "dev" Handling numpydoc; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numpydoc; extra == "dev" Handling pydata-sphinx-theme; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pydata-sphinx-theme; extra == "dev" Handling sphinx-design; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-design; extra == "dev" Handling autodoc_pydantic; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: autodoc_pydantic; extra == "dev" Handling sphinx-autodoc-typehints; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-autodoc-typehints; extra == "dev" Handling myst-nb; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: myst-nb; extra == "dev" Handling jupytext; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jupytext; extra == "dev" + cat /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires + rm -rfv pyradplan-0.8.0.dist-info/ removed 'pyradplan-0.8.0.dist-info/licenses/LICENSE' removed directory 'pyradplan-0.8.0.dist-info/licenses' removed 'pyradplan-0.8.0.dist-info/METADATA' removed 'pyradplan-0.8.0.dist-info/top_level.txt' removed 'pyradplan-0.8.0.dist-info/entry_points.txt' removed directory 'pyradplan-0.8.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc44.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: updates 100% | 24.7 KiB/s | 5.3 KiB | 00m00s fedora 100% | 43.3 KiB/s | 9.3 KiB | 00m00s Copr repository 100% | 8.3 KiB/s | 1.5 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc44.noarch" is already installed. Package "python3-devel-3.14.10-1.fc44.aarch64" is already installed. Package "python3-pytest-8.4.2-2.fc44.noarch" is already installed. Package "python3-array-api-compat-1.15.0-1.fc44.noarch" is already installed. Package "python3-array-api-extra-0.11.5-1.fc44.noarch" is already installed. Package "python3-array-api-strict-2.0.1-8.fc44.noarch" is already installed. Package "python3-h5py-3.15.1-3.fc44.aarch64" is already installed. Package "python3-huggingface-hub-1.24.0-1.fc44.noarch" is already installed. Package "python3-ipax-0.13.0-1.fc44.noarch" is already installed. Package "python3-jinja2-3.1.6-7.fc44.noarch" is already installed. Package "python3-matplotlib-3.10.8-2.fc44.aarch64" is already installed. Package "python3-numpy-1:2.4.6-1.fc44.aarch64" is already installed. Package "python3-numpydantic-2.0.0-1.fc44.noarch" is already installed. Package "python3-packaging-25.0-8.fc44.noarch" is already installed. Package "python3-pint-0.25.2-2.fc44.noarch" is already installed. Package "python3-pip-26.0.1-3.fc44.noarch" is already installed. Package "python3-pydicom-3.0.2-1.fc44.noarch" is already installed. Package "python3-pymatreader-1.3.1-1.fc44.noarch" is already installed. Package "python3-regex-2026.9.10-1.fc44.aarch64" is already installed. Nothing to do. Package "python3-safetensors-0.7.0-1.fc44.aarch64" is already installed. Package "python3-scipy-1.16.2-3.fc44.aarch64" is already installed. Package "python3-setuptools-80.10.2-3.fc44.noarch" is already installed. Package "python3-setuptools_scm-9.2.2-5.fc44.noarch" is already installed. Package "python3-simpleitk-2.5.5-12.fc44.aarch64" is already installed. Package "python3-tqdm-4.69.0-2.fc44.noarch" is already installed. Building target platforms: aarch64 Building for target aarch64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.CUFj9A + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + cd pyradplan-0.8.0 + echo pyproject-rpm-macros + echo python3-devel + echo 'python3dist(packaging)' + echo 'python3dist(pip) >= 19' + '[' -f pyproject.toml ']' + echo '(python3dist(tomli) if python3-devel < 3.11)' + rm -rfv '*.dist-info/' + '[' -f /usr/bin/python3 ']' + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + echo -n + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + RPM_TOXENV=py314 + FEDORA=44 + HOSTNAME=rpmbuild + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_buildrequires.py --generate-extras --python3_pkgversion 3 --wheeldir /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir --output /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 80.10.2) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 9.2.2) toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running egg_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running dist_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/pyradplan-0.8.0.dist-info' Handling scipy>=1.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: scipy>=1.13.0 (installed: scipy 1.16.2) Handling numpy>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: numpy>=2.0 (installed: numpy 2.4.6) Handling array_api_compat from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_compat (installed: array_api_compat 1.15.0) Handling array_api_strict from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_strict (installed: array_api_strict 2.0.1) Handling array_api_extra from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: array_api_extra (installed: array_api_extra 0.11.5) Handling ipax>=0.13.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: ipax>=0.13.0 (installed: ipax 0.13.0) Handling pymatreader>=1.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pymatreader>=1.0.0 (installed: pymatreader 1.3.1) Handling h5py>=3.11.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: h5py>=3.11.0 (installed: h5py 3.15.1) Handling regex>=2024.5.15 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: regex>=2024.5.15 (installed: regex 2026.9.10) Handling pydicom>=2.4.4 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydicom>=2.4.4 (installed: pydicom 3.0.2) Handling matplotlib>=3.9.2 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: matplotlib>=3.9.2 (installed: matplotlib 3.10.8) Handling pydantic<2.20,>=2.10 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydantic<2.20,>=2.10 (installed: pydantic 2.12.5) Handling pydantic-settings<3.0,>=2.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pydantic-settings<3.0,>=2.0 (installed: pydantic-settings 2.15.0) Handling numpydantic>=1.6.9 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: numpydantic>=1.6.9 (installed: numpydantic 2.0.0) Handling SimpleITK>=2.4.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement not satisfied: SimpleITK>=2.4.0 Handling tqdm>=4.0.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: tqdm>=4.0.0 (installed: tqdm 4.69.0) Handling pint>=0.24.0 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: pint>=0.24.0 (installed: pint 0.25.2) Handling jinja2 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: jinja2 (installed: jinja2 3.1.6) Handling huggingface_hub>=0.23 from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: huggingface_hub>=0.23 (installed: huggingface_hub 1.24.0) Handling safetensors from hook generated metadata: Requires-Dist (pyradplan) Requirement satisfied: safetensors (installed: safetensors 0.7.0) Handling matlabengine; extra == "matlab" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: matlabengine; extra == "matlab" Handling oct2py; extra == "octave" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: oct2py; extra == "octave" Handling pyside6-essentials<6.12,>=6.4; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyside6-essentials<6.12,>=6.4; extra == "gui" Handling pyqtgraph>=0.12.0; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pyqtgraph>=0.12.0; extra == "gui" Handling contourpy>=1.0.1; extra == "gui" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: contourpy>=1.0.1; extra == "gui" Handling numba>=0.61.0; extra == "numba" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numba>=0.61.0; extra == "numba" Handling torch>=2.0; extra == "torch" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: torch>=2.0; extra == "torch" Handling cupy>=13.0; extra == "cupy" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: cupy>=13.0; extra == "cupy" Handling jax>=0.4.35; extra == "jax" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jax>=0.4.35; extra == "jax" Handling line_profiler>=4.0; extra == "profiling" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: line_profiler>=4.0; extra == "profiling" Handling pytest; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest; extra == "dev" Handling coverage; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: coverage; extra == "dev" Handling pytest-cov; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-cov; extra == "dev" Handling pytest-benchmark; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pytest-benchmark; extra == "dev" Handling pre-commit; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pre-commit; extra == "dev" Handling ruff<0.18; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: ruff<0.18; extra == "dev" Handling sphinx; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx; extra == "dev" Handling numpydoc; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: numpydoc; extra == "dev" Handling pydata-sphinx-theme; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: pydata-sphinx-theme; extra == "dev" Handling sphinx-design; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-design; extra == "dev" Handling autodoc_pydantic; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: autodoc_pydantic; extra == "dev" Handling sphinx-autodoc-typehints; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: sphinx-autodoc-typehints; extra == "dev" Handling myst-nb; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: myst-nb; extra == "dev" Handling jupytext; extra == "dev" from hook generated metadata: Requires-Dist (pyradplan) Ignoring alien requirement: jupytext; extra == "dev" + cat /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-buildrequires + rm -rfv pyradplan-0.8.0.dist-info/ removed 'pyradplan-0.8.0.dist-info/licenses/LICENSE' removed directory 'pyradplan-0.8.0.dist-info/licenses' removed 'pyradplan-0.8.0.dist-info/METADATA' removed 'pyradplan-0.8.0.dist-info/entry_points.txt' removed 'pyradplan-0.8.0.dist-info/top_level.txt' removed directory 'pyradplan-0.8.0.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.N9MhiU + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd pyradplan-0.8.0 + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + VALAFLAGS=-g + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + LT_SYS_LIBRARY_PATH=/usr/lib64: + CC=gcc + CXX=g++ + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + /usr/bin/python3 -Bs /usr/lib/rpm/redhat/pyproject_wheel.py /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir Processing ./. Preparing metadata (pyproject.toml): started Running command Preparing metadata (pyproject.toml) toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running dist_info creating /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info writing /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/PKG-INFO writing dependency_links to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/dependency_links.txt writing entry points to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/entry_points.txt writing requirements to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/requires.txt writing top-level names to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/top_level.txt writing manifest file '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/SOURCES.txt' reading manifest file '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyRadPlan.egg-info/SOURCES.txt' creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-_xj5nvr3/pyradplan-0.8.0.dist-info' Preparing metadata (pyproject.toml): finished with status 'done' Building wheels for collected packages: pyRadPlan Building wheel for pyRadPlan (pyproject.toml): started Running command Building wheel for pyRadPlan (pyproject.toml) toml section missing PosixPath('pyproject.toml') does not contain a tool.setuptools_scm section /usr/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /usr/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: BSD License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running bdist_wheel running build running build_py creating build/lib/pyRadPlan copying pyRadPlan/_settings.py -> build/lib/pyRadPlan copying pyRadPlan/_lazy.py -> build/lib/pyRadPlan copying pyRadPlan/__init__.py -> build/lib/pyRadPlan creating build/lib/pyRadPlan/visualization copying pyRadPlan/visualization/_plot_slice.py -> build/lib/pyRadPlan/visualization copying pyRadPlan/visualization/_plot_multiple_slices.py -> build/lib/pyRadPlan/visualization copying pyRadPlan/visualization/__init__.py -> build/lib/pyRadPlan/visualization creating build/lib/pyRadPlan/util copying pyRadPlan/util/openmp.py -> build/lib/pyRadPlan/util copying pyRadPlan/util/logging_utils.py -> build/lib/pyRadPlan/util copying pyRadPlan/util/keyboard_listener.py -> build/lib/pyRadPlan/util copying pyRadPlan/util/helpers.py -> build/lib/pyRadPlan/util copying pyRadPlan/util/_jupyter.py -> build/lib/pyRadPlan/util copying pyRadPlan/util/__init__.py -> build/lib/pyRadPlan/util creating build/lib/pyRadPlan/stf copying pyRadPlan/stf/_steeringinformation.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_ray.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_rangeshifter.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_presets.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_generate_stf.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_exceptions.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_beamlet.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/_beam.py -> build/lib/pyRadPlan/stf copying pyRadPlan/stf/__init__.py -> build/lib/pyRadPlan/stf creating build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_worst_case.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_set.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_random.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_nominal.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_legacy.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_importance.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_gridded.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_explicit.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_distributions.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_dimensions.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/_base.py -> build/lib/pyRadPlan/scenarios copying pyRadPlan/scenarios/__init__.py -> build/lib/pyRadPlan/scenarios creating build/lib/pyRadPlan/raytracer copying pyRadPlan/raytracer/_siddon.py -> build/lib/pyRadPlan/raytracer copying pyRadPlan/raytracer/_kernels_numba.py -> build/lib/pyRadPlan/raytracer copying pyRadPlan/raytracer/_kernels.py -> build/lib/pyRadPlan/raytracer copying pyRadPlan/raytracer/_base.py -> build/lib/pyRadPlan/raytracer copying pyRadPlan/raytracer/__init__.py -> build/lib/pyRadPlan/raytracer creating build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_sqrt_beta_dose.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_resolver.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_rbe_x_dose.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_let_x_dose.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_let.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_effect.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_dose.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_base.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/_alpha_dose.py -> build/lib/pyRadPlan/quantities copying pyRadPlan/quantities/__init__.py -> build/lib/pyRadPlan/quantities creating build/lib/pyRadPlan/plan copying pyRadPlan/plan/_plans.py -> build/lib/pyRadPlan/plan copying pyRadPlan/plan/__init__.py -> build/lib/pyRadPlan/plan creating build/lib/pyRadPlan/optimization copying pyRadPlan/optimization/_fluence_optimization.py -> build/lib/pyRadPlan/optimization copying pyRadPlan/optimization/__init__.py -> build/lib/pyRadPlan/optimization creating build/lib/pyRadPlan/matRad copying pyRadPlan/matRad/_octave.py -> build/lib/pyRadPlan/matRad copying pyRadPlan/matRad/_matlab.py -> build/lib/pyRadPlan/matRad copying pyRadPlan/matRad/_engine.py -> build/lib/pyRadPlan/matRad copying pyRadPlan/matRad/__init__.py -> build/lib/pyRadPlan/matRad creating build/lib/pyRadPlan/machines copying pyRadPlan/machines/_validate.py -> build/lib/pyRadPlan/machines copying pyRadPlan/machines/_load.py -> build/lib/pyRadPlan/machines copying pyRadPlan/machines/__init__.py -> build/lib/pyRadPlan/machines creating build/lib/pyRadPlan/io copying pyRadPlan/io/_load_save.py -> build/lib/pyRadPlan/io copying pyRadPlan/io/_helpers.py -> build/lib/pyRadPlan/io copying pyRadPlan/io/_factory.py -> build/lib/pyRadPlan/io copying pyRadPlan/io/__init__.py -> build/lib/pyRadPlan/io creating build/lib/pyRadPlan/gui copying pyRadPlan/gui/workspace.py -> build/lib/pyRadPlan/gui copying pyRadPlan/gui/apps.py -> build/lib/pyRadPlan/gui copying pyRadPlan/gui/__init__.py -> build/lib/pyRadPlan/gui creating build/lib/pyRadPlan/geometry copying pyRadPlan/geometry/lps.py -> build/lib/pyRadPlan/geometry copying pyRadPlan/geometry/__init__.py -> build/lib/pyRadPlan/geometry creating build/lib/pyRadPlan/dose copying pyRadPlan/dose/_calc_dose.py -> build/lib/pyRadPlan/dose copying pyRadPlan/dose/__init__.py -> build/lib/pyRadPlan/dose creating build/lib/pyRadPlan/dij copying pyRadPlan/dij/_dij.py -> build/lib/pyRadPlan/dij copying pyRadPlan/dij/_compose_beam_dijs.py -> build/lib/pyRadPlan/dij copying pyRadPlan/dij/__init__.py -> build/lib/pyRadPlan/dij creating build/lib/pyRadPlan/ct copying pyRadPlan/ct/_hlut.py -> build/lib/pyRadPlan/ct copying pyRadPlan/ct/_ct.py -> build/lib/pyRadPlan/ct copying pyRadPlan/ct/__init__.py -> build/lib/pyRadPlan/ct creating build/lib/pyRadPlan/cst copying pyRadPlan/cst/_voi.py -> build/lib/pyRadPlan/cst copying pyRadPlan/cst/_cst.py -> build/lib/pyRadPlan/cst copying pyRadPlan/cst/__init__.py -> build/lib/pyRadPlan/cst creating build/lib/pyRadPlan/core copying pyRadPlan/core/resample.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/np2sitk.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/datamodel.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_units.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_progress.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_paths.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_grids.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_exceptions.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_configurable.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/_base_data.py -> build/lib/pyRadPlan/core copying pyRadPlan/core/__init__.py -> build/lib/pyRadPlan/core creating build/lib/pyRadPlan/biology copying pyRadPlan/biology/__init__.py -> build/lib/pyRadPlan/biology creating build/lib/pyRadPlan/analysis copying pyRadPlan/analysis/_units.py -> build/lib/pyRadPlan/analysis copying pyRadPlan/analysis/_qi.py -> build/lib/pyRadPlan/analysis copying pyRadPlan/analysis/_dvh_plot.py -> build/lib/pyRadPlan/analysis copying pyRadPlan/analysis/_dvh.py -> build/lib/pyRadPlan/analysis copying pyRadPlan/analysis/__init__.py -> build/lib/pyRadPlan/analysis creating build/lib/pyRadPlan/ai copying pyRadPlan/ai/__init__.py -> build/lib/pyRadPlan/ai creating build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_vhee.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_photons.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_ions.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_factory.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_externalbeam.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/_base.py -> build/lib/pyRadPlan/stf/generators copying pyRadPlan/stf/generators/__init__.py -> build/lib/pyRadPlan/stf/generators creating build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/_scipy_solver.py -> build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/_ipopt.py -> build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/_ipax_solver.py -> build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/_factory.py -> build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/_base_solvers.py -> build/lib/pyRadPlan/optimization/solvers copying pyRadPlan/optimization/solvers/__init__.py -> build/lib/pyRadPlan/optimization/solvers creating build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_voxel_worst_case.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_utils.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_terms.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_smooth_max.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_objective_worst_case.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_none.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_factory.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_expected_value.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_expected_quantity.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_composite_worst_case.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/_base.py -> build/lib/pyRadPlan/optimization/robustness copying pyRadPlan/optimization/robustness/__init__.py -> build/lib/pyRadPlan/optimization/robustness creating build/lib/pyRadPlan/optimization/problems copying pyRadPlan/optimization/problems/_simple_least_squares.py -> build/lib/pyRadPlan/optimization/problems copying pyRadPlan/optimization/problems/_optiprob.py -> build/lib/pyRadPlan/optimization/problems copying pyRadPlan/optimization/problems/_nonlin_fluence.py -> build/lib/pyRadPlan/optimization/problems copying pyRadPlan/optimization/problems/_factory.py -> build/lib/pyRadPlan/optimization/problems copying pyRadPlan/optimization/problems/__init__.py -> build/lib/pyRadPlan/optimization/problems creating build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_variance.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_std.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_squared_under.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_squared_over.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_squared_mimicking.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_squared_dev.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_objective.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_min_dvh.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_mean.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_max_dvh.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_factory.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/_eud.py -> build/lib/pyRadPlan/optimization/objectives copying pyRadPlan/optimization/objectives/__init__.py -> build/lib/pyRadPlan/optimization/objectives creating build/lib/pyRadPlan/machines/photons copying pyRadPlan/machines/photons/_svd_kernel.py -> build/lib/pyRadPlan/machines/photons copying pyRadPlan/machines/photons/_linac.py -> build/lib/pyRadPlan/machines/photons copying pyRadPlan/machines/photons/_calculate_machine_scale.py -> build/lib/pyRadPlan/machines/photons copying pyRadPlan/machines/photons/_base.py -> build/lib/pyRadPlan/machines/photons copying pyRadPlan/machines/photons/__init__.py -> build/lib/pyRadPlan/machines/photons creating build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_vhee.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_ions.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_beam_fragment_spectrum.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_beam_focus.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_beam_energy.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_beam_emittance.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_beam_cutoff.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/_base.py -> build/lib/pyRadPlan/machines/particles copying pyRadPlan/machines/particles/__init__.py -> build/lib/pyRadPlan/machines/particles creating build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/_internal_beam.py -> build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/_factory.py -> build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/_external_beam.py -> build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/_beam_modifier.py -> build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/_base.py -> build/lib/pyRadPlan/machines/base copying pyRadPlan/machines/base/__init__.py -> build/lib/pyRadPlan/machines/base creating build/lib/pyRadPlan/machines/particles/kernel copying pyRadPlan/machines/particles/kernel/_vhee.py -> build/lib/pyRadPlan/machines/particles/kernel copying pyRadPlan/machines/particles/kernel/_ions.py -> build/lib/pyRadPlan/machines/particles/kernel copying pyRadPlan/machines/particles/kernel/_base.py -> build/lib/pyRadPlan/machines/particles/kernel copying pyRadPlan/machines/particles/kernel/__init__.py -> build/lib/pyRadPlan/machines/particles/kernel creating build/lib/pyRadPlan/io/sitk_based copying pyRadPlan/io/sitk_based/_binary_import.py -> build/lib/pyRadPlan/io/sitk_based copying pyRadPlan/io/sitk_based/__init__.py -> build/lib/pyRadPlan/io/sitk_based creating build/lib/pyRadPlan/io/pickle copying pyRadPlan/io/pickle/_importer.py -> build/lib/pyRadPlan/io/pickle copying pyRadPlan/io/pickle/_handler.py -> build/lib/pyRadPlan/io/pickle copying pyRadPlan/io/pickle/_exporter.py -> build/lib/pyRadPlan/io/pickle copying pyRadPlan/io/pickle/__init__.py -> build/lib/pyRadPlan/io/pickle creating build/lib/pyRadPlan/io/npz copying pyRadPlan/io/npz/_serialize.py -> build/lib/pyRadPlan/io/npz copying pyRadPlan/io/npz/_importer.py -> build/lib/pyRadPlan/io/npz copying pyRadPlan/io/npz/_handler.py -> build/lib/pyRadPlan/io/npz copying pyRadPlan/io/npz/_exporter.py -> build/lib/pyRadPlan/io/npz copying pyRadPlan/io/npz/__init__.py -> build/lib/pyRadPlan/io/npz creating build/lib/pyRadPlan/io/matlab copying pyRadPlan/io/matlab/_matfile.py -> build/lib/pyRadPlan/io/matlab copying pyRadPlan/io/matlab/_importer.py -> build/lib/pyRadPlan/io/matlab copying pyRadPlan/io/matlab/_handler.py -> build/lib/pyRadPlan/io/matlab copying pyRadPlan/io/matlab/_exporter.py -> build/lib/pyRadPlan/io/matlab copying pyRadPlan/io/matlab/__init__.py -> build/lib/pyRadPlan/io/matlab creating build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_importer.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_import_dose.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_import_ct.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_import_cst.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_helpers.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_handler.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_exporter.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_export_seg.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_export_dose.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_export_ct.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_export_cst.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/_export_common.py -> build/lib/pyRadPlan/io/dicom copying pyRadPlan/io/dicom/__init__.py -> build/lib/pyRadPlan/io/dicom creating build/lib/pyRadPlan/io/base copying pyRadPlan/io/base/_importer.py -> build/lib/pyRadPlan/io/base copying pyRadPlan/io/base/_exporter.py -> build/lib/pyRadPlan/io/base copying pyRadPlan/io/base/__init__.py -> build/lib/pyRadPlan/io/base creating build/lib/pyRadPlan/io/sitk_based/nrrd copying pyRadPlan/io/sitk_based/nrrd/__init__.py -> build/lib/pyRadPlan/io/sitk_based/nrrd creating build/lib/pyRadPlan/io/sitk_based/nifti copying pyRadPlan/io/sitk_based/nifti/__init__.py -> build/lib/pyRadPlan/io/sitk_based/nifti creating build/lib/pyRadPlan/io/sitk_based/meta_image copying pyRadPlan/io/sitk_based/meta_image/__init__.py -> build/lib/pyRadPlan/io/sitk_based/meta_image creating build/lib/pyRadPlan/io/sitk_based/base copying pyRadPlan/io/sitk_based/base/_serialize.py -> build/lib/pyRadPlan/io/sitk_based/base copying pyRadPlan/io/sitk_based/base/_importer.py -> build/lib/pyRadPlan/io/sitk_based/base copying pyRadPlan/io/sitk_based/base/_exporter.py -> build/lib/pyRadPlan/io/sitk_based/base copying pyRadPlan/io/sitk_based/base/__init__.py -> build/lib/pyRadPlan/io/sitk_based/base creating build/lib/pyRadPlan/gui/windows copying pyRadPlan/gui/windows/_splash_win.py -> build/lib/pyRadPlan/gui/windows copying pyRadPlan/gui/windows/_result_win.py -> build/lib/pyRadPlan/gui/windows copying pyRadPlan/gui/windows/_main_win.py -> build/lib/pyRadPlan/gui/windows copying pyRadPlan/gui/windows/_analysis_win.py -> build/lib/pyRadPlan/gui/windows creating build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_ui_mode.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_tissue_params.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_result_widget.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_quantity_selector.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_plot_theme.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_logo_widget.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_log_console.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_info_widget.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_display_names.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_config_form.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_base.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/_analysis_widget.py -> build/lib/pyRadPlan/gui/widgets copying pyRadPlan/gui/widgets/__init__.py -> build/lib/pyRadPlan/gui/widgets creating build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_view.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_settings.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_help.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_file.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_edit.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/_base_data.py -> build/lib/pyRadPlan/gui/menus copying pyRadPlan/gui/menus/__init__.py -> build/lib/pyRadPlan/gui/menus creating build/lib/pyRadPlan/gui/assets copying pyRadPlan/gui/assets/__init__.py -> build/lib/pyRadPlan/gui/assets creating build/lib/pyRadPlan/gui/widgets/workflow copying pyRadPlan/gui/widgets/workflow/_workflow_widget.py -> build/lib/pyRadPlan/gui/widgets/workflow copying pyRadPlan/gui/widgets/workflow/_image_import_dialog.py -> build/lib/pyRadPlan/gui/widgets/workflow copying pyRadPlan/gui/widgets/workflow/_dicom_import_dialog.py -> build/lib/pyRadPlan/gui/widgets/workflow copying pyRadPlan/gui/widgets/workflow/_binary_import_dialog.py -> build/lib/pyRadPlan/gui/widgets/workflow copying pyRadPlan/gui/widgets/workflow/__init__.py -> build/lib/pyRadPlan/gui/widgets/workflow creating build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/vois_widget.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/visualization_widget.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/viewer_options_widget.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/quantity_widget.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/_save_result_dialog.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/_orientation_marker.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/_labels.py -> build/lib/pyRadPlan/gui/widgets/result copying pyRadPlan/gui/widgets/result/__init__.py -> build/lib/pyRadPlan/gui/widgets/result creating build/lib/pyRadPlan/gui/widgets/plan copying pyRadPlan/gui/widgets/plan/_tissue_dialog.py -> build/lib/pyRadPlan/gui/widgets/plan copying pyRadPlan/gui/widgets/plan/_plan_widget.py -> build/lib/pyRadPlan/gui/widgets/plan copying pyRadPlan/gui/widgets/plan/_optimization_dialog.py -> build/lib/pyRadPlan/gui/widgets/plan copying pyRadPlan/gui/widgets/plan/__init__.py -> build/lib/pyRadPlan/gui/widgets/plan creating build/lib/pyRadPlan/gui/widgets/optimization copying pyRadPlan/gui/widgets/optimization/_status_window.py -> build/lib/pyRadPlan/gui/widgets/optimization copying pyRadPlan/gui/widgets/optimization/_optimization_widget.py -> build/lib/pyRadPlan/gui/widgets/optimization copying pyRadPlan/gui/widgets/optimization/__init__.py -> build/lib/pyRadPlan/gui/widgets/optimization creating build/lib/pyRadPlan/gui/widgets/analysis copying pyRadPlan/gui/widgets/analysis/_qi_point_dialog.py -> build/lib/pyRadPlan/gui/widgets/analysis copying pyRadPlan/gui/widgets/analysis/_qi.py -> build/lib/pyRadPlan/gui/widgets/analysis copying pyRadPlan/gui/widgets/analysis/_gamma.py -> build/lib/pyRadPlan/gui/widgets/analysis copying pyRadPlan/gui/widgets/analysis/_dvh.py -> build/lib/pyRadPlan/gui/widgets/analysis creating build/lib/pyRadPlan/gui/widgets/ai copying pyRadPlan/gui/widgets/ai/_ai_task_dialog.py -> build/lib/pyRadPlan/gui/widgets/ai copying pyRadPlan/gui/widgets/ai/__init__.py -> build/lib/pyRadPlan/gui/widgets/ai creating build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_topasmc.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_svdpb.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_sparse_output.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_particle_cutoff.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_hongpb.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_fredmc.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_factory.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_base_pencilbeam_particle.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_base_pencilbeam.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_base_montecarlo.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/_base.py -> build/lib/pyRadPlan/dose/engines copying pyRadPlan/dose/engines/__init__.py -> build/lib/pyRadPlan/dose/engines creating build/lib/pyRadPlan/dose/engines/kernels copying pyRadPlan/dose/engines/kernels/_calc_geo_dists_kernel.py -> build/lib/pyRadPlan/dose/engines/kernels copying pyRadPlan/dose/engines/kernels/__init__.py -> build/lib/pyRadPlan/dose/engines/kernels creating build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/typing.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/jittable.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/helpers.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/compat.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/_reductions.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/_interpolation1d.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/_interpolation.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/_image_interpolation.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/_backends.py -> build/lib/pyRadPlan/core/xp_utils copying pyRadPlan/core/xp_utils/__init__.py -> build/lib/pyRadPlan/core/xp_utils creating build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_sources.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_reference.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_provenance.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_presets.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_conversion.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/_base.py -> build/lib/pyRadPlan/biology/tissues copying pyRadPlan/biology/tissues/__init__.py -> build/lib/pyRadPlan/biology/tissues creating build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_tissue_lookup.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_resolution.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_options.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_kernel_sets.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_influence.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_factory.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_evaluator.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_engine.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/_base.py -> build/lib/pyRadPlan/biology/models copying pyRadPlan/biology/models/__init__.py -> build/lib/pyRadPlan/biology/models creating build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/zstar_based_lq_model.py -> build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/tabulated_rbe_models.py -> build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/lq_models.py -> build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/let_based_lq_models.py -> build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/kernel_based_lq_model.py -> build/lib/pyRadPlan/biology/models/_models copying pyRadPlan/biology/models/_models/const_rbe.py -> build/lib/pyRadPlan/biology/models/_models creating build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/_settings.py -> build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/_resolve.py -> build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/_registry.py -> build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/_preprocessor.py -> build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/_load_model.py -> build/lib/pyRadPlan/ai/modelhub copying pyRadPlan/ai/modelhub/__init__.py -> build/lib/pyRadPlan/ai/modelhub creating build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/_usage.py -> build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/_settings.py -> build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/_plan_agents.py -> build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/_models.py -> build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/_cst_agents.py -> build/lib/pyRadPlan/ai/agents copying pyRadPlan/ai/agents/__init__.py -> build/lib/pyRadPlan/ai/agents running egg_info writing pyRadPlan.egg-info/PKG-INFO writing dependency_links to pyRadPlan.egg-info/dependency_links.txt writing entry points to pyRadPlan.egg-info/entry_points.txt writing requirements to pyRadPlan.egg-info/requires.txt writing top-level names to pyRadPlan.egg-info/top_level.txt reading manifest file 'pyRadPlan.egg-info/SOURCES.txt' adding license file 'LICENSE' writing manifest file 'pyRadPlan.egg-info/SOURCES.txt' creating build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/template/pyRadPlan_run_template.txt -> build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/template/patient_template.txt -> build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/template/beamSetup_template.txt -> build/lib/pyRadPlan/data/topas/input/template creating build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/scorer/TOPAS_subscorer_LET.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToWater.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToMedium.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer creating build/lib/pyRadPlan/data/topas/input/material_converter copying pyRadPlan/data/topas/input/material_converter/TOPAS_schneider_converter.txt.in -> build/lib/pyRadPlan/data/topas/input/material_converter creating build/lib/pyRadPlan/data/topas/input/beam_setup copying pyRadPlan/data/topas/input/beam_setup/TOPAS_beam_setup_biGaussian.txt.in -> build/lib/pyRadPlan/data/topas/input/beam_setup creating build/lib/pyRadPlan/data/rbe copying pyRadPlan/data/rbe/RBEtable_LEMI_Scholz06_AX01_BX005.mat -> build/lib/pyRadPlan/data/rbe creating build/lib/pyRadPlan/data/physics/stopping copying pyRadPlan/data/physics/stopping/SPtable.mat -> build/lib/pyRadPlan/data/physics/stopping creating build/lib/pyRadPlan/data/phantoms copying pyRadPlan/data/phantoms/TG119.mat -> build/lib/pyRadPlan/data/phantoms creating build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/protons_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/photons_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/oxygen_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/helium_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/carbon_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/VHEE_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/VHEE_Focused.mat -> build/lib/pyRadPlan/data/machines creating build/lib/pyRadPlan/data/ai_models copying pyRadPlan/data/ai_models/model_config.template.json -> build/lib/pyRadPlan/data/ai_models copying pyRadPlan/gui/assets/__init__.py -> build/lib/pyRadPlan/gui/assets creating build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/pyradplan_logo_skull_square.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/pyradplan_logo_full_landscape.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/dkfz_logo_white.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/dkfz_logo_blue.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/matRad/.gitkeep -> build/lib/pyRadPlan/matRad copying pyRadPlan/io/.gitkeep -> build/lib/pyRadPlan/io creating build/lib/pyRadPlan/stf/hlutLibrary copying pyRadPlan/stf/hlutLibrary/matRad_default.hlut -> build/lib/pyRadPlan/stf/hlutLibrary copying pyRadPlan/gui/assets/logos/dkfz_logo_blue.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/dkfz_logo_white.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/pyradplan_logo_full_landscape.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/gui/assets/logos/pyradplan_logo_skull_square.svg -> build/lib/pyRadPlan/gui/assets/logos copying pyRadPlan/data/rbe/RBEtable_LEMI_Scholz06_AX01_BX005.mat -> build/lib/pyRadPlan/data/rbe copying pyRadPlan/data/phantoms/TG119.mat -> build/lib/pyRadPlan/data/phantoms copying pyRadPlan/data/machines/VHEE_Focused.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/VHEE_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/carbon_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/helium_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/oxygen_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/photons_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/machines/protons_Generic.mat -> build/lib/pyRadPlan/data/machines copying pyRadPlan/data/ai_models/model_config.template.json -> build/lib/pyRadPlan/data/ai_models copying pyRadPlan/data/topas/input/template/beamSetup_template.txt -> build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/template/patient_template.txt -> build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/template/pyRadPlan_run_template.txt -> build/lib/pyRadPlan/data/topas/input/template copying pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToMedium.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToWater.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/scorer/TOPAS_subscorer_LET.txt.in -> build/lib/pyRadPlan/data/topas/input/scorer copying pyRadPlan/data/topas/input/material_converter/TOPAS_schneider_converter.txt.in -> build/lib/pyRadPlan/data/topas/input/material_converter copying pyRadPlan/data/topas/input/beam_setup/TOPAS_beam_setup_biGaussian.txt.in -> build/lib/pyRadPlan/data/topas/input/beam_setup copying pyRadPlan/data/physics/stopping/SPtable.mat -> build/lib/pyRadPlan/data/physics/stopping installing to build/bdist.linux-aarch64/wheel running install running install_lib creating build/bdist.linux-aarch64/wheel creating build/bdist.linux-aarch64/wheel/pyRadPlan creating build/bdist.linux-aarch64/wheel/pyRadPlan/data creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/ai_models copying build/lib/pyRadPlan/data/ai_models/model_config.template.json -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/ai_models creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/protons_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/photons_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/oxygen_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/helium_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/carbon_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/VHEE_Generic.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/VHEE_Focused.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/machines creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/phantoms copying build/lib/pyRadPlan/data/phantoms/TG119.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/phantoms creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/physics creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/physics/stopping copying build/lib/pyRadPlan/data/physics/stopping/SPtable.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/physics/stopping creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/rbe copying build/lib/pyRadPlan/data/rbe/RBEtable_LEMI_Scholz06_AX01_BX005.mat -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/rbe creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas/input creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas/input/beam_setup copying build/lib/pyRadPlan/data/topas/input/beam_setup/TOPAS_beam_setup_biGaussian.txt.in -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/beam_setup creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas/input/material_converter copying build/lib/pyRadPlan/data/topas/input/material_converter/TOPAS_schneider_converter.txt.in -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/material_converter creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_subscorer_LET.txt.in -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToWater.txt.in -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToMedium.txt.in -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/scorer creating build/bdist.linux-aarch64/wheel/pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/pyRadPlan_run_template.txt -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/patient_template.txt -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/beamSetup_template.txt -> build/bdist.linux-aarch64/wheel/./pyRadPlan/data/topas/input/template creating build/bdist.linux-aarch64/wheel/pyRadPlan/ai creating build/bdist.linux-aarch64/wheel/pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_cst_agents.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_models.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_plan_agents.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_settings.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_usage.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/agents creating build/bdist.linux-aarch64/wheel/pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_load_model.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_preprocessor.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_registry.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_resolve.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_settings.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ai creating build/bdist.linux-aarch64/wheel/pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_dvh.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_dvh_plot.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_qi.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_units.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/analysis creating build/bdist.linux-aarch64/wheel/pyRadPlan/biology creating build/bdist.linux-aarch64/wheel/pyRadPlan/biology/models creating build/bdist.linux-aarch64/wheel/pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/const_rbe.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/kernel_based_lq_model.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/let_based_lq_models.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/lq_models.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/tabulated_rbe_models.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/zstar_based_lq_model.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_engine.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_evaluator.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_influence.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_kernel_sets.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_options.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_resolution.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_tissue_lookup.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/models creating build/bdist.linux-aarch64/wheel/pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_conversion.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_presets.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_provenance.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_reference.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_sources.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/biology creating build/bdist.linux-aarch64/wheel/pyRadPlan/core creating build/bdist.linux-aarch64/wheel/pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_backends.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_image_interpolation.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_interpolation.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_interpolation1d.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_reductions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/compat.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/helpers.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/jittable.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/typing.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_base_data.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_configurable.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_exceptions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_grids.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_paths.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_progress.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_units.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/datamodel.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/np2sitk.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/resample.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/core creating build/bdist.linux-aarch64/wheel/pyRadPlan/cst copying build/lib/pyRadPlan/cst/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/cst copying build/lib/pyRadPlan/cst/_cst.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/cst copying build/lib/pyRadPlan/cst/_voi.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/cst creating build/bdist.linux-aarch64/wheel/pyRadPlan/ct copying build/lib/pyRadPlan/ct/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ct copying build/lib/pyRadPlan/ct/_ct.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ct copying build/lib/pyRadPlan/ct/_hlut.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/ct creating build/bdist.linux-aarch64/wheel/pyRadPlan/dij copying build/lib/pyRadPlan/dij/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dij copying build/lib/pyRadPlan/dij/_compose_beam_dijs.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dij copying build/lib/pyRadPlan/dij/_dij.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dij creating build/bdist.linux-aarch64/wheel/pyRadPlan/dose creating build/bdist.linux-aarch64/wheel/pyRadPlan/dose/engines creating build/bdist.linux-aarch64/wheel/pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/kernels/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/kernels/_calc_geo_dists_kernel.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_montecarlo.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_pencilbeam.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_pencilbeam_particle.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_fredmc.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_hongpb.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_particle_cutoff.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_sparse_output.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_svdpb.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_topasmc.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose copying build/lib/pyRadPlan/dose/_calc_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/dose creating build/bdist.linux-aarch64/wheel/pyRadPlan/geometry copying build/lib/pyRadPlan/geometry/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/geometry copying build/lib/pyRadPlan/geometry/lps.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/geometry creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/assets creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/pyradplan_logo_skull_square.svg -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/pyradplan_logo_full_landscape.svg -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/dkfz_logo_white.svg -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/dkfz_logo_blue.svg -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/assets creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_base_data.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_edit.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_file.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_help.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_settings.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_view.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/menus creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/ai copying build/lib/pyRadPlan/gui/widgets/ai/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/ai copying build/lib/pyRadPlan/gui/widgets/ai/_ai_task_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/ai creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_dvh.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_gamma.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_qi.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_qi_point_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/analysis creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/_optimization_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/_status_window.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/optimization creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_optimization_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_plan_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_tissue_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/plan creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_labels.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_orientation_marker.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_save_result_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/quantity_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/viewer_options_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/visualization_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/vois_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/result creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_binary_import_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_dicom_import_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_image_import_dialog.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_workflow_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_analysis_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_config_form.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_display_names.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_info_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_log_console.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_logo_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_plot_theme.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_quantity_selector.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_result_widget.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_tissue_params.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_ui_mode.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/widgets creating build/bdist.linux-aarch64/wheel/pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_analysis_win.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_main_win.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_result_win.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_splash_win.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui copying build/lib/pyRadPlan/gui/apps.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui copying build/lib/pyRadPlan/gui/workspace.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/gui creating build/bdist.linux-aarch64/wheel/pyRadPlan/io copying build/lib/pyRadPlan/io/.gitkeep -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/base creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_common.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_cst.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_ct.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_seg.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_handler.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_helpers.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_cst.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_ct.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/dicom creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_handler.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_matfile.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/matlab creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_handler.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_serialize.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/npz creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_handler.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/pickle creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/sitk_based creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_exporter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_importer.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_serialize.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/base creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/sitk_based/meta_image copying build/lib/pyRadPlan/io/sitk_based/meta_image/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/meta_image creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/sitk_based/nifti copying build/lib/pyRadPlan/io/sitk_based/nifti/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/nifti creating build/bdist.linux-aarch64/wheel/pyRadPlan/io/sitk_based/nrrd copying build/lib/pyRadPlan/io/sitk_based/nrrd/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based/nrrd copying build/lib/pyRadPlan/io/sitk_based/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based copying build/lib/pyRadPlan/io/sitk_based/_binary_import.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io/sitk_based copying build/lib/pyRadPlan/io/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_helpers.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_load_save.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/io creating build/bdist.linux-aarch64/wheel/pyRadPlan/machines creating build/bdist.linux-aarch64/wheel/pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_beam_modifier.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_external_beam.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_internal_beam.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/base creating build/bdist.linux-aarch64/wheel/pyRadPlan/machines/particles creating build/bdist.linux-aarch64/wheel/pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_ions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_vhee.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_cutoff.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_emittance.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_energy.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_focus.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_fragment_spectrum.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_ions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_vhee.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/particles creating build/bdist.linux-aarch64/wheel/pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_calculate_machine_scale.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_linac.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_svd_kernel.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines copying build/lib/pyRadPlan/machines/_load.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines copying build/lib/pyRadPlan/machines/_validate.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/machines creating build/bdist.linux-aarch64/wheel/pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/.gitkeep -> build/bdist.linux-aarch64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_engine.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_matlab.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_octave.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/matRad creating build/bdist.linux-aarch64/wheel/pyRadPlan/optimization creating build/bdist.linux-aarch64/wheel/pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_eud.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_max_dvh.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_mean.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_min_dvh.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_objective.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_dev.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_mimicking.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_over.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_under.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_std.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_variance.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/objectives creating build/bdist.linux-aarch64/wheel/pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_nonlin_fluence.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_optiprob.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_simple_least_squares.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/problems creating build/bdist.linux-aarch64/wheel/pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_composite_worst_case.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_expected_quantity.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_expected_value.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_none.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_objective_worst_case.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_smooth_max.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_terms.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_utils.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_voxel_worst_case.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/robustness creating build/bdist.linux-aarch64/wheel/pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_base_solvers.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_ipax_solver.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_ipopt.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_scipy_solver.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization copying build/lib/pyRadPlan/optimization/_fluence_optimization.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/optimization creating build/bdist.linux-aarch64/wheel/pyRadPlan/plan copying build/lib/pyRadPlan/plan/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/plan copying build/lib/pyRadPlan/plan/_plans.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/plan creating build/bdist.linux-aarch64/wheel/pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_alpha_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_effect.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_let.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_let_x_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_rbe_x_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_resolver.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_sqrt_beta_dose.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/quantities creating build/bdist.linux-aarch64/wheel/pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_kernels.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_kernels_numba.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_siddon.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/raytracer creating build/bdist.linux-aarch64/wheel/pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_dimensions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_distributions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_explicit.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_gridded.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_importance.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_legacy.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_nominal.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_random.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_set.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_worst_case.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/scenarios creating build/bdist.linux-aarch64/wheel/pyRadPlan/stf creating build/bdist.linux-aarch64/wheel/pyRadPlan/stf/hlutLibrary copying build/lib/pyRadPlan/stf/hlutLibrary/matRad_default.hlut -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/hlutLibrary creating build/bdist.linux-aarch64/wheel/pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_base.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_externalbeam.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_factory.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_ions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_photons.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_vhee.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_beam.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_beamlet.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_exceptions.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_generate_stf.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_presets.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_rangeshifter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_ray.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_steeringinformation.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/stf creating build/bdist.linux-aarch64/wheel/pyRadPlan/util copying build/lib/pyRadPlan/util/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/_jupyter.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/helpers.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/keyboard_listener.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/logging_utils.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/openmp.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/util creating build/bdist.linux-aarch64/wheel/pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/_plot_multiple_slices.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/_plot_slice.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/__init__.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan copying build/lib/pyRadPlan/_lazy.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan copying build/lib/pyRadPlan/_settings.py -> build/bdist.linux-aarch64/wheel/./pyRadPlan running install_egg_info Copying pyRadPlan.egg-info to build/bdist.linux-aarch64/wheel/./pyRadPlan-0.8.0-py3.14.egg-info running install_scripts creating build/bdist.linux-aarch64/wheel/pyradplan-0.8.0.dist-info/WHEEL creating '/builddir/.cache/pip/wheels/bf/c6/d9/519a10de0a2de160c5e3070733236db255354cd2b9dc1b2561/tmpo33wq5zx/.tmp-9wdfhmv3/pyradplan-0.8.0-py3-none-any.whl' and adding 'build/bdist.linux-aarch64/wheel' to it adding 'pyRadPlan/__init__.py' adding 'pyRadPlan/_lazy.py' adding 'pyRadPlan/_settings.py' adding 'pyRadPlan/ai/__init__.py' adding 'pyRadPlan/ai/agents/__init__.py' adding 'pyRadPlan/ai/agents/_cst_agents.py' adding 'pyRadPlan/ai/agents/_models.py' adding 'pyRadPlan/ai/agents/_plan_agents.py' adding 'pyRadPlan/ai/agents/_settings.py' adding 'pyRadPlan/ai/agents/_usage.py' adding 'pyRadPlan/ai/modelhub/__init__.py' adding 'pyRadPlan/ai/modelhub/_load_model.py' adding 'pyRadPlan/ai/modelhub/_preprocessor.py' adding 'pyRadPlan/ai/modelhub/_registry.py' adding 'pyRadPlan/ai/modelhub/_resolve.py' adding 'pyRadPlan/ai/modelhub/_settings.py' adding 'pyRadPlan/analysis/__init__.py' adding 'pyRadPlan/analysis/_dvh.py' adding 'pyRadPlan/analysis/_dvh_plot.py' adding 'pyRadPlan/analysis/_qi.py' adding 'pyRadPlan/analysis/_units.py' adding 'pyRadPlan/biology/__init__.py' adding 'pyRadPlan/biology/models/__init__.py' adding 'pyRadPlan/biology/models/_base.py' adding 'pyRadPlan/biology/models/_engine.py' adding 'pyRadPlan/biology/models/_evaluator.py' adding 'pyRadPlan/biology/models/_factory.py' adding 'pyRadPlan/biology/models/_influence.py' adding 'pyRadPlan/biology/models/_kernel_sets.py' adding 'pyRadPlan/biology/models/_options.py' adding 'pyRadPlan/biology/models/_resolution.py' adding 'pyRadPlan/biology/models/_tissue_lookup.py' adding 'pyRadPlan/biology/models/_models/const_rbe.py' adding 'pyRadPlan/biology/models/_models/kernel_based_lq_model.py' adding 'pyRadPlan/biology/models/_models/let_based_lq_models.py' adding 'pyRadPlan/biology/models/_models/lq_models.py' adding 'pyRadPlan/biology/models/_models/tabulated_rbe_models.py' adding 'pyRadPlan/biology/models/_models/zstar_based_lq_model.py' adding 'pyRadPlan/biology/tissues/__init__.py' adding 'pyRadPlan/biology/tissues/_base.py' adding 'pyRadPlan/biology/tissues/_conversion.py' adding 'pyRadPlan/biology/tissues/_presets.py' adding 'pyRadPlan/biology/tissues/_provenance.py' adding 'pyRadPlan/biology/tissues/_reference.py' adding 'pyRadPlan/biology/tissues/_sources.py' adding 'pyRadPlan/core/__init__.py' adding 'pyRadPlan/core/_base_data.py' adding 'pyRadPlan/core/_configurable.py' adding 'pyRadPlan/core/_exceptions.py' adding 'pyRadPlan/core/_grids.py' adding 'pyRadPlan/core/_paths.py' adding 'pyRadPlan/core/_progress.py' adding 'pyRadPlan/core/_units.py' adding 'pyRadPlan/core/datamodel.py' adding 'pyRadPlan/core/np2sitk.py' adding 'pyRadPlan/core/resample.py' adding 'pyRadPlan/core/xp_utils/__init__.py' adding 'pyRadPlan/core/xp_utils/_backends.py' adding 'pyRadPlan/core/xp_utils/_image_interpolation.py' adding 'pyRadPlan/core/xp_utils/_interpolation.py' adding 'pyRadPlan/core/xp_utils/_interpolation1d.py' adding 'pyRadPlan/core/xp_utils/_reductions.py' adding 'pyRadPlan/core/xp_utils/compat.py' adding 'pyRadPlan/core/xp_utils/helpers.py' adding 'pyRadPlan/core/xp_utils/jittable.py' adding 'pyRadPlan/core/xp_utils/typing.py' adding 'pyRadPlan/cst/__init__.py' adding 'pyRadPlan/cst/_cst.py' adding 'pyRadPlan/cst/_voi.py' adding 'pyRadPlan/ct/__init__.py' adding 'pyRadPlan/ct/_ct.py' adding 'pyRadPlan/ct/_hlut.py' adding 'pyRadPlan/data/ai_models/model_config.template.json' adding 'pyRadPlan/data/machines/VHEE_Focused.mat' adding 'pyRadPlan/data/machines/VHEE_Generic.mat' adding 'pyRadPlan/data/machines/carbon_Generic.mat' adding 'pyRadPlan/data/machines/helium_Generic.mat' adding 'pyRadPlan/data/machines/oxygen_Generic.mat' adding 'pyRadPlan/data/machines/photons_Generic.mat' adding 'pyRadPlan/data/machines/protons_Generic.mat' adding 'pyRadPlan/data/phantoms/TG119.mat' adding 'pyRadPlan/data/physics/stopping/SPtable.mat' adding 'pyRadPlan/data/rbe/RBEtable_LEMI_Scholz06_AX01_BX005.mat' adding 'pyRadPlan/data/topas/input/beam_setup/TOPAS_beam_setup_biGaussian.txt.in' adding 'pyRadPlan/data/topas/input/material_converter/TOPAS_schneider_converter.txt.in' adding 'pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToMedium.txt.in' adding 'pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToWater.txt.in' adding 'pyRadPlan/data/topas/input/scorer/TOPAS_subscorer_LET.txt.in' adding 'pyRadPlan/data/topas/input/template/beamSetup_template.txt' adding 'pyRadPlan/data/topas/input/template/patient_template.txt' adding 'pyRadPlan/data/topas/input/template/pyRadPlan_run_template.txt' adding 'pyRadPlan/dij/__init__.py' adding 'pyRadPlan/dij/_compose_beam_dijs.py' adding 'pyRadPlan/dij/_dij.py' adding 'pyRadPlan/dose/__init__.py' adding 'pyRadPlan/dose/_calc_dose.py' adding 'pyRadPlan/dose/engines/__init__.py' adding 'pyRadPlan/dose/engines/_base.py' adding 'pyRadPlan/dose/engines/_base_montecarlo.py' adding 'pyRadPlan/dose/engines/_base_pencilbeam.py' adding 'pyRadPlan/dose/engines/_base_pencilbeam_particle.py' adding 'pyRadPlan/dose/engines/_factory.py' adding 'pyRadPlan/dose/engines/_fredmc.py' adding 'pyRadPlan/dose/engines/_hongpb.py' adding 'pyRadPlan/dose/engines/_particle_cutoff.py' adding 'pyRadPlan/dose/engines/_sparse_output.py' adding 'pyRadPlan/dose/engines/_svdpb.py' adding 'pyRadPlan/dose/engines/_topasmc.py' adding 'pyRadPlan/dose/engines/kernels/__init__.py' adding 'pyRadPlan/dose/engines/kernels/_calc_geo_dists_kernel.py' adding 'pyRadPlan/geometry/__init__.py' adding 'pyRadPlan/geometry/lps.py' adding 'pyRadPlan/gui/__init__.py' adding 'pyRadPlan/gui/apps.py' adding 'pyRadPlan/gui/workspace.py' adding 'pyRadPlan/gui/assets/__init__.py' adding 'pyRadPlan/gui/assets/logos/dkfz_logo_blue.svg' adding 'pyRadPlan/gui/assets/logos/dkfz_logo_white.svg' adding 'pyRadPlan/gui/assets/logos/pyradplan_logo_full_landscape.svg' adding 'pyRadPlan/gui/assets/logos/pyradplan_logo_skull_square.svg' adding 'pyRadPlan/gui/menus/__init__.py' adding 'pyRadPlan/gui/menus/_base_data.py' adding 'pyRadPlan/gui/menus/_edit.py' adding 'pyRadPlan/gui/menus/_file.py' adding 'pyRadPlan/gui/menus/_help.py' adding 'pyRadPlan/gui/menus/_settings.py' adding 'pyRadPlan/gui/menus/_view.py' adding 'pyRadPlan/gui/widgets/__init__.py' adding 'pyRadPlan/gui/widgets/_analysis_widget.py' adding 'pyRadPlan/gui/widgets/_base.py' adding 'pyRadPlan/gui/widgets/_config_form.py' adding 'pyRadPlan/gui/widgets/_display_names.py' adding 'pyRadPlan/gui/widgets/_info_widget.py' adding 'pyRadPlan/gui/widgets/_log_console.py' adding 'pyRadPlan/gui/widgets/_logo_widget.py' adding 'pyRadPlan/gui/widgets/_plot_theme.py' adding 'pyRadPlan/gui/widgets/_quantity_selector.py' adding 'pyRadPlan/gui/widgets/_result_widget.py' adding 'pyRadPlan/gui/widgets/_tissue_params.py' adding 'pyRadPlan/gui/widgets/_ui_mode.py' adding 'pyRadPlan/gui/widgets/ai/__init__.py' adding 'pyRadPlan/gui/widgets/ai/_ai_task_dialog.py' adding 'pyRadPlan/gui/widgets/analysis/_dvh.py' adding 'pyRadPlan/gui/widgets/analysis/_gamma.py' adding 'pyRadPlan/gui/widgets/analysis/_qi.py' adding 'pyRadPlan/gui/widgets/analysis/_qi_point_dialog.py' adding 'pyRadPlan/gui/widgets/optimization/__init__.py' adding 'pyRadPlan/gui/widgets/optimization/_optimization_widget.py' adding 'pyRadPlan/gui/widgets/optimization/_status_window.py' adding 'pyRadPlan/gui/widgets/plan/__init__.py' adding 'pyRadPlan/gui/widgets/plan/_optimization_dialog.py' adding 'pyRadPlan/gui/widgets/plan/_plan_widget.py' adding 'pyRadPlan/gui/widgets/plan/_tissue_dialog.py' adding 'pyRadPlan/gui/widgets/result/__init__.py' adding 'pyRadPlan/gui/widgets/result/_labels.py' adding 'pyRadPlan/gui/widgets/result/_orientation_marker.py' adding 'pyRadPlan/gui/widgets/result/_save_result_dialog.py' adding 'pyRadPlan/gui/widgets/result/quantity_widget.py' adding 'pyRadPlan/gui/widgets/result/viewer_options_widget.py' adding 'pyRadPlan/gui/widgets/result/visualization_widget.py' adding 'pyRadPlan/gui/widgets/result/vois_widget.py' adding 'pyRadPlan/gui/widgets/workflow/__init__.py' adding 'pyRadPlan/gui/widgets/workflow/_binary_import_dialog.py' adding 'pyRadPlan/gui/widgets/workflow/_dicom_import_dialog.py' adding 'pyRadPlan/gui/widgets/workflow/_image_import_dialog.py' adding 'pyRadPlan/gui/widgets/workflow/_workflow_widget.py' adding 'pyRadPlan/gui/windows/_analysis_win.py' adding 'pyRadPlan/gui/windows/_main_win.py' adding 'pyRadPlan/gui/windows/_result_win.py' adding 'pyRadPlan/gui/windows/_splash_win.py' adding 'pyRadPlan/io/.gitkeep' adding 'pyRadPlan/io/__init__.py' adding 'pyRadPlan/io/_factory.py' adding 'pyRadPlan/io/_helpers.py' adding 'pyRadPlan/io/_load_save.py' adding 'pyRadPlan/io/base/__init__.py' adding 'pyRadPlan/io/base/_exporter.py' adding 'pyRadPlan/io/base/_importer.py' adding 'pyRadPlan/io/dicom/__init__.py' adding 'pyRadPlan/io/dicom/_export_common.py' adding 'pyRadPlan/io/dicom/_export_cst.py' adding 'pyRadPlan/io/dicom/_export_ct.py' adding 'pyRadPlan/io/dicom/_export_dose.py' adding 'pyRadPlan/io/dicom/_export_seg.py' adding 'pyRadPlan/io/dicom/_exporter.py' adding 'pyRadPlan/io/dicom/_handler.py' adding 'pyRadPlan/io/dicom/_helpers.py' adding 'pyRadPlan/io/dicom/_import_cst.py' adding 'pyRadPlan/io/dicom/_import_ct.py' adding 'pyRadPlan/io/dicom/_import_dose.py' adding 'pyRadPlan/io/dicom/_importer.py' adding 'pyRadPlan/io/matlab/__init__.py' adding 'pyRadPlan/io/matlab/_exporter.py' adding 'pyRadPlan/io/matlab/_handler.py' adding 'pyRadPlan/io/matlab/_importer.py' adding 'pyRadPlan/io/matlab/_matfile.py' adding 'pyRadPlan/io/npz/__init__.py' adding 'pyRadPlan/io/npz/_exporter.py' adding 'pyRadPlan/io/npz/_handler.py' adding 'pyRadPlan/io/npz/_importer.py' adding 'pyRadPlan/io/npz/_serialize.py' adding 'pyRadPlan/io/pickle/__init__.py' adding 'pyRadPlan/io/pickle/_exporter.py' adding 'pyRadPlan/io/pickle/_handler.py' adding 'pyRadPlan/io/pickle/_importer.py' adding 'pyRadPlan/io/sitk_based/__init__.py' adding 'pyRadPlan/io/sitk_based/_binary_import.py' adding 'pyRadPlan/io/sitk_based/base/__init__.py' adding 'pyRadPlan/io/sitk_based/base/_exporter.py' adding 'pyRadPlan/io/sitk_based/base/_importer.py' adding 'pyRadPlan/io/sitk_based/base/_serialize.py' adding 'pyRadPlan/io/sitk_based/meta_image/__init__.py' adding 'pyRadPlan/io/sitk_based/nifti/__init__.py' adding 'pyRadPlan/io/sitk_based/nrrd/__init__.py' adding 'pyRadPlan/machines/__init__.py' adding 'pyRadPlan/machines/_load.py' adding 'pyRadPlan/machines/_validate.py' adding 'pyRadPlan/machines/base/__init__.py' adding 'pyRadPlan/machines/base/_base.py' adding 'pyRadPlan/machines/base/_beam_modifier.py' adding 'pyRadPlan/machines/base/_external_beam.py' adding 'pyRadPlan/machines/base/_factory.py' adding 'pyRadPlan/machines/base/_internal_beam.py' adding 'pyRadPlan/machines/particles/__init__.py' adding 'pyRadPlan/machines/particles/_base.py' adding 'pyRadPlan/machines/particles/_beam_cutoff.py' adding 'pyRadPlan/machines/particles/_beam_emittance.py' adding 'pyRadPlan/machines/particles/_beam_energy.py' adding 'pyRadPlan/machines/particles/_beam_focus.py' adding 'pyRadPlan/machines/particles/_beam_fragment_spectrum.py' adding 'pyRadPlan/machines/particles/_ions.py' adding 'pyRadPlan/machines/particles/_vhee.py' adding 'pyRadPlan/machines/particles/kernel/__init__.py' adding 'pyRadPlan/machines/particles/kernel/_base.py' adding 'pyRadPlan/machines/particles/kernel/_ions.py' adding 'pyRadPlan/machines/particles/kernel/_vhee.py' adding 'pyRadPlan/machines/photons/__init__.py' adding 'pyRadPlan/machines/photons/_base.py' adding 'pyRadPlan/machines/photons/_calculate_machine_scale.py' adding 'pyRadPlan/machines/photons/_linac.py' adding 'pyRadPlan/machines/photons/_svd_kernel.py' adding 'pyRadPlan/matRad/.gitkeep' adding 'pyRadPlan/matRad/__init__.py' adding 'pyRadPlan/matRad/_engine.py' adding 'pyRadPlan/matRad/_matlab.py' adding 'pyRadPlan/matRad/_octave.py' adding 'pyRadPlan/optimization/__init__.py' adding 'pyRadPlan/optimization/_fluence_optimization.py' adding 'pyRadPlan/optimization/objectives/__init__.py' adding 'pyRadPlan/optimization/objectives/_eud.py' adding 'pyRadPlan/optimization/objectives/_factory.py' adding 'pyRadPlan/optimization/objectives/_max_dvh.py' adding 'pyRadPlan/optimization/objectives/_mean.py' adding 'pyRadPlan/optimization/objectives/_min_dvh.py' adding 'pyRadPlan/optimization/objectives/_objective.py' adding 'pyRadPlan/optimization/objectives/_squared_dev.py' adding 'pyRadPlan/optimization/objectives/_squared_mimicking.py' adding 'pyRadPlan/optimization/objectives/_squared_over.py' adding 'pyRadPlan/optimization/objectives/_squared_under.py' adding 'pyRadPlan/optimization/objectives/_std.py' adding 'pyRadPlan/optimization/objectives/_variance.py' adding 'pyRadPlan/optimization/problems/__init__.py' adding 'pyRadPlan/optimization/problems/_factory.py' adding 'pyRadPlan/optimization/problems/_nonlin_fluence.py' adding 'pyRadPlan/optimization/problems/_optiprob.py' adding 'pyRadPlan/optimization/problems/_simple_least_squares.py' adding 'pyRadPlan/optimization/robustness/__init__.py' adding 'pyRadPlan/optimization/robustness/_base.py' adding 'pyRadPlan/optimization/robustness/_composite_worst_case.py' adding 'pyRadPlan/optimization/robustness/_expected_quantity.py' adding 'pyRadPlan/optimization/robustness/_expected_value.py' adding 'pyRadPlan/optimization/robustness/_factory.py' adding 'pyRadPlan/optimization/robustness/_none.py' adding 'pyRadPlan/optimization/robustness/_objective_worst_case.py' adding 'pyRadPlan/optimization/robustness/_smooth_max.py' adding 'pyRadPlan/optimization/robustness/_terms.py' adding 'pyRadPlan/optimization/robustness/_utils.py' adding 'pyRadPlan/optimization/robustness/_voxel_worst_case.py' adding 'pyRadPlan/optimization/solvers/__init__.py' adding 'pyRadPlan/optimization/solvers/_base_solvers.py' adding 'pyRadPlan/optimization/solvers/_factory.py' adding 'pyRadPlan/optimization/solvers/_ipax_solver.py' adding 'pyRadPlan/optimization/solvers/_ipopt.py' adding 'pyRadPlan/optimization/solvers/_scipy_solver.py' adding 'pyRadPlan/plan/__init__.py' adding 'pyRadPlan/plan/_plans.py' adding 'pyRadPlan/quantities/__init__.py' adding 'pyRadPlan/quantities/_alpha_dose.py' adding 'pyRadPlan/quantities/_base.py' adding 'pyRadPlan/quantities/_dose.py' adding 'pyRadPlan/quantities/_effect.py' adding 'pyRadPlan/quantities/_let.py' adding 'pyRadPlan/quantities/_let_x_dose.py' adding 'pyRadPlan/quantities/_rbe_x_dose.py' adding 'pyRadPlan/quantities/_resolver.py' adding 'pyRadPlan/quantities/_sqrt_beta_dose.py' adding 'pyRadPlan/raytracer/__init__.py' adding 'pyRadPlan/raytracer/_base.py' adding 'pyRadPlan/raytracer/_kernels.py' adding 'pyRadPlan/raytracer/_kernels_numba.py' adding 'pyRadPlan/raytracer/_siddon.py' adding 'pyRadPlan/scenarios/__init__.py' adding 'pyRadPlan/scenarios/_base.py' adding 'pyRadPlan/scenarios/_dimensions.py' adding 'pyRadPlan/scenarios/_distributions.py' adding 'pyRadPlan/scenarios/_explicit.py' adding 'pyRadPlan/scenarios/_gridded.py' adding 'pyRadPlan/scenarios/_importance.py' adding 'pyRadPlan/scenarios/_legacy.py' adding 'pyRadPlan/scenarios/_nominal.py' adding 'pyRadPlan/scenarios/_random.py' adding 'pyRadPlan/scenarios/_set.py' adding 'pyRadPlan/scenarios/_worst_case.py' adding 'pyRadPlan/stf/__init__.py' adding 'pyRadPlan/stf/_beam.py' adding 'pyRadPlan/stf/_beamlet.py' adding 'pyRadPlan/stf/_exceptions.py' adding 'pyRadPlan/stf/_generate_stf.py' adding 'pyRadPlan/stf/_presets.py' adding 'pyRadPlan/stf/_rangeshifter.py' adding 'pyRadPlan/stf/_ray.py' adding 'pyRadPlan/stf/_steeringinformation.py' adding 'pyRadPlan/stf/generators/__init__.py' adding 'pyRadPlan/stf/generators/_base.py' adding 'pyRadPlan/stf/generators/_externalbeam.py' adding 'pyRadPlan/stf/generators/_factory.py' adding 'pyRadPlan/stf/generators/_ions.py' adding 'pyRadPlan/stf/generators/_photons.py' adding 'pyRadPlan/stf/generators/_vhee.py' adding 'pyRadPlan/stf/hlutLibrary/matRad_default.hlut' adding 'pyRadPlan/util/__init__.py' adding 'pyRadPlan/util/_jupyter.py' adding 'pyRadPlan/util/helpers.py' adding 'pyRadPlan/util/keyboard_listener.py' adding 'pyRadPlan/util/logging_utils.py' adding 'pyRadPlan/util/openmp.py' adding 'pyRadPlan/visualization/__init__.py' adding 'pyRadPlan/visualization/_plot_multiple_slices.py' adding 'pyRadPlan/visualization/_plot_slice.py' adding 'pyradplan-0.8.0.dist-info/licenses/LICENSE' adding 'pyradplan-0.8.0.dist-info/METADATA' adding 'pyradplan-0.8.0.dist-info/WHEEL' adding 'pyradplan-0.8.0.dist-info/entry_points.txt' adding 'pyradplan-0.8.0.dist-info/top_level.txt' adding 'pyradplan-0.8.0.dist-info/RECORD' removing build/bdist.linux-aarch64/wheel Building wheel for pyRadPlan (pyproject.toml): finished with status 'done' Created wheel for pyRadPlan: filename=pyradplan-0.8.0-py3-none-any.whl size=32327552 sha256=3e87038af4e10eba3cd2e519fe3afd87c2215ee4c1b90cffccaed142619c7f36 Stored in directory: /builddir/.cache/pip/wheels/bf/c6/d9/519a10de0a2de160c5e3070733236db255354cd2b9dc1b2561 Successfully built pyRadPlan + RPM_EC=0 ++ jobs -p + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.4iqfBb + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + '[' /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT '!=' / ']' + rm -rf /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT ++ dirname /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT + mkdir -p /builddir/build/BUILD/python-pyradplan-0.8.0-build + mkdir /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd pyradplan-0.8.0 ++ ls /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir/pyradplan-0.8.0-py3-none-any.whl ++ xargs basename --multiple ++ sed -E 's/([^-]+)-([^-]+)-.+\.whl/\1==\2/' + specifier=pyradplan==0.8.0 + '[' -z pyradplan==0.8.0 ']' + PIP_CONFIG_FILE=/dev/null + TMPDIR=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir + /usr/bin/python3 -m pip install --root /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT --prefix /usr --no-deps --disable-pip-version-check --progress-bar off --verbose --ignore-installed --no-warn-script-location --no-index --no-cache-dir --find-links /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir pyradplan==0.8.0 Using pip 26.0.1 from /usr/lib/python3.14/site-packages/pip (python 3.14) Looking in links: /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir Processing /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir/pyradplan-0.8.0-py3-none-any.whl Installing collected packages: pyradplan Creating /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin changing mode of /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin/pyRadPlanGUI to 755 Successfully installed pyradplan-0.8.0 + '[' -d /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin ']' + '[' -z sP ']' + shebang_flags=-kasP + /usr/bin/python3 -B /usr/lib/rpm/redhat/pathfix.py -pni /usr/bin/python3 -kasP /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin/pyRadPlanGUI /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin/pyRadPlanGUI: updating + rm -rfv /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin/__pycache__ + rm -f /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-ghost-distinfo + site_dirs=() + '[' -d /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages ']' + site_dirs+=("/usr/lib/python3.14/site-packages") + '[' /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib64/python3.14/site-packages '!=' /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages ']' + '[' -d /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib64/python3.14/site-packages ']' + for site_dir in ${site_dirs[@]} + for distinfo in /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT$site_dir/*.dist-info + echo '%ghost %dir /usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info' +++ basename /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info ++ PYTHONPATH=/usr/lib/rpm/redhat ++ /usr/bin/python3 -sBc 'import sys; from pyproject_save_files import canonical_name_from_distinfo; print(canonical_name_from_distinfo(sys.argv[1]))' pyradplan-0.8.0.dist-info + _normalized=pyradplan + echo '%ghost %dir /usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info' + sed -i s/pip/rpm/ /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/INSTALLER + PYTHONPATH=/usr/lib/rpm/redhat + /usr/bin/python3 -B /usr/lib/rpm/redhat/pyproject_preprocess_record.py --buildroot /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT --record /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/RECORD --output /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-record + rm -fv /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/RECORD removed '/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/RECORD' + rm -fv /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/REQUESTED removed '/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyradplan-0.8.0.dist-info/REQUESTED' + '[' -f /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-dep-overrides ']' ++ wc -l /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-ghost-distinfo ++ cut -f1 '-d ' + lines=1 + '[' 1 -ne 1 ']' + RPM_FILES_ESCAPE=4.19 + /usr/bin/python3 /usr/lib/rpm/redhat/pyproject_save_files.py --output-files /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-files --output-modules /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-modules --buildroot /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT --sitelib /usr/lib/python3.14/site-packages --sitearch /usr/lib64/python3.14/site-packages --python-version 3.14 --pyproject-record /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-record --prefix /usr pyRadPlan + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-ldconfig + COMPRESS='gzip -9 -n' + COMPRESS_EXT=.gz + /usr/lib/rpm/brp-compress + /usr/lib/rpm/brp-strip /usr/bin/strip + /usr/lib/rpm/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump + /usr/lib/rpm/redhat/brp-strip-lto /usr/bin/strip + /usr/lib/rpm/check-rpaths + /usr/lib/rpm/redhat/brp-mangle-shebangs + /usr/lib/rpm/brp-remove-la-files + /usr/lib/rpm/redhat/brp-python-rpm-in-distinfo + env /usr/lib/rpm/redhat/brp-python-bytecompile '' 1 0 -j4 Bytecompiling .py files below /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14 using python3.14 + /usr/lib/rpm/redhat/brp-python-hardlink + /usr/bin/add-det --brp -j4 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/__pycache__/_lazy.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/visualization/__pycache__/_plot_multiple_slices.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/visualization/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/__pycache__/_settings.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/openmp.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/logging_utils.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/_jupyter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/helpers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/util/__pycache__/keyboard_listener.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_steeringinformation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_ray.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_rangeshifter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/visualization/__pycache__/_plot_slice.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_generate_stf.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_exceptions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_presets.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_beam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/__pycache__/_beamlet.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_photons.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_vhee.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_externalbeam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/__pycache__/_ions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_worst_case.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_dimensions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_importance.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_random.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_nominal.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_gridded.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_explicit.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/__pycache__/_kernels_numba.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/__pycache__/_kernels.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_legacy.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/__pycache__/_siddon.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_distributions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_effect.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_let.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_sqrt_beta_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_alpha_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/__pycache__/_set.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_let_x_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_rbe_x_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_resolver.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/plan/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/plan/__pycache__/_plans.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/__pycache__/_fluence_optimization.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/_scipy_solver.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/_ipopt.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/_base_solvers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/__pycache__/_ipax_solver.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_smooth_max.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_objective_worst_case.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_voxel_worst_case.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_utils.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_none.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_expected_value.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_expected_quantity.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_composite_worst_case.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/__pycache__/_terms.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/__pycache__/_simple_least_squares.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_squared_dev.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_std.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/__pycache__/_nonlin_fluence.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_max_dvh.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_variance.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_squared_under.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/__pycache__/_optiprob.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_min_dvh.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_squared_over.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_squared_mimicking.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_mean.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_objective.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/__pycache__/_eud.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/matRad/__pycache__/_octave.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/matRad/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/matRad/__pycache__/_engine.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/matRad/__pycache__/_matlab.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/__pycache__/_validate.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/__pycache__/_calculate_machine_scale.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/__pycache__/_svd_kernel.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_vhee.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/__pycache__/_linac.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_ions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_beam_emittance.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_beam_cutoff.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_beam_fragment_spectrum.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_beam_energy.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/__pycache__/_vhee.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/__pycache__/_ions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_beam_focus.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/__pycache__/_load.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/_internal_beam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/__pycache__/_helpers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/_external_beam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/__pycache__/_load_save.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/nrrd/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/__pycache__/_binary_import.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/__pycache__/_beam_modifier.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/base/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/nifti/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/meta_image/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/pickle/__pycache__/_handler.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/base/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/pickle/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/base/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/pickle/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/npz/__pycache__/_serialize.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/npz/__pycache__/_handler.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/sitk_based/base/__pycache__/_serialize.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/npz/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/npz/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/matlab/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/matlab/__pycache__/_matfile.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/npz/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/matlab/__pycache__/_handler.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/matlab/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/pickle/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_import_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/matlab/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_import_ct.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_export_seg.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_helpers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_export_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_handler.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_export_ct.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_export_cst.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_export_common.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_import_cst.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/base/__pycache__/_exporter.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/base/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/base/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/__pycache__/apps.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/windows/__pycache__/_result_win.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/__pycache__/workspace.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/windows/__pycache__/_analysis_win.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_ui_mode.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/dicom/__pycache__/_importer.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/windows/__pycache__/_main_win.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/windows/__pycache__/_splash_win.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_info_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_display_names.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_quantity_selector.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_result_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_plot_theme.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_logo_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_tissue_params.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_log_console.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_config_form.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/workflow/__pycache__/_dicom_import_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/workflow/__pycache__/_image_import_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/workflow/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/__pycache__/_analysis_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/workflow/__pycache__/_binary_import_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/visualization_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/viewer_options_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/_save_result_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/_orientation_marker.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/_labels.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/workflow/__pycache__/_workflow_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/vois_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/plan/__pycache__/_optimization_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/plan/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/plan/__pycache__/_tissue_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/optimization/__pycache__/_status_window.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/optimization/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/result/__pycache__/quantity_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/analysis/__pycache__/_gamma.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/analysis/__pycache__/_qi.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/analysis/__pycache__/_qi_point_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/ai/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/analysis/__pycache__/_dvh.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/ai/__pycache__/_ai_task_dialog.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/optimization/__pycache__/_optimization_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_view.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_edit.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_help.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_file.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/assets/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/geometry/__pycache__/lps.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/geometry/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/__pycache__/_calc_dose.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_settings.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_hongpb.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/widgets/plan/__pycache__/_plan_widget.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/gui/menus/__pycache__/_base_data.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_svdpb.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_topasmc.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_base_montecarlo.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_sparse_output.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_fredmc.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_particle_cutoff.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_base_pencilbeam.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/kernels/__pycache__/_calc_geo_dists_kernel.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/kernels/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_base_pencilbeam_particle.cpython-314.opt-1.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/__pycache__/_compose_beam_dijs.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ct/__pycache__/_hlut.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ct/__pycache__/_ct.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ct/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_base_pencilbeam_particle.cpython-314.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/cst/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/resample.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/cst/__pycache__/_cst.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/np2sitk.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_progress.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/__pycache__/_dij.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/datamodel.cpython-314.opt-1.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_paths.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/cst/__pycache__/_voi.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/datamodel.cpython-314.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_units.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_exceptions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_configurable.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_grids.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/__pycache__/_base_data.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/compat.cpython-314.opt-1.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/typing.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/_interpolation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/_reductions.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/compat.cpython-314.pyc: replacing with normalized version /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/_image_interpolation.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/jittable.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/_backends.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/_interpolation1d.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_reference.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/helpers.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_sources.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_provenance.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_conversion.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_options.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_presets.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_influence.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_tissue_lookup.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/tissues/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_factory.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_resolution.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_evaluator.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_base.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_kernel_sets.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/let_based_lq_models.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/zstar_based_lq_model.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/const_rbe.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/lq_models.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/__pycache__/_engine.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/kernel_based_lq_model.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/__pycache__/_units.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/__pycache__/_dvh.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/__pycache__/_dvh_plot.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/_settings.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/_resolve.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/_load_model.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/__pycache__/tabulated_rbe_models.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/_registry.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/modelhub/__pycache__/_preprocessor.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/_models.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/_plan_agents.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/_usage.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/_settings.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/__init__.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/ai/agents/__pycache__/_cst_agents.cpython-314.opt-1.pyc: rewriting with normalized contents /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/__pycache__/_qi.cpython-314.opt-1.pyc: rewriting with normalized contents Scanned 141 directories and 972 files, processed 316 inodes, 316 modified (6 replaced + 310 rewritten), 0 unsupported format, 0 errors + /usr/bin/linkdupes --brp /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr Scanned 140 directories and 972 files, considered 972 files, read 57 files, linked 1 files, 0 errors sum of sizes of linked files: 0 bytes Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.KtJa7r + umask 022 + cd /builddir/build/BUILD/python-pyradplan-0.8.0-build + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CFLAGS + CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + export CXXFLAGS + FFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FFLAGS + FCFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules ' + export FCFLAGS + VALAFLAGS=-g + export VALAFLAGS + RUSTFLAGS='-Copt-level=3 -Cdebuginfo=2 -Ccodegen-units=1 -Cstrip=none -Cforce-frame-pointers=yes -Clink-arg=-specs=/usr/lib/rpm/redhat/redhat-package-notes --cap-lints=warn' + export RUSTFLAGS + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + export LDFLAGS + LT_SYS_LIBRARY_PATH=/usr/lib64: + export LT_SYS_LIBRARY_PATH + CC=gcc + export CC + CXX=g++ + export CXX + cd pyradplan-0.8.0 + '[' '!' -f /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-modules ']' + PATH=/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin + PYTHONPATH=/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib64/python3.14/site-packages:/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages + _PYTHONSITE=/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib64/python3.14/site-packages:/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages + PYTHONDONTWRITEBYTECODE=1 + /usr/bin/python3 -sP /usr/lib/rpm/redhat/import_all_modules.py -f /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc44.aarch64-pyproject-modules -e 'pyRadPlan.ai.*' -e 'pyRadPlan.gui*' -e 'pyRadPlan.matRad*' -e pyRadPlan.optimization.solvers._ipopt Check import: pyRadPlan Check import: pyRadPlan.ai Check import: pyRadPlan.analysis Check import: pyRadPlan.biology Check import: pyRadPlan.biology.models Check import: pyRadPlan.biology.tissues Check import: pyRadPlan.core Check import: pyRadPlan.core.datamodel Check import: pyRadPlan.core.np2sitk Check import: pyRadPlan.core.resample Check import: pyRadPlan.core.xp_utils Check import: pyRadPlan.core.xp_utils.compat Check import: pyRadPlan.core.xp_utils.helpers Check import: pyRadPlan.core.xp_utils.jittable Check import: pyRadPlan.core.xp_utils.typing Check import: pyRadPlan.cst Check import: pyRadPlan.ct Check import: pyRadPlan.dij Check import: pyRadPlan.dose Check import: pyRadPlan.dose.engines Check import: pyRadPlan.dose.engines.kernels Check import: pyRadPlan.geometry Check import: pyRadPlan.geometry.lps Check import: pyRadPlan.io Check import: pyRadPlan.io.base Check import: pyRadPlan.io.dicom Check import: pyRadPlan.io.matlab Check import: pyRadPlan.io.npz Check import: pyRadPlan.io.pickle Check import: pyRadPlan.io.sitk_based Check import: pyRadPlan.io.sitk_based.base Check import: pyRadPlan.io.sitk_based.meta_image Check import: pyRadPlan.io.sitk_based.nifti Check import: pyRadPlan.io.sitk_based.nrrd Check import: pyRadPlan.machines Check import: pyRadPlan.machines.base Check import: pyRadPlan.machines.particles Check import: pyRadPlan.machines.particles.kernel Check import: pyRadPlan.machines.photons Check import: pyRadPlan.optimization Check import: pyRadPlan.optimization.objectives Check import: pyRadPlan.optimization.problems Check import: pyRadPlan.optimization.robustness Check import: pyRadPlan.optimization.solvers Check import: pyRadPlan.plan Check import: pyRadPlan.quantities Check import: pyRadPlan.raytracer Check import: pyRadPlan.scenarios Check import: pyRadPlan.stf Check import: pyRadPlan.stf.generators Check import: pyRadPlan.util Check import: pyRadPlan.util.helpers Check import: pyRadPlan.util.keyboard_listener Check import: pyRadPlan.util.logging_utils Check import: pyRadPlan.util.openmp Check import: pyRadPlan.visualization + export ARRAY_API_STRICT_API_VERSION=2023.12 + ARRAY_API_STRICT_API_VERSION=2023.12 + CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer ' + LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' + PATH=/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin + PYTHONPATH=/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib64/python3.14/site-packages:/builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages + PYTHONDONTWRITEBYTECODE=1 + PYTEST_ADDOPTS=' --ignore=/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir' + PYTEST_XDIST_AUTO_NUM_WORKERS=4 + /usr/bin/pytest -p no:cacheprovider test --ignore=test/ai --ignore=test/gui --ignore=test/packaging --ignore=test/test_matlabEngine.py --ignore=test/test_matrad_octave.py --ignore=test/test_octaveEngine.py ============================= test session starts ============================== platform linux -- Python 3.14.10, pytest-8.4.2, pluggy-1.6.0 rootdir: /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0 configfile: pyproject.toml plugins: anyio-4.13.0 collected 3418 items test/analysis/test_dvh.py ........... [ 0%] test/analysis/test_dvh_plot.py ....... [ 0%] test/analysis/test_qi.py ............................ [ 1%] test/analysis/test_units.py ........... [ 1%] test/biology/models/test_bio_model_factory.py ................... [ 2%] test/biology/models/test_check_tissues.py .............................. [ 3%] ... [ 3%] test/biology/models/test_const_rbe_bio_model.py ... [ 3%] test/biology/models/test_custom_model_extension.py ...F.... [ 3%] test/biology/models/test_empty_bio_model.py .. [ 3%] test/biology/models/test_engine_capability.py .......................... [ 4%] . [ 4%] test/biology/models/test_evaluator.py ........ [ 4%] test/biology/models/test_formalism_resolution.py ....................... [ 5%] .. [ 5%] test/biology/models/test_fragment_species_selection.py .............F [ 5%] test/biology/models/test_gpu_backend.py sssss [ 5%] test/biology/models/test_influence.py . [ 5%] test/biology/models/test_kernel_bio_model.py ...F.......F..F [ 6%] test/biology/models/test_kernel_let_model.py .........F. [ 6%] test/biology/models/test_reference_parameter_domain.py .........F....... [ 7%] ......................................................... [ 8%] test/biology/models/test_tabulated_kernel_model.py .........F [ 9%] test/biology/models/test_tissue_lookup.py ........FF.F....F..FF [ 9%] test/biology/models/test_tissue_quick_fixes.py ......... [ 10%] test/biology/models/test_zstar_bio_model.py ..FFF......... [ 10%] test/biology/tissues/test_tissue_properties.py ......................... [ 11%] ........................................................................ [ 13%] .. [ 13%] test/biology/tissues/test_tissue_reference_parameters.py ............... [ 13%] .............................. [ 14%] test/core/test_array_resample.py ................sssssssssssssssssssssss [ 15%] s..............sssssssssssssssssssss..sss..sss....ssssss....ssssss [ 17%] test/core/test_base_data.py ........................ [ 18%] test/core/test_configurable.py .................. [ 18%] test/core/test_coordinates.py . [ 18%] test/core/test_datamodel.py .. [ 19%] test/core/test_np2sitk.py .......... [ 19%] test/core/test_paths.py ...... [ 19%] test/core/test_progress.py ................ [ 19%] test/core/test_resample.py .... [ 20%] test/core/test_resample_array_api.py ..................FF..FF..FF..FFsss [ 21%] sssssssssssssssssssssssssssssssssssssssssssss..................sssssssss [ 23%] ssssssssssssssssss..sss.....Fsss..sss..........sssssssssssssss [ 25%] test/core/test_unit_registry.py .. [ 25%] test/core/xp_utils/compat/test_backend_consistency.py .Fsss.Fsss.Fsss.Fs [ 25%] ss..sss..sss [ 25%] test/core/xp_utils/compat/test_interp1d_torch.py ssssssss [ 26%] test/core/xp_utils/compat/test_interpnd.py FFF....sss [ 26%] test/core/xp_utils/compat/test_math_interp1d.py FFFFFFFFFFFFFFFF. [ 26%] test/core/xp_utils/compat/test_math_quantile.py .....ss [ 27%] test/core/xp_utils/helpers/test_device_parsing.py ......FsF.ssF.s [ 27%] test/core/xp_utils/helpers/test_namespace_conversion.py ...sssssss.sssss [ 28%] sssssssssssssssssss [ 28%] test/core/xp_utils/helpers/test_openblas_warning.py .......... [ 28%] test/core/xp_utils/helpers/test_scatter.py ...s [ 29%] test/core/xp_utils/test_backends.py ..s....... [ 29%] test/core/xp_utils/test_initialization.py .....ss..ssss.s.... [ 29%] test/core/xp_utils/test_interpolation.py ........ssssssssFFFFFFFFsssssss [ 30%] sssssssss..ssFFssss....ssss....ssssssss....ss..ssss.s...s..........sssss [ 32%] sssFFFFFFFFssssssssssssssss.. [ 33%] test/core/xp_utils/test_interpolation1d.py ............................. [ 34%] ...............................sssssssssssssssssssssssssssssssssssssssss [ 36%] sssssssssssssssssssFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF [ 38%] FFFFFFF...sssFFF.s...ss.. [ 39%] test/core/xp_utils/test_reductions.py ......sssssss.....ssssssssssss.s.s [ 40%] s.s.ss.s.ss.s.ss.s.sss [ 41%] test/cst/test_VOI.py ................................................... [ 42%] .................................................. [ 44%] test/cst/test_cst.py ................................................... [ 45%] ...... [ 45%] test/cst/test_cst_4d_ct.py ...... [ 45%] test/ct/test_ct.py .............................. [ 46%] test/ct/test_hlut.py . [ 46%] test/data/test_validate_test_data.py ..... [ 47%] test/dose/kernels/test_calc_geo_dists.py ssssssssssssss [ 47%] test/dose/test_base_pencilbeam.py .............. [ 47%] test/dose/test_bio_tissue_check.py F.FFF.F.FF.F..FFFFFFF.FFFF [ 48%] test/dose/test_default_bio_models.py FFFFFFFFFF..FFF.F [ 49%] test/dose/test_depth_preparation.py .s.s.s.s.s.s.s.s [ 49%] test/dose/test_dose_engine_base.py ........... [ 49%] test/dose/test_engine_reuse.py FFFFFF [ 50%] test/dose/test_factory.py .... [ 50%] test/dose/test_fred.py ....s.ssssssss................. [ 51%] test/dose/test_fred_bio.py ................. [ 51%] test/dose/test_hongpb.py .FFFFFFFFFFFFFFFFFFFFFFFF.F.FF [ 52%] test/dose/test_hongpb_bio.py .............FFFFFFF.FF.FF.F......F [ 53%] test/dose/test_particle_cutoff.py ....................ssssssssssssssssss [ 54%] ssFFFFFFFFFFFFFFFFFFFF.s...ss......ss.....sss..........sssssss.......... [ 56%] ..F.s...s.....s. [ 57%] test/dose/test_particle_indexing.py ........................ssssssssssss [ 58%] ssssssssssss................FFFFFFFFEEEEEEEEEEEEEEEEEEEEEEEE [ 60%] test/dose/test_particle_interpolators.py .sF.sF..FF.. [ 60%] test/dose/test_particle_lateral_cutoff.py F [ 60%] test/dose/test_pb_geodist.py .... [ 60%] test/dose/test_ray_geometry_preparation.py ........ssssssss........sssss [ 61%] sss....ssss....ssss...ssFFss.s.s..ss..ss.s.s.s.s [ 62%] test/dose/test_scenarios_pencilbeam.py FFFFFFFFFFFFFF.s.sFFFF...FFFFFFFF [ 63%] FFFFFFFFFFFFFFF.s.s [ 64%] test/dose/test_sparse_output.py .........s..s... [ 64%] test/dose/test_svdpb.py FFF [ 64%] test/dose/test_svdpb_bio.py FFF [ 64%] test/dose/test_svdpb_bixel.py ............ssssssssssss............ssssss [ 66%] ssssss.s.s.s.s [ 66%] test/dose/test_svdpb_interpolators.py ..ssFF [ 66%] test/dose/test_svdpb_sampling.py .s..s..s..s.....ssss....ssss [ 67%] test/dose/test_topas.py ............... [ 67%] test/dose/test_voxel_preparation.py ............... [ 68%] test/geometry/test_lps.py ............ss [ 68%] test/io/test_io_binary_import.py ............... [ 69%] test/io/test_io_dicom.py ........FF.....F..FFF.......................... [ 70%] .. [ 70%] test/io/test_io_factory.py ....... [ 70%] test/io/test_io_frontend.py ..................... [ 71%] test/io/test_io_matlab.py .............. [ 71%] test/io/test_io_npz.py ........ [ 72%] test/io/test_io_pickle.py ...... [ 72%] test/io/test_io_sitk.py ............................. [ 73%] test/machines/test_beam_focus.py ..... [ 73%] test/machines/test_beam_modifiers.py ........... [ 73%] test/machines/test_bundled_base_data.py ............ [ 74%] test/machines/test_energy_spectrum.py ...... [ 74%] test/machines/test_kernel_sets.py ................. [ 74%] test/machines/test_particle_kernel.py ......... [ 74%] test/machines/test_user_machines.py ............. [ 75%] test/optimization/robustness/test_robustness_contract.py .....F.....F... [ 75%] [ 75%] test/optimization/robustness/test_robustness_operators.py F............. [ 76%] .......FF.F.. [ 76%] test/optimization/robustness/test_smooth_max.py ....... [ 76%] test/optimization/robustness/test_variance_objective.py FF.F. [ 76%] test/optimization/test_dose_convention.py .............................. [ 77%] [ 77%] test/optimization/test_fluence_optiprob.py .......FFF...FFFFs [ 78%] test/optimization/test_ipax_solver.py .........sFss. [ 78%] test/optimization/test_ipopt_output.py ssssssss [ 78%] test/optimization/test_ipopt_solver.py ssssssss [ 79%] test/optimization/test_obj_history.py ..F.F.. [ 79%] test/optimization/test_objectives.py ............................F.ss... [ 80%] ..........FF.FFsssssssss [ 81%] test/optimization/test_opt_info.py .E.E.E.E..... [ 81%] test/optimization/test_problem_factory.py ........ [ 81%] test/optimization/test_robust_fluence_optiprob.py ..F.FF...FFF.F [ 82%] test/optimization/test_scipy_solver.py .FFFFF..........s [ 82%] test/optimization/test_solver_factory.py ............ [ 83%] test/quantities/test_alpha_dose_quantity.py ... [ 83%] test/quantities/test_dose_quantity.py ... [ 83%] test/quantities/test_effect_quantity.py ... [ 83%] test/quantities/test_let_dose_quantity.py ... [ 83%] test/quantities/test_let_quantity.py ..... [ 83%] test/quantities/test_multi_scenario_quantities.py ...........F..F..F..F. [ 84%] ....F [ 84%] test/quantities/test_rbe_x_dose_quantity.py .FF......FFFF..F [ 84%] test/quantities/test_resolver.py ............. [ 85%] test/quantities/test_sqrt_beta_dose_quantity.py .... [ 85%] test/scenarios/test_scenario_dimensions.py .................. [ 85%] test/scenarios/test_scenario_gridded.py ................................ [ 86%] ......... [ 86%] test/scenarios/test_scenario_models.py ....................... [ 87%] test/scenarios/test_scenario_random.py ......... [ 87%] test/scenarios/test_scenario_set.py .................................... [ 88%] [ 88%] test/stf/test_beam_angle_presets.py ..... [ 89%] test/stf/test_beamlet.py .......... [ 89%] test/stf/test_stf.py ...FF.... [ 89%] test/stf/test_stf_gen.py ........FF..FF.FF..................... [ 90%] test/test_dij.py ....................s [ 91%] test/test_dij_scenarios.py ......................s................. [ 92%] test/test_grid.py .................... [ 93%] test/test_helpers.py ............ [ 93%] test/test_keyboard_listener.py .......... [ 93%] test/test_lazy_imports.py .s...... [ 94%] test/test_logging_utils.py ............ [ 94%] test/test_machine_model.py .................. [ 94%] test/test_openmp.py .................................s....... [ 96%] test/test_plan.py ........................................... [ 97%] test/test_raytracer_kernels.py ssss.s [ 97%] test/test_raytracersiddon.py .FF.FFsFs.....sFs [ 98%] test/test_scenarios.py ......... [ 98%] test/test_settings.py .................... [ 98%] test/visualization/test_plot_multiple_slices.py ...................... [ 99%] test/visualization/test_plot_slice.py ................ [100%] ==================================== ERRORS ==================================== _ ERROR at setup of test_particle_support_selection[strict2025-full-False-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-False-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-False-all] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-False-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-True-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-True-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-True-all] __ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-full-True-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-False-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-False-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-False-all] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-False-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-True-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-True-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-True-all] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-constant-True-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-False-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-False-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-False-all] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-False-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-True-empty] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-True-none] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-True-all] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _ ERROR at setup of test_particle_support_selection[strict2025-table-True-mixed] _ request = > @pytest.fixture(params=["numpy", "cupy", "strict2023", "strict2025"]) def xp(request): """Exercise native arrays and strict versions without boolean indexing.""" if request.param.startswith("strict"): strict = pytest.importorskip("array_api_strict") # Table-cutoff interpolation already requires clip, introduced in 2023.12. version = request.param.removeprefix("strict") + ".12" > with strict.ArrayAPIStrictFlags(api_version=version, boolean_indexing=False): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: in __enter__ set_array_api_strict_flags(**self.kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def set_array_api_strict_flags( *, api_version=None, boolean_indexing=None, data_dependent_shapes=None, enabled_extensions=None, ): """ Set the array-api-strict flags to the specified values. Flags are global variables that enable or disable array-api-strict behaviors. The flags can also be changed by setting :ref:`environment variables `. .. note:: This function is **not** part of the array API standard. It only exists in array-api-strict. Parameters ---------- api_version : str, optional The version of the standard to use. Supported versions are: ``{supported_versions}``. The default version number is ``{default_version!r}``. Note that 2021.12 is supported, but currently gives the same thing as 2022.12 (except that the fft extension will be disabled). 2023.12 support is experimental. Some features in 2023.12 may still be missing, and it hasn't been fully tested. A future version of array-api-strict will change the default version to 2023.12. boolean_indexing : bool, optional Whether indexing by a boolean array is supported. This flag is enabled by default. Note that although boolean array indexing does result in data-dependent shapes, this flag is independent of the `data_dependent_shapes` flag (see below). data_dependent_shapes : bool, optional Whether data-dependent shapes are enabled in array-api-strict. This flag is enabled by default. Array libraries that use computation graphs may not be able to support functions whose output shapes depend on the input data. The functions that make use of data-dependent shapes, and are therefore disabled by setting this flag to False are - `unique_all()`, `unique_counts()`, `unique_inverse()`, and `unique_values()`. - `nonzero()` - `repeat()` when the `repeats` argument is an array (requires the 2023.12 version of the standard) Note that while boolean indexing is also data-dependent, it is controlled by a separate `boolean_indexing` flag (see above). See https://data-apis.org/array-api/latest/design_topics/data_dependent_output_shapes.html for more details. enabled_extensions : list of str, optional A list of extensions that are enabled in array-api-strict. The default is ``{default_extensions}``. Note that some extensions require a minimum version of the standard. Examples -------- >>> from array_api_strict import set_array_api_strict_flags >>> # Set the standard version to 2021.12 >>> set_array_api_strict_flags(api_version="2021.12") >>> # Disable data-dependent shapes and boolean indexing >>> set_array_api_strict_flags(data_dependent_shapes=False, boolean_indexing=False) >>> # Enable only the linalg extension (disable the fft extension) >>> set_array_api_strict_flags(enabled_extensions=["linalg"]) See Also -------- get_array_api_strict_flags: Get the current values of flags. reset_array_api_strict_flags: Reset the flags to their default values. ArrayAPIStrictFlags: A context manager to temporarily set the flags. """ global API_VERSION, BOOLEAN_INDEXING, DATA_DEPENDENT_SHAPES, ENABLED_EXTENSIONS if api_version is not None: if api_version not in supported_versions: > raise ValueError(f"Unsupported standard version {api_version!r}") E ValueError: Unsupported standard version '2025.12' /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:142: ValueError _____________ ERROR at setup of test_opt_info_is_populated[scipy] ______________ request = > small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.fixture def optimized(request, small_proton_case): """Run a full optimization with ``opt_info`` for the solver named by the test parameter.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": request.param, "display": False, "max_iter": 25} opt_info = {} > w = fluence_optimization(ct, cst, stf, dij, pln, opt_info=opt_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_opt_info.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/_fluence_optimization.py:95: in fluence_optimization x, result_info = planning_prob.solve(_ct, _cst, _stf, _dij) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log setup ------------------------------ WARNING pyRadPlan.optimization.problems._factory:_factory.py:138 No PlanningProblem specified in Plan. Using first available problem nonlin_fluence. _____________ ERROR at setup of test_result_info_is_a_dict[scipy] ______________ request = > small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.fixture def optimized(request, small_proton_case): """Run a full optimization with ``opt_info`` for the solver named by the test parameter.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": request.param, "display": False, "max_iter": 25} opt_info = {} > w = fluence_optimization(ct, cst, stf, dij, pln, opt_info=opt_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_opt_info.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/_fluence_optimization.py:95: in fluence_optimization x, result_info = planning_prob.solve(_ct, _cst, _stf, _dij) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log setup ------------------------------ WARNING pyRadPlan.optimization.problems._factory:_factory.py:138 No PlanningProblem specified in Plan. Using first available problem nonlin_fluence. _________ ERROR at setup of test_num_iter_comes_from_the_solver[scipy] _________ request = > small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.fixture def optimized(request, small_proton_case): """Run a full optimization with ``opt_info`` for the solver named by the test parameter.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": request.param, "display": False, "max_iter": 25} opt_info = {} > w = fluence_optimization(ct, cst, stf, dij, pln, opt_info=opt_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_opt_info.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/_fluence_optimization.py:95: in fluence_optimization x, result_info = planning_prob.solve(_ct, _cst, _stf, _dij) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log setup ------------------------------ WARNING pyRadPlan.optimization.problems._factory:_factory.py:138 No PlanningProblem specified in Plan. Using first available problem nonlin_fluence. ______ ERROR at setup of test_obj_history_records_every_evaluation[scipy] ______ request = > small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.fixture def optimized(request, small_proton_case): """Run a full optimization with ``opt_info`` for the solver named by the test parameter.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": request.param, "display": False, "max_iter": 25} opt_info = {} > w = fluence_optimization(ct, cst, stf, dij, pln, opt_info=opt_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_opt_info.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/_fluence_optimization.py:95: in fluence_optimization x, result_info = planning_prob.solve(_ct, _cst, _stf, _dij) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log setup ------------------------------ WARNING pyRadPlan.optimization.problems._factory:_factory.py:138 No PlanningProblem specified in Plan. Using first available problem nonlin_fluence. =================================== FAILURES =================================== __________________ test_custom_model_runs_in_particle_engine ___________________ registered_custom_model = test_data_protons_raw = {'__globals__': [], '__header__': b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Fri Apr 11 14:50:38 2025', '__... 'alphaX': 0.1, ...}, {'className': 'DoseObjectives.matRad_SquaredOverdosing', 'parameters': 0, 'penalty': 400}]], ...} def test_custom_model_runs_in_particle_engine(registered_custom_model, test_data_protons_raw): """The public model/evaluator contract integrates with the particle dose engine.""" pln = validate_pln(test_data_protons_raw["pln"]) ct = validate_ct(test_data_protons_raw["ct"]) cst = validate_cst(test_data_protons_raw["cst"], ct=ct) stf = validate_stf(test_data_protons_raw["stf"]) pln.bio_model = {"model": registered_custom_model.model, "slope": 0.03} > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_custom_model_extension.py:142: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid ______________ test_spectrum_tables_are_cached_per_logical_device ______________ def test_spectrum_tables_are_cached_per_logical_device(): """Every array_api_strict device shares one DLPack tuple, so it cannot be the cache key.""" import array_api_compat import array_api_strict as xps class _Machine: energies = [100.0] pb_kernels = {100.0: _kernel([(1, 1.0), (6, np.nan)])} machine = _Machine() evaluator = TabulatedAlphaBetaModel().evaluator( machine, { "alpha_x": np.asarray([[0.1]]), "beta_x": np.asarray([[0.05]]), "tissue_class": np.asarray([TissueProperties(alpha_x=0.1, beta_x=0.05)]), "tissue_class_ix": np.asarray([[0]]), }, ) # built by hand: xp_utils.to_namespace cannot express array_api_strict's logical devices depths = np.asarray(machine.pb_kernels[100.0].depths) > devices = [xps.Device("CPU_DEVICE"), xps.Device("device1")] ^^^^^^^^^^ test/biology/models/test_fragment_species_selection.py:220: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ____________ test_KernelBasedLQModel_evaluate_mixed_tissue_classes _____________ machine = voxel_params = {'alpha_x': array([[0.1], [0.5], [0. ]]), 'beta_x': array([[0.05], [0.05], [0. ]]), 'tiss...(cell_line=None, model='Generic', alpha_x=0.5, beta_x=0.05)], dtype=object), 'tissue_class_ix': array([0, 1, 0])} def test_KernelBasedLQModel_evaluate_mixed_tissue_classes(machine, voxel_params): evaluator = KernelBasedLQModel().evaluator(machine, voxel_params) # interpolated kernels: (n_tissue_classes, n_voxels) kernels = { "alpha": xp.asarray([[1.0, 1.0, 1.0, 1.0], [2.0, 2.0, 2.0, 2.0]]), "beta": xp.asarray([[4.0, 4.0, 4.0, 4.0], [5.0, 5.0, 5.0, 5.0]]), } > result = evaluator.evaluate( BioEvaluationContext( { "alpha_x": xp.asarray([0.1, 0.5, 0.1, 0.0]), "beta_x": xp.asarray([0.05, 0.05, 0.05, 0.0]), "tissue_class_ix": xp.asarray([0, 1, 0, 0]), **kernels, } ) ) test/biology/models/test_kernel_bio_model.py:97: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1., 1., 1.], [2., 2., 2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1, 0, 0], dtype=array_api_strict.int64), Array([0, 1, 2, 3], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_declared_tissue_classes_are_mapped_onto_kernel_rows_by_value _______ voxel_params = {'alpha_x': array([[0.1], [0.5], [0. ]]), 'beta_x': array([[0.05], [0.05], [0. ]]), 'tiss...(cell_line=None, model='Generic', alpha_x=0.5, beta_x=0.05)], dtype=object), 'tissue_class_ix': array([0, 1, 0])} def test_declared_tissue_classes_are_mapped_onto_kernel_rows_by_value(voxel_params): """A tissueParameters order differing from the kernel order still selects the own row.""" machine = _Machine([0.1, 0.5], [0.05, 0.05]) machine.tissue_properties = list(reversed(machine.tissue_properties)) model = KernelBasedLQModel() classes = model.kernel_tissue_classes(machine) assert [tissue.alpha_x for tissue in classes] == [0.1, 0.5] # CST tissue 0 has alpha_x = 0.1 (kernel row 0), tissue 1 has alpha_x = 0.5 (row 1) evaluator = model.evaluator(machine, voxel_params) > assert _evaluate_alpha(evaluator, [0, 1]) == [1.0, 2.0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_kernel_bio_model.py:225: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/biology/models/test_kernel_bio_model.py:200: in _evaluate_alpha result = evaluator.evaluate( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1.], [2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1], dtype=array_api_strict.int64), Array([0, 1], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________ test_machine_without_tissue_parameters_uses_the_kernel_classes ________ voxel_params = {'alpha_x': array([[0.1], [0.5], [0. ]]), 'beta_x': array([[0.05], [0.05], [0. ]]), 'tiss...(cell_line=None, model='Generic', alpha_x=0.5, beta_x=0.05)], dtype=object), 'tissue_class_ix': array([0, 1, 0])} def test_machine_without_tissue_parameters_uses_the_kernel_classes(voxel_params): """Without tissueParameters meta data the classes come from the kernels themselves.""" carbon = load_from_name("carbon", "Generic") data = { name: getattr(carbon, name) for name in carbon.model_fields_set if name != "tissue_properties" } machine = IonAccelerator.model_validate(data) assert "tissue_properties" not in machine.model_fields_set assert len(machine.tissue_properties) == 1 model = KernelBasedLQModel() classes = model.kernel_tissue_classes(machine) assert [(t.alpha_x, t.beta_x) for t in classes] == [(0.1, 0.05), (0.5, 0.05)] # an alpha_x = 0.5 structure is served by the second kernel row evaluator = model.evaluator(machine, voxel_params) > assert _evaluate_alpha(evaluator, [0, 1]) == [1.0, 2.0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_kernel_bio_model.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/biology/models/test_kernel_bio_model.py:200: in _evaluate_alpha result = evaluator.evaluate( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1.], [2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1], dtype=array_api_strict.int64), Array([0, 1], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________________________ test_LinearScaling_alpha_beta _________________________ sample_parameters = (Array([0.1, 0.1, 0.1], dtype=array_api_strict.float64), Array([0.05, 0.05, 0.05], dtype=array_api_strict.float64)) def test_LinearScaling_alpha_beta(sample_parameters): alpha_x, beta_x = sample_parameters lam, corr, upper, lower = 0.008, 0.5, 30.0, 0.3 # below, inside and above the LET thresholds kernels = {"let": xp.asarray([0.1, 5.0, 40.0])} let_clipped = np.asarray([lower, 5.0, upper]) alpha_0 = np.asarray(alpha_x) - lam * corr expected_alpha = alpha_0 + lam * let_clipped > alpha, beta = _evaluate(LinearScaling(), alpha_x, beta_x, kernels) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_kernel_let_model.py:119: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/biology/models/test_kernel_let_model.py:29: in _evaluate result = evaluator.evaluate( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:297: in _evaluate alpha, beta = self.model.alpha_beta( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/let_based_lq_models.py:75: in alpha_beta rbe_min, rbe_max = self.rbe_min_max( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/let_based_lq_models.py:256: in rbe_min_max rbe_max = xp.where(alpha_x > 0, alpha / xp.where(alpha_x > 0, alpha_x, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True], dtype=array_api_strict.bool) x1 = Array([0.1, 0.1, 0.1], dtype=array_api_strict.float64), x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ___ test_outside_structure_voxels_evaluate_to_zero_array_api[LinearScaling] ____ model_cls = @pytest.mark.parametrize("model_cls", ALL_MODELS) def test_outside_structure_voxels_evaluate_to_zero_array_api(model_cls): """The masking uses only array-API operations, so it works on any backend.""" > influence = _influence(model_cls(), [0.0, 0.1], [0.0, 0.05], [1.0, 1.0], [3.0, 3.0], xp=xps) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_reference_parameter_domain.py:87: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/biology/models/test_reference_parameter_domain.py:33: in _influence return evaluator.evaluate_influence( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:235: in evaluate_influence self._evaluate_influence(context), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:274: in _evaluate_influence result = self.evaluate(context) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:297: in _evaluate alpha, beta = self.model.alpha_beta( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/let_based_lq_models.py:75: in alpha_beta rbe_min, rbe_max = self.rbe_min_max( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_models/let_based_lq_models.py:256: in rbe_min_max rbe_max = xp.where(alpha_x > 0, alpha / xp.where(alpha_x > 0, alpha_x, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True], dtype=array_api_strict.bool) x1 = Array([1. , 0.1], dtype=array_api_strict.float64), x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ____________________ test_TabulatedAlphaBetaModel_evaluate _____________________ machine = voxel_params = {'alpha_x': array([[0.1], [0. ]]), 'beta_x': array([[0.05], [0. ]]), 'tissue_class': array([TissueProperties(cell_line=None, model='Generic', alpha_x=0.1, beta_x=0.05)], dtype=object), 'tissue_class_ix': array([0, 0])} def test_TabulatedAlphaBetaModel_evaluate(machine, voxel_params): evaluator = TabulatedAlphaBetaModel().evaluator(machine, voxel_params) # interpolated kernels: (n_tissue_classes, n_voxels) kernels = { "alpha": xp.asarray([[1.0, 2.0, 3.0, 4.0]]), "sqrt_beta": xp.asarray([[1.0, 2.0, 1.0, 2.0]]), } > result = evaluator.evaluate( BioEvaluationContext( { "alpha_x": xp.asarray([0.1, 0.1, 0.0, 0.1]), "beta_x": xp.asarray([0.05, 0.05, 0.0, 0.05]), "tissue_class_ix": xp.asarray([0, 0, 0, 0]), **kernels, } ) ) test/biology/models/test_tabulated_kernel_model.py:245: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 2., 3., 4.]], dtype=array_api_strict.float64) key = (Array([0, 0, 0, 0], dtype=array_api_strict.int64), Array([0, 1, 2, 3], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______________________________ test_exact_gather _______________________________ lookup = def test_exact_gather(lookup): context = { "alpha_x": xp.asarray([0.1, 0.5, 0.1, 0.0]), "beta_x": xp.asarray([0.05, 0.05, 0.05, 0.0]), "tissue_class_ix": xp.asarray([0, 1, 0, 0]), # interpolated kernels: (n_classes, n_voxels) "alpha": xp.asarray([[1.0, 1.0, 1.0, 1.0], [2.0, 2.0, 2.0, 2.0]]), "beta": xp.asarray([[4.0, 4.0, 4.0, 4.0], [5.0, 5.0, 5.0, 5.0]]), "let": xp.asarray([9.0, 9.0, 9.0, 9.0]), # not requested, must be ignored } > rows = lookup.gather(context, ["alpha", "beta"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_tissue_lookup.py:98: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1., 1., 1.], [2., 2., 2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1, 0, 0], dtype=array_api_strict.int64), Array([0, 1, 2, 3], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________ test_exact_gather_takes_one_dimensional_kernels_per_voxel ___________ lookup = def test_exact_gather_takes_one_dimensional_kernels_per_voxel(lookup): """A kernel that is not tabulated per tissue class is used as-is.""" context = { "alpha_x": xp.asarray([0.1, 0.5]), "tissue_class_ix": xp.asarray([0, 1]), "zs": xp.asarray([7.0, 8.0]), } > rows = lookup.gather(context, ["zs"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/biology/models/test_tissue_lookup.py:111: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:231: in gather name: context[name][voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([7., 8.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_exact_gather_skips_the_check_once_the_grid_is_validated _________ lookup = def test_exact_gather_skips_the_check_once_the_grid_is_validated(lookup): """Per-bixel indices are a subset of the validated grid, so the check is redundant.""" lookup.validate({"tissue_class_ix": np.asarray([[1], [0]])}) > rows = lookup.gather( { "alpha_x": xp.asarray([0.5, 0.1]), "tissue_class_ix": xp.asarray([1, 0]), "alpha": xp.asarray([[1.0, 1.0], [2.0, 2.0]]), }, ["alpha"], ) test/biology/models/test_tissue_lookup.py:131: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1.], [2., 2.]], dtype=array_api_strict.float64) key = (Array([1, 0], dtype=array_api_strict.int64), Array([0, 1], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________ test_gather_tissue_parameters_matches_the_per_bixel_conversion ________ def test_gather_tissue_parameters_matches_the_per_bixel_conversion(): """The cached class parameters give identical results on every device.""" classes = [ MKMTissueProperties(r_nucleus=3.9, r_domain=0.32, alpha_0=0.1, beta_0=0.05), MKMTissueProperties(r_nucleus=3.9, r_domain=0.32, alpha_0=0.2, beta_0=0.06), ] lookup = ExactClassLookup(classes, [0, 1]) > for device in (None, xp.Device("device1")): ^^^^^^^^^ test/biology/models/test_tissue_lookup.py:250: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ______________ test_reference_cache_distinguishes_logical_devices ______________ lookup = def test_reference_cache_distinguishes_logical_devices(lookup): """Every array_api_strict device shares the DLPack tuple (1, 0), so it cannot be the key.""" > devices = [xp.Device("CPU_DEVICE"), xp.Device("device1")] ^^^^^^^^^ test/biology/models/test_tissue_lookup.py:288: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ______________ test_gather_works_on_a_non_default_logical_device _______________ lookup = def test_gather_works_on_a_non_default_logical_device(lookup): """A cached reference from another device must not leak into this one.""" lookup.class_index(xp.asarray([0])) # warm the CPU_DEVICE entry > device = xp.Device("device1") ^^^^^^^^^ test/biology/models/test_tissue_lookup.py:302: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _______ test_MKM_evaluate_combines_kernel_rows_with_the_class_parameters _______ machine = ._Machine object at 0xffff8cd3bcb0> voxel_params = {'alpha_x': array([[0.1], [0.2]]), 'beta_x': array([[0.05], [0.06]]), 'tissue_class': array([MKMTissuePr...0.2, beta_0=0.06, reference_radiation='xray_200kV')], dtype=object), 'tissue_class_ix': array([[0], [1]])} def test_MKM_evaluate_combines_kernel_rows_with_the_class_parameters(machine, voxel_params): """alpha = alpha_0 + beta_0 * zs and beta = beta_0, both of the voxel's own class.""" evaluator = MKM().evaluator(machine, voxel_params) > result = evaluator.evaluate( BioEvaluationContext( { "alpha_x": xp.asarray([0.1, 0.2, 0.2]), "beta_x": xp.asarray([0.05, 0.06, 0.06]), "tissue_class_ix": xp.asarray([0, 1, 1]), # interpolated zs kernels: (n_tissue_classes, n_voxels) "zs": xp.asarray([[1.0, 1.0, 1.0], [2.0, 2.0, 2.0]]), } ) ) test/biology/models/test_zstar_bio_model.py:74: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1., 1.], [2., 2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1, 1], dtype=array_api_strict.int64), Array([0, 1, 2], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____________________ test_mkm_copies_no_host_data_per_bixel ____________________ machine = ._Machine object at 0xffff8cd3a270> voxel_params = {'alpha_x': array([[0.1], [0.2]]), 'beta_x': array([[0.05], [0.06]]), 'tissue_class': array([MKMTissuePr...0.2, beta_0=0.06, reference_radiation='xray_200kV')], dtype=object), 'tissue_class_ix': array([[0], [1]])} monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff8a35c7c0> def test_mkm_copies_no_host_data_per_bixel(machine, voxel_params, monkeypatch): """Evaluating further bixels only indexes arrays already on the device.""" evaluator = MKM().evaluator(machine, voxel_params) rng = np.random.default_rng(1) bixels = [ BioEvaluationContext( { "alpha_x": xp.asarray([0.1, 0.2, 0.2]), "beta_x": xp.asarray([0.05, 0.06, 0.06]), "tissue_class_ix": xp.asarray(rng.integers(0, 2, 3)), "physical_dose": xp.asarray(rng.random(3)), "zs": xp.asarray(rng.random((2, 3))), } ) for _ in range(10) ] host_conversions = [] asarray = xp.asarray def counting(obj, *args, **kwargs): if isinstance(obj, (list, tuple, np.ndarray)): host_conversions.append(obj) return asarray(obj, *args, **kwargs) monkeypatch.setattr(xp, "asarray", counting) > evaluator.evaluate_influence(bixels[0]) test/biology/models/test_zstar_bio_model.py:117: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:235: in evaluate_influence self._evaluate_influence(context), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:274: in _evaluate_influence result = self.evaluate(context) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[0.42332645, 0.82770259, 0.40919914], [0.54959369, 0.02755911, 0.75351311]], dtype=array_api_strict.float64) key = (Array([0, 1, 1], dtype=array_api_strict.int64), Array([0, 1, 2], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____ test_MKM_evaluate_influence_weights_the_class_parameters_with_the_dose ____ machine = ._Machine object at 0xffffac546510> voxel_params = {'alpha_x': array([[0.1], [0.2]]), 'beta_x': array([[0.05], [0.06]]), 'tissue_class': array([MKMTissuePr...0.2, beta_0=0.06, reference_radiation='xray_200kV')], dtype=object), 'tissue_class_ix': array([[0], [1]])} def test_MKM_evaluate_influence_weights_the_class_parameters_with_the_dose(machine, voxel_params): evaluator = MKM().evaluator(machine, voxel_params) physical_dose = xp.asarray([2.0, 4.0]) > result = evaluator.evaluate_influence( BioEvaluationContext( { "alpha_x": xp.asarray([0.1, 0.2]), "beta_x": xp.asarray([0.05, 0.06]), "tissue_class_ix": xp.asarray([0, 1]), "physical_dose": physical_dose, "zs": xp.asarray([[1.0, 1.0], [2.0, 2.0]]), } ) ) test/biology/models/test_zstar_bio_model.py:130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:235: in evaluate_influence self._evaluate_influence(context), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:274: in _evaluate_influence result = self.evaluate(context) ^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:223: in evaluate self._evaluate(context), self.model.output_quantities, "output quantities" ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:322: in _evaluate alpha, beta = self.model.alpha_beta_from_kernel_rows(self._gather_rows(context)) ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_evaluator.py:317: in _gather_rows rows = self.lookup.gather(context, self.kernel_fields) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/biology/models/_tissue_lookup.py:233: in gather else context[name][row_ix, voxel_ix] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([[1., 1.], [2., 2.]], dtype=array_api_strict.float64) key = (Array([0, 1], dtype=array_api_strict.int64), Array([0, 1], dtype=array_api_strict.int64)) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_enums_extrapolation_and_backend[array_api_strict-nearest-23] _______ xp = method = 23, extrapolate = 'nearest' @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _______ test_enums_extrapolation_and_backend[array_api_strict-nearest-4] _______ xp = method = 4, extrapolate = 'nearest' @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _______ test_enums_extrapolation_and_backend[array_api_strict--3.25-23] ________ xp = method = 23, extrapolate = -3.25 @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_enums_extrapolation_and_backend[array_api_strict--3.25-4] ________ xp = method = 4, extrapolate = -3.25 @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _______ test_enums_extrapolation_and_backend[array_api_strict-False-23] ________ xp = method = 23, extrapolate = False @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_enums_extrapolation_and_backend[array_api_strict-False-4] ________ xp = method = 4, extrapolate = False @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_enums_extrapolation_and_backend[array_api_strict-True-23] ________ xp = method = 23, extrapolate = True @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_enums_extrapolation_and_backend[array_api_strict-True-4] _________ xp = method = 4, extrapolate = True @pytest.mark.parametrize( "method", [sitk.sitkLinear, sitk.sitkNearestNeighbor, sitk.sitkBSpline, sitk.sitkGaussian] ) @pytest.mark.parametrize("extrapolate", ["nearest", -3.25, False, True]) def test_enums_extrapolation_and_backend(xp, method, extrapolate): """All enum requests retain native semantics, including host fallback modes.""" values, image, target = images() expected = sitk.GetArrayFromImage( resample_image(image, interpolator=method, target_grid=target, extrapolate=extrapolate) ) input_array = xp.asarray(values) > actual = resample_array( input_array, image, interpolator=method, target_grid=target, extrapolate=extrapolate ) test/core/test_resample_array_api.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________ test_small_bspline_fallback_is_preserved[array_api_strict] __________ xp = def test_small_bspline_fallback_is_preserved(xp): """The existing native small-image fallback still works on device inputs.""" values = np.arange(27, dtype=np.float32).reshape(3, 3, 3) image = sitk.GetImageFromArray(values) grid = Grid.from_sitk_image(image).resample(dict(x=0.8, y=0.7, z=0.9)) > actual = resample_array(xp.asarray(values), image, target_grid=grid) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/test_resample_array_api.py:152: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/resample.py:187: in resample_array return to_namespace(xp, result, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________________ test_interp1d_2d_boundaries[array_api_strict] _________________ xp = @pytest.mark.parametrize("xp", BACKENDS) def test_interp1d_2d_boundaries(xp): """Use the same 2D boundary semantics on every backend.""" x = xp.asarray([0.0, 1.0, 2.0], dtype=xp.float32) y = xp.asarray([[0.0, 1.0, 2.0], [10.0, 11.0, 12.0]], dtype=xp.float32) xq = xp.asarray([-1.0, 0.5, 3.0], dtype=xp.float32) > default_result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_backend_consistency.py:60: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____________ test_interp1d_container_boundaries[array_api_strict] _____________ xp = @pytest.mark.parametrize("xp", BACKENDS) def test_interp1d_container_boundaries(xp): """Allow scalar but reject row-wise boundaries for y containers.""" x = xp.asarray([0.0, 1.0, 2.0], dtype=xp.float32) xq = xp.asarray([-1.0, 0.5, 3.0], dtype=xp.float32) y1 = xp.asarray([0.0, 1.0, 2.0], dtype=xp.float32) y2 = xp.asarray([10.0, 11.0, 12.0], dtype=xp.float32) row_left = xp.asarray([-5.0, -6.0], dtype=xp.float32) containers = ([y1, y2], (y1, y2), {"first": y1, "second": y2}) for y in containers: > result = interp1d(xq, x, y, left=-5.0, right=99.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_backend_consistency.py:86: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:408: in interp1d res = [_interpolation(xq, x, y_arr, left, right) for y_arr in y] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_interp1d_multidimensional_queries[array_api_strict] ___________ xp = @pytest.mark.parametrize("xp", BACKENDS) def test_interp1d_multidimensional_queries(xp): """Preserve multidimensional query shapes for 2D y arrays.""" x = xp.asarray([0.0, 1.0, 2.0], dtype=xp.float32) y = xp.asarray([[0.0, 1.0, 2.0], [10.0, 11.0, 12.0]], dtype=xp.float32) xq = xp.asarray([[-1.0, 0.5], [1.5, 3.0]], dtype=xp.float32) left = xp.asarray([-5.0, -6.0], dtype=xp.float32) right = xp.asarray([98.0, 99.0], dtype=xp.float32) > result = interp1d(xq, x, y, left=left, right=right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_backend_consistency.py:108: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_interpnd_bounds_and_multiple_queries[array_api_strict] __________ xp = @pytest.mark.parametrize("xp", BACKENDS) def test_interpnd_bounds_and_multiple_queries(xp): """Interpolate multiple points and apply the requested bounds behavior.""" gx = xp.asarray([0.0, 1.0, 3.0], dtype=xp.float32) gy = xp.asarray([0.0, 2.0, 3.0], dtype=xp.float32) y = xp.asarray( [[0.0, 20.0, 30.0], [1.0, 21.0, 31.0], [3.0, 23.0, 33.0]], dtype=xp.float32, ) xq = xp.asarray([[0.5, 1.0], [-1.0, 1.0], [2.0, 4.0]], dtype=xp.float32) > result = interpnd(xq, (gx, gy), y) ^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_backend_consistency.py:125: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 3.], dtype=array_api_strict.float32) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______________________ test_interpnd_generic_returns[2d] _______________________ xq = Array([[0.25, 0.5 ]], dtype=array_api_strict.float64) x = (Array([0., 1.], dtype=array_api_strict.float64), Array([0., 1.], dtype=array_api_strict.float64)) y = Array([[ 0., 10.], [ 1., 11.]], dtype=array_api_strict.float64) expected = Array([5.25], dtype=array_api_strict.float64) @pytest.mark.parametrize( "xq, x, y, expected", [_interp_input_2d(strictxp), _interp_input_3d(strictxp)], ids=["2d", "3d"], ) def test_interpnd_generic_returns(xq, x, y, expected): > result = interpnd(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_interpnd.py:113: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1.], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______________________ test_interpnd_generic_returns[3d] _______________________ xq = Array([[0.25, 0.5 , 0.75]], dtype=array_api_strict.float64) x = (Array([0., 1.], dtype=array_api_strict.float64), Array([0., 1.], dtype=array_api_strict.float64), Array([0., 1.], dtype=array_api_strict.float64)) y = Array([[[ 0., 100.], [ 10., 110.]], [[ 1., 101.], [ 11., 111.]]], dtype=array_api_strict.float64) expected = Array([80.25], dtype=array_api_strict.float64) @pytest.mark.parametrize( "xq, x, y, expected", [_interp_input_2d(strictxp), _interp_input_3d(strictxp)], ids=["2d", "3d"], ) def test_interpnd_generic_returns(xq, x, y, expected): > result = interpnd(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_interpnd.py:113: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1.], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_interpnd_generic_2d_handles_descending_axes _______________ def test_interpnd_generic_2d_handles_descending_axes(): xq, _, __, expected = _interp_input_2d(strictxp) gx = strictxp.asarray([1.0, 0.0], dtype=strictxp.float64) gy = strictxp.asarray([1.0, 0.0], dtype=strictxp.float64) x = (gx, gy) y = strictxp.asarray( [ [11.0, 1.0], # x = 1 [10.0, 0.0], # x = 0 ], dtype=strictxp.float64, ) > result = interpnd(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_interpnd.py:132: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1.], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________________________ test_interp1d_basic[dtype0] __________________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_basic(dtype): x = xp.asarray([0.0, 1.0, 2.0, 3.0], dtype=dtype) y = xp.asarray([0.0, 1.0, 4.0, 9.0], dtype=dtype) xq = xp.asarray([0.5, 1.5, 2.5], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:15: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2., 3.], dtype=array_api_strict.float64) key = Array([0, 1, 2], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 2] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________________________ test_interp1d_basic[dtype1] __________________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_basic(dtype): x = xp.asarray([0.0, 1.0, 2.0, 3.0], dtype=dtype) y = xp.asarray([0.0, 1.0, 4.0, 9.0], dtype=dtype) xq = xp.asarray([0.5, 1.5, 2.5], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:15: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2., 3.], dtype=array_api_strict.float32) key = Array([0, 1, 2], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 2] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________________ test_interp1d_on_points[dtype0] ________________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_on_points(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = x > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:26: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________________ test_interp1d_on_points[dtype1] ________________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_on_points(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = x > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:26: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________________________ test_interp1d_2darray[dtype0] _________________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_2darray(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([[0.0, 1.0, 4.0], [0.0, 1.0, 4.0]], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:36: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________________________ test_interp1d_2darray[dtype1] _________________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_2darray(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([[0.0, 1.0, 4.0], [0.0, 1.0, 4.0]], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:36: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_interp1d_multiple_y_stack_sequence[dtype0] ________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_multiple_y_stack_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) y2 = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, [y1, y2], stack=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:52: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_interp1d_multiple_y_stack_sequence[dtype1] ________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_multiple_y_stack_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) y2 = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, [y1, y2], stack=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:52: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________________ test_interp1_multiple_y_sequence[dtype0] ___________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1_multiple_y_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) y2 = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, [y1, y2], stack=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:76: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:408: in interp1d res = [_interpolation(xq, x, y_arr, left, right) for y_arr in y] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________________ test_interp1_multiple_y_sequence[dtype1] ___________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1_multiple_y_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) y2 = xp.asarray([10.0, 20.0, 30.0], dtype=dtype) xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, [y1, y2], stack=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:76: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:408: in interp1d res = [_interpolation(xq, x, y_arr, left, right) for y_arr in y] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________________ test_interp1d_mixed_1d_2d_sequence[dtype0] __________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_mixed_1d_2d_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) # 1D y2 = xp.asarray([[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]], dtype=dtype) # 2D xq = xp.asarray([0.5, 1.5], dtype=dtype) # stack=False: should return a list, with shapes matching y1 and y2 > result = interp1d(xq, x, [y1, y2], stack=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:101: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:408: in interp1d res = [_interpolation(xq, x, y_arr, left, right) for y_arr in y] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________________ test_interp1d_mixed_1d_2d_sequence[dtype1] __________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_mixed_1d_2d_sequence(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y1 = xp.asarray([1.0, 2.0, 3.0], dtype=dtype) # 1D y2 = xp.asarray([[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]], dtype=dtype) # 2D xq = xp.asarray([0.5, 1.5], dtype=dtype) # stack=False: should return a list, with shapes matching y1 and y2 > result = interp1d(xq, x, [y1, y2], stack=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:101: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:408: in interp1d res = [_interpolation(xq, x, y_arr, left, right) for y_arr in y] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________________ test_interp1d_dict_input[dtype0] _______________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_dict_input(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y_dict = { "a": xp.asarray([1.0, 2.0, 3.0], dtype=dtype), "b": xp.asarray([10.0, 20.0, 30.0], dtype=dtype), } xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, y_dict) ^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________________ test_interp1d_dict_input[dtype1] _______________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_dict_input(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y_dict = { "a": xp.asarray([1.0, 2.0, 3.0], dtype=dtype), "b": xp.asarray([10.0, 20.0, 30.0], dtype=dtype), } xq = xp.asarray([0.5, 1.5], dtype=dtype) > result = interp1d(xq, x, y_dict) ^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____________________ test_interp1d_out_of_bounds[dtype0] ______________________ dtype = array_api_strict.float64 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_out_of_bounds(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([0.0, 1.0, 4.0], dtype=dtype) xq = xp.asarray([-1.0, 0.0, 2.0, 3.0], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:154: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____________________ test_interp1d_out_of_bounds[dtype1] ______________________ dtype = array_api_strict.float32 @pytest.mark.parametrize("dtype", [xp.float64, xp.float32]) def test_interp1d_out_of_bounds(dtype): x = xp.asarray([0.0, 1.0, 2.0], dtype=dtype) y = xp.asarray([0.0, 1.0, 4.0], dtype=dtype) xq = xp.asarray([-1.0, 0.0, 2.0, 3.0], dtype=dtype) > result = interp1d(xq, x, y) ^^^^^^^^^^^^^^^^^^ test/core/xp_utils/compat/test_math_interp1d.py:154: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________________ test_parse_array_api_strict_default_device __________________ def test_parse_array_api_strict_default_device(): """The strict Device object must map to CPU (matched by type, not by repr).""" device = xps.asarray([1.0]).device > assert _parse_device_to_dlpack(device) == (DLPACK_CPU, 0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/helpers/test_device_parsing.py:44: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________ test_device_repr_containing_cpu_is_not_classified_as_cpu ___________ def test_device_repr_containing_cpu_is_not_classified_as_cpu(): """A device whose repr merely mentions "cpu" must not be treated as a CPU device.""" class SneakyDevice: def __repr__(self): return "cuda:1 (spilled from cpu)" with pytest.raises(ValueError, match="Invalid device specification"): > _parse_device_to_dlpack(SneakyDevice()) test/core/xp_utils/helpers/test_device_parsing.py:66: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________ test_device_cache_key_prefers_the_backend_device_object ____________ def test_device_cache_key_prefers_the_backend_device_object(): """Hashable device objects identify a device exactly; the DLPack tuple does not.""" > cpu = xps.asarray([1.0], device=xps.Device("CPU_DEVICE")) ^^^^^^^^^^ test/core/xp_utils/helpers/test_device_parsing.py:100: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ____________ test_repeated_queries[array_api_strict-float32-2-True] ____________ xp = prefer_native = True, ndim = 2, dtype_name = 'float32' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float32) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_repeated_queries[array_api_strict-float32-2-False] ____________ xp = prefer_native = False, ndim = 2, dtype_name = 'float32' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float32) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____________ test_repeated_queries[array_api_strict-float32-3-True] ____________ xp = prefer_native = True, ndim = 3, dtype_name = 'float32' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float32) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_repeated_queries[array_api_strict-float32-3-False] ____________ xp = prefer_native = False, ndim = 3, dtype_name = 'float32' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float32) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____________ test_repeated_queries[array_api_strict-float64-2-True] ____________ xp = prefer_native = True, ndim = 2, dtype_name = 'float64' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_repeated_queries[array_api_strict-float64-2-False] ____________ xp = prefer_native = False, ndim = 2, dtype_name = 'float64' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____________ test_repeated_queries[array_api_strict-float64-3-True] ____________ xp = prefer_native = True, ndim = 3, dtype_name = 'float64' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_repeated_queries[array_api_strict-float64-3-False] ____________ xp = prefer_native = False, ndim = 3, dtype_name = 'float64' @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_repeated_queries(xp, prefer_native, ndim, dtype_name): """Nonuniform, descending grids reproduce a multilinear field and clip queries.""" dtype = getattr(xp, dtype_name) points = (np.array([3.0, 1.0, -2.0]),) + (np.array([-1.0, 0.5, 2.0]),) * (ndim - 1) grids = np.meshgrid(*points, indexing="ij") values = sum((i + 1) * g for i, g in enumerate(grids)) + np.prod(grids, axis=0) coords = np.array([[0.25] * ndim, [3.0] * ndim, [-2.0] * ndim]) clipped = np.column_stack( [np.clip(coords[:, i], p.min(), p.max()) for i, p in enumerate(points)] ) expected = sum((i + 1) * clipped[:, i] for i in range(ndim)) + np.prod(clipped, axis=1) points = tuple(xp.asarray(p, dtype=dtype) for p in points) values = xp.asarray(values, dtype=dtype) queries = xp.asarray(coords, dtype=dtype) interpolator = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) if not prefer_native: assert interpolator.implementation == "array_api" for _ in range(2): > result = interpolator(queries) ^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 1, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_bounds_and_query_validation[array_api_strict-True] ____________ xp = prefer_native = True @pytest.mark.parametrize("prefer_native", [True, False]) def test_bounds_and_query_validation(xp, prefer_native): """Boundary points are accepted, out-of-grid coordinates and bad shapes rejected.""" p = xp.asarray([0.0, 1.0]) values = xp.asarray([[0.0, 1.0], [1.0, 2.0]]) interpolator = ArrayBackendGridInterpolator( (p, p), values, bounds_error=True, prefer_native=prefer_native ) np.testing.assert_allclose( > to_numpy(interpolator(xp.asarray([[0.0, 0.0], [1.0, 1.0]]))), [0, 2] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) test/core/xp_utils/test_interpolation.py:73: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1.], dtype=array_api_strict.float64) key = Array([0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___________ test_bounds_and_query_validation[array_api_strict-False] ___________ xp = prefer_native = False @pytest.mark.parametrize("prefer_native", [True, False]) def test_bounds_and_query_validation(xp, prefer_native): """Boundary points are accepted, out-of-grid coordinates and bad shapes rejected.""" p = xp.asarray([0.0, 1.0]) values = xp.asarray([[0.0, 1.0], [1.0, 2.0]]) interpolator = ArrayBackendGridInterpolator( (p, p), values, bounds_error=True, prefer_native=prefer_native ) np.testing.assert_allclose( > to_numpy(interpolator(xp.asarray([[0.0, 0.0], [1.0, 1.0]]))), [0, 2] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) test/core/xp_utils/test_interpolation.py:73: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1.], dtype=array_api_strict.float64) key = Array([0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_shared_value_dimensions[array_api_strict-value_shape0-2-True] ______ xp = prefer_native = True, ndim = 2, value_shape = (3,) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____ test_shared_value_dimensions[array_api_strict-value_shape0-2-False] ______ xp = prefer_native = False, ndim = 2, value_shape = (3,) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_shared_value_dimensions[array_api_strict-value_shape0-3-True] ______ xp = prefer_native = True, ndim = 3, value_shape = (3,) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____ test_shared_value_dimensions[array_api_strict-value_shape0-3-False] ______ xp = prefer_native = False, ndim = 3, value_shape = (3,) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_shared_value_dimensions[array_api_strict-value_shape1-2-True] ______ xp = prefer_native = True, ndim = 2, value_shape = (2, 3) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____ test_shared_value_dimensions[array_api_strict-value_shape1-2-False] ______ xp = prefer_native = False, ndim = 2, value_shape = (2, 3) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______ test_shared_value_dimensions[array_api_strict-value_shape1-3-True] ______ xp = prefer_native = True, ndim = 3, value_shape = (2, 3) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _____ test_shared_value_dimensions[array_api_strict-value_shape1-3-False] ______ xp = prefer_native = False, ndim = 3, value_shape = (2, 3) @pytest.mark.parametrize("prefer_native", [True, False]) @pytest.mark.parametrize("ndim", [2, 3]) @pytest.mark.parametrize("value_shape", [(3,), (2, 3)]) def test_shared_value_dimensions(xp, prefer_native, ndim, value_shape): """Shared grid searches preserve independent scalar fields and trailing shape.""" points = (xp.asarray([3.0, 1.0, -2.0]),) * ndim shape = (3,) * ndim + value_shape values = xp.asarray(np.random.default_rng(6).normal(size=shape), dtype=xp.float32) queries = xp.asarray([[0.5] * ndim, [-2.0] * ndim, [4.0] * ndim], dtype=xp.float32) shared = ArrayBackendGridInterpolator(points, values, prefer_native=prefer_native) > result = shared(queries) ^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:303: in _interp3d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None-None-array-float32] ___ xp = dtype = 'float32', kind = 'array', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None-None-array-float64] ___ xp = dtype = 'float64', kind = 'array', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None-None-rows-float32] ____ xp = dtype = 'float32', kind = 'rows', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None-None-rows-float64] ____ xp = dtype = 'float64', kind = 'rows', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-None-None-fields-float32] ___ xp = dtype = 'float32', kind = 'fields', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-None-None-fields-float64] ___ xp = dtype = 'float64', kind = 'fields', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None-None-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None-None-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None-None-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None-None-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = None, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None--3.5-array-float32] ___ xp = dtype = 'float32', kind = 'array', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None--3.5-array-float64] ___ xp = dtype = 'float64', kind = 'array', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None--3.5-rows-float32] ____ xp = dtype = 'float32', kind = 'rows', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_prepared_matches_one_shot[array_api_strict-None--3.5-rows-float64] ____ xp = dtype = 'float64', kind = 'rows', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-None--3.5-fields-float32] ___ xp = dtype = 'float32', kind = 'fields', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-None--3.5-fields-float64] ___ xp = dtype = 'float64', kind = 'fields', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = -3.5, offset = None @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0. , 0.3, 2.4, 5. ], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-array-float32] __ xp = dtype = 'float32', kind = 'array', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-array-float64] __ xp = dtype = 'float64', kind = 'array', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict--0.1723-None-rows-float32] __ xp = dtype = 'float32', kind = 'rows', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict--0.1723-None-rows-float64] __ xp = dtype = 'float64', kind = 'rows', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-fields-float32] _ xp = dtype = 'float32', kind = 'fields', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-fields-float64] _ xp = dtype = 'float64', kind = 'fields', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = None, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-array-float32] __ xp = dtype = 'float32', kind = 'array', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-array-float64] __ xp = dtype = 'float64', kind = 'array', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-rows-float32] __ xp = dtype = 'float32', kind = 'rows', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-rows-float64] __ xp = dtype = 'float64', kind = 'rows', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-fields-float32] _ xp = dtype = 'float32', kind = 'fields', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-fields-float64] _ xp = dtype = 'float64', kind = 'fields', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723 , 0.12770002, 2.2277 , 4.8277 ], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = -3.5, offset = -0.1723 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-0.1723, 0.1277, 2.2277, 4.8277], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 1, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 1 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234-None-array-float32] __ xp = dtype = 'float32', kind = 'array', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234-None-array-float64] __ xp = dtype = 'float64', kind = 'array', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234-None-rows-float32] ___ xp = dtype = 'float32', kind = 'rows', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234-None-rows-float64] ___ xp = dtype = 'float64', kind = 'rows', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-fields-float32] __ xp = dtype = 'float32', kind = 'fields', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-fields-float64] __ xp = dtype = 'float64', kind = 'fields', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = None, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-array-float32] __ xp = dtype = 'float32', kind = 'array', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-array-float64] __ xp = dtype = 'float64', kind = 'array', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-rows-float32] ___ xp = dtype = 'float32', kind = 'rows', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-rows-float64] ___ xp = dtype = 'float64', kind = 'rows', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-fields-float32] __ xp = dtype = 'float32', kind = 'fields', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-fields-float64] __ xp = dtype = 'float64', kind = 'fields', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_rows-float32] _ xp = dtype = 'float32', kind = 'mixed_rows', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_rows-float64] _ xp = dtype = 'float64', kind = 'mixed_rows', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_dtype-float32] _ xp = dtype = 'float32', kind = 'mixed_dtype', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234 , 13.534 , 15.634001, 18.234001], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_dtype-float64] _ xp = dtype = 'float64', kind = 'mixed_dtype', boundary = -3.5, offset = 13.234 @pytest.mark.parametrize("dtype", ["float32", "float64"]) @pytest.mark.parametrize("kind", ["array", "rows", "fields", "mixed_rows", "mixed_dtype"]) @pytest.mark.parametrize("boundary", [None, -3.5]) @pytest.mark.parametrize("offset", [None, -0.1723, 13.234]) def test_prepared_matches_one_shot(xp, dtype, kind, boundary, offset): x = xp.asarray([0.0, 0.3, 2.4, 5.0], dtype=getattr(xp, dtype)) y = xp.asarray([1.0, -2.0, 4.0, 3.0], dtype=getattr(xp, dtype)) if kind == "rows": y = xp.stack([y, y * 2], axis=0) elif kind != "array": y = {"one": y, "two": y * 2} if kind == "mixed_rows": y["two"] = xp.stack([y["one"] * 2, y["one"] * 3], axis=0) if kind == "mixed_dtype": y["two"] = xp.astype(y["two"], xp.float64 if dtype == "float32" else xp.float32) obj = ArrayBackend1DInterpolator(x, y, left=boundary, right=boundary) grid = x if offset is None else x + offset q = xp.concat( [grid, xp.asarray([-9.0, 0.11, 2.2, 40.0, np.nan, np.inf, -np.inf], dtype=x.dtype)] ) for queries in (q, q[:0], xp.flip(q, axis=0)): > actual = obj(queries, grid_offset=offset) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([13.234, 13.534, 15.634, 18.234], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 0, 0, 2, 2, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 0 0 2 2 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_dispatch_preference[array_api_strict-None] ________________ xp = prefer_native = None @pytest.mark.parametrize("prefer_native", [None, True, False]) def test_dispatch_preference(xp, prefer_native): x = xp.asarray([0.0, 1.0, 3.0], dtype=xp.float64) y = {"a": x * 2, "b": xp.stack([x * 3, x * 4])} q = xp.asarray([-1.0, 0.5, 2.0, 4.0], dtype=xp.float64) > actual = ArrayBackend1DInterpolator(x, y, prefer_native=prefer_native)(q) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_dispatch_preference[array_api_strict-True] ________________ xp = prefer_native = True @pytest.mark.parametrize("prefer_native", [None, True, False]) def test_dispatch_preference(xp, prefer_native): x = xp.asarray([0.0, 1.0, 3.0], dtype=xp.float64) y = {"a": x * 2, "b": xp.stack([x * 3, x * 4])} q = xp.asarray([-1.0, 0.5, 2.0, 4.0], dtype=xp.float64) > actual = ArrayBackend1DInterpolator(x, y, prefer_native=prefer_native)(q) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________ test_dispatch_preference[array_api_strict-False] _______________ xp = prefer_native = False @pytest.mark.parametrize("prefer_native", [None, True, False]) def test_dispatch_preference(xp, prefer_native): x = xp.asarray([0.0, 1.0, 3.0], dtype=xp.float64) y = {"a": x * 2, "b": xp.stack([x * 3, x * 4])} q = xp.asarray([-1.0, 0.5, 2.0, 4.0], dtype=xp.float64) > actual = ArrayBackend1DInterpolator(x, y, prefer_native=prefer_native)(q) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/core/xp_utils/test_interpolation1d.py:54: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation1d.py:134: in __call__ interpolated = self._interpolate(xq, x, values, self._left, self._right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0., 1., 3.], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue0-False] _ request = > mode = 'carbon', model = 'alpha_beta_kernels' tissue = TissueProperties(cell_line=None, model='Generic', alpha_x=0.1, beta_x=0.05) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue2-False] _ request = > mode = 'carbon', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue3-False] _ request = > mode = 'carbon', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=30.0, r_nucleus=5.0) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue4-False] _ request = > mode = 'carbon', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'alpha_beta_kernels': Target: The tissue is labelled LEM I; the base data is LEM IV (α/β kernels · LEM IV, kernel set 'alpha_beta', tissue class Generic_LEMax05). Evaluated with the base data's model. Relabel it as LEM IV to silence this warning (tissue.adopt_provenance("LEM_IV")). WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'alpha_beta_kernels': Body: The tissue is labelled LEM I; the base data is LEM IV (α/β kernels · LEM IV, kernel set 'alpha_beta', tissue class Generic_LEMax05). Evaluated with the base data's model. Relabel it as LEM IV to silence this warning (tissue.adopt_provenance("LEM_IV")). _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-alpha_beta_kernels-tissue6-False] _ request = > mode = 'oxygen', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-zstar_kernels-tissue8-False] _ request = > mode = 'oxygen', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-zstar_kernels-tissue9-False] _ request = > mode = 'oxygen', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='MKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'zstar_kernels': Target: The tissue is labelled MKM; the base data is mMKM (z* kernels · mMKM, z1D_saturation_corrected, kernel set 'zs', tissue class Generic_MKM). Evaluated with the base data's model. Relabel it as mMKM to silence this warning (tissue.adopt_provenance("mMKM")). WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'zstar_kernels': Body: The tissue is labelled MKM; the base data is mMKM (z* kernels · mMKM, z1D_saturation_corrected, kernel set 'zs', tissue class Generic_MKM). Evaluated with the base data's model. Relabel it as mMKM to silence this warning (tissue.adopt_provenance("mMKM")). _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-LEM-tissue11-False] _ request = > mode = 'oxygen', model = 'LEM' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='II', d_t=30.0, r_nucleus=5.0) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'alpha_beta_kernels': Target: The tissue is labelled LEM II; the base data is LEM I (α/β kernels · LEM I, kernel set 'alpha_beta', tissue class Generic_LEMax05). Evaluated with the base data's model. Relabel it as LEM I to silence this warning (tissue.adopt_provenance("LEM_I")). WARNING pyRadPlan.dose.engines._base:_base.py:983 Biological model 'alpha_beta_kernels': Body: The tissue is labelled LEM II; the base data is LEM I (α/β kernels · LEM I, kernel set 'alpha_beta', tissue class Generic_LEMax05). Evaluated with the base data's model. Relabel it as LEM I to silence this warning (tissue.adopt_provenance("LEM_I")). _ test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[protons-WED-tissue14-False] _ request = > mode = 'protons', model = 'WED' tissue = TissueProperties(cell_line=None, model='Generic', alpha_x=0.1, beta_x=0.05) has_errors = False @pytest.mark.parametrize(("mode", "model", "tissue", "has_errors"), CASES) def test_requested_bio_dose_raises_exactly_when_the_check_reports_errors( request, mode, model, tissue, has_errors ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = True _set_tissue(cst, tissue) machine = DoseEngineBase.load_machine(pln.radiation_mode, pln.machine) issues = create_bio_model(model).check_tissues(machine, cst) assert bool([issue for issue in issues if issue.is_error]) is has_errors if has_errors: with pytest.raises(BioModelUnavailableError) as info: calc_dose_influence(ct, cst, stf, pln) for issue in issues: assert issue.message in str(info.value) else: > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:81: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[carbon-alpha_beta_kernels-tissue0] _ request = > mode = 'carbon', model = 'alpha_beta_kernels' tissue = TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan).; Body: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan). Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[carbon-zstar_kernels-tissue1] _ request = > mode = 'carbon', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'zstar_kernels' cannot be evaluated for this machine and these structures: Biological model 'zstar_kernels' not available: Required quantities not provided by Dose Engine or selected Machine Dataset: zs. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-alpha_beta_kernels-tissue2] _ request = > mode = 'oxygen', model = 'alpha_beta_kernels' tissue = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: The tissue parameters are mMKM (MKMTissueProperties), but α/β kernels · LEM I (kernel set 'alpha_beta') is tabulated for LEM I tissue classes, which share no identifying parameter with them.; Body: The tissue parameters are mMKM (MKMTissueProperties), but α/β kernels · LEM I (kernel set 'alpha_beta') is tabulated for LEM I tissue classes, which share no identifying parameter with them. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-zstar_kernels-tissue3] _ request = > mode = 'oxygen', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=nan, reference_radiation='xray_200kV') @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'zstar_kernels' cannot be evaluated for this machine and these structures: Target: Biological model 'zstar_kernels' reads the tissue parameter(s) beta_0 of every structure, but MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=nan, reference_radiation='xray_200kV') lacks beta_0.; Body: Biological model 'zstar_kernels' reads the tissue parameter(s) beta_0 of every structure, but MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=nan, reference_radiation='xray_200kV') lacks beta_0. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-zstar_kernels-tissue4] _ request = > mode = 'oxygen', model = 'zstar_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0) @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'zstar_kernels' cannot be evaluated for this machine and these structures: Target: The tissue parameters are LEM I (LEMTissueProperties), but z* kernels · mMKM (kernel set 'zs') is tabulated for mMKM tissue classes, which share no identifying parameter with them.; Body: The tissue parameters are LEM I (LEMTissueProperties), but z* kernels · mMKM (kernel set 'zs') is tabulated for mMKM tissue classes, which share no identifying parameter with them. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[protons-MCN-tissue5] _ request = > mode = 'protons', model = 'MCN' tissue = TissueProperties(cell_line=None, model='Generic', alpha_x=0.1, beta_x=0.0) @pytest.mark.parametrize( ("mode", "model", "tissue"), [(mode, model, tissue) for mode, model, tissue, has_errors in CASES if has_errors], ) def test_automatic_bio_dose_falls_back_to_physical_dose_on_errors(request, mode, model, tissue): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model _set_tissue(cst, tissue) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:95: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'MCN' cannot be evaluated for this machine and these structures: Target: Biological model 'MCN' is only defined for beta_x > 0, but the structure has beta_x = 0.0.; Body: Biological model 'MCN' is only defined for beta_x > 0, but the structure has beta_x = 0.0. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_differing_provenance_label_warns_and_evaluates_the_model[oxygen-zstar_kernels-tissue0-relabelled0-auto] _ request = > caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb8d75450> mode = 'oxygen', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='MKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') relabelled = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') calc_bio_dose = 'auto' @pytest.mark.parametrize("calc_bio_dose", ["auto", True]) @pytest.mark.parametrize(("mode", "model", "tissue", "relabelled"), WARNING_CASES) def test_differing_provenance_label_warns_and_evaluates_the_model( request, caplog, mode, model, tissue, relabelled, calc_bio_dose ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = calc_bio_dose _set_tissue(cst, relabelled) > reference = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:134: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_differing_provenance_label_warns_and_evaluates_the_model[oxygen-zstar_kernels-tissue0-relabelled0-True] _ request = > caplog = <_pytest.logging.LogCaptureFixture object at 0xffff8cd69f30> mode = 'oxygen', model = 'zstar_kernels' tissue = MKMTissueProperties(cell_line=None, model='MKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') relabelled = MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.30051126563660663, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615, reference_radiation='xray_200kV') calc_bio_dose = True @pytest.mark.parametrize("calc_bio_dose", ["auto", True]) @pytest.mark.parametrize(("mode", "model", "tissue", "relabelled"), WARNING_CASES) def test_differing_provenance_label_warns_and_evaluates_the_model( request, caplog, mode, model, tissue, relabelled, calc_bio_dose ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = calc_bio_dose _set_tissue(cst, relabelled) > reference = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:134: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_differing_provenance_label_warns_and_evaluates_the_model[carbon-alpha_beta_kernels-tissue1-relabelled1-auto] _ request = > caplog = <_pytest.logging.LogCaptureFixture object at 0xffff8cd68d60> mode = 'carbon', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0) relabelled = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=30.0, r_nucleus=5.0) calc_bio_dose = 'auto' @pytest.mark.parametrize("calc_bio_dose", ["auto", True]) @pytest.mark.parametrize(("mode", "model", "tissue", "relabelled"), WARNING_CASES) def test_differing_provenance_label_warns_and_evaluates_the_model( request, caplog, mode, model, tissue, relabelled, calc_bio_dose ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = calc_bio_dose _set_tissue(cst, relabelled) > reference = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:134: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _ test_differing_provenance_label_warns_and_evaluates_the_model[carbon-alpha_beta_kernels-tissue1-relabelled1-True] _ request = > caplog = <_pytest.logging.LogCaptureFixture object at 0xffff8a307650> mode = 'carbon', model = 'alpha_beta_kernels' tissue = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0) relabelled = LEMTissueProperties(cell_line=None, model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=30.0, r_nucleus=5.0) calc_bio_dose = True @pytest.mark.parametrize("calc_bio_dose", ["auto", True]) @pytest.mark.parametrize(("mode", "model", "tissue", "relabelled"), WARNING_CASES) def test_differing_provenance_label_warns_and_evaluates_the_model( request, caplog, mode, model, tissue, relabelled, calc_bio_dose ): pln, ct, cst, stf, _dij, _result = request.getfixturevalue(f"test_data_{mode}") pln.bio_model = model pln.prop_dose_calc["calc_bio_dose"] = calc_bio_dose _set_tissue(cst, relabelled) > reference = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_bio_tissue_check.py:134: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose _____________ test_default_bio_model_with_matching_tissue[protons] _____________ request = > mode = 'protons' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff8a35ee00> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_matching_tissue(request, mode, caplog): """Physical-dose objectives are optimized on RBExDose, which the dij provides.""" pln, ct, cst, stf = _case(request, mode) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:59: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _____________ test_default_bio_model_with_matching_tissue[helium] ______________ request = > mode = 'helium' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff8a35f790> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_matching_tissue(request, mode, caplog): """Physical-dose objectives are optimized on RBExDose, which the dij provides.""" pln, ct, cst, stf = _case(request, mode) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:59: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! _____________ test_default_bio_model_with_matching_tissue[carbon] ______________ request = > mode = 'carbon' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff88168e50> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_matching_tissue(request, mode, caplog): """Physical-dose objectives are optimized on RBExDose, which the dij provides.""" pln, ct, cst, stf = _case(request, mode) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:59: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _____________ test_default_bio_model_with_matching_tissue[oxygen] ______________ request = > mode = 'oxygen' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff88123b50> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_matching_tissue(request, mode, caplog): """Physical-dose objectives are optimized on RBExDose, which the dij provides.""" pln, ct, cst, stf = _case(request, mode) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:59: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _ test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[protons] _ request = > mode = 'protons' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff83750b90> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow(request, mode, caplog): """Tissue without base data only drops the kernel-based biology, with a warning.""" pln, ct, cst, stf = _case(request, mode) _set_tissue(cst, UNMATCHED_TISSUE) with caplog.at_level(logging.WARNING): > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:82: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _ test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[helium] _ request = > mode = 'helium' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff821367b0> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow(request, mode, caplog): """Tissue without base data only drops the kernel-based biology, with a warning.""" pln, ct, cst, stf = _case(request, mode) _set_tissue(cst, UNMATCHED_TISSUE) with caplog.at_level(logging.WARNING): > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:82: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! _ test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[carbon] _ request = > mode = 'carbon' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff82924590> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow(request, mode, caplog): """Tissue without base data only drops the kernel-based biology, with a warning.""" pln, ct, cst, stf = _case(request, mode) _set_tissue(cst, UNMATCHED_TISSUE) with caplog.at_level(logging.WARNING): > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:82: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan).; Body: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan). Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[oxygen] _ request = > mode = 'oxygen' caplog = <_pytest.logging.LogCaptureFixture object at 0xffff82165630> @pytest.mark.parametrize("mode", ION_MODES) def test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow(request, mode, caplog): """Tissue without base data only drops the kernel-based biology, with a warning.""" pln, ct, cst, stf = _case(request, mode) _set_tissue(cst, UNMATCHED_TISSUE) with caplog.at_level(logging.WARNING): > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:82: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM I (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0).; Body: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM I (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0). Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ____________ test_unmatched_tissue_with_physical_dose_only[carbon] _____________ request = > mode = 'carbon' @pytest.mark.parametrize("mode", KERNEL_MODES) def test_unmatched_tissue_with_physical_dose_only(request, mode): """The physical-dose influence of an unmatched tissue works as before (calc_bio_dose=False).""" pln, ct, cst, stf = _case(request, mode) pln.prop_dose_calc["calc_bio_dose"] = False _set_tissue(cst, UNMATCHED_TISSUE) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:107: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan).; Body: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM IV (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='IV', d_t=nan, r_nucleus=nan). Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ____________ test_unmatched_tissue_with_physical_dose_only[oxygen] _____________ request = > mode = 'oxygen' @pytest.mark.parametrize("mode", KERNEL_MODES) def test_unmatched_tissue_with_physical_dose_only(request, mode): """The physical-dose influence of an unmatched tissue works as before (calc_bio_dose=False).""" pln, ct, cst, stf = _case(request, mode) pln.prop_dose_calc["calc_bio_dose"] = False _set_tissue(cst, UNMATCHED_TISSUE) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:107: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'alpha_beta_kernels' cannot be evaluated for this machine and these structures: Target: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM I (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0).; Body: No matching tissue class in the machine base data for TissueProperties(cell_line=None, model='Generic', alpha_x=0.2, beta_x=0.05) in α/β kernels · LEM I (kernel set 'alpha_beta'). Available classes: [LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0), LEMTissueProperties(cell_line='Generic_LEMax05', model='LEM', alpha_x=0.5, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0)]. Closest class: LEMTissueProperties(cell_line='Generic_LEMax01', model='LEM', alpha_x=0.1, beta_x=0.05, version='I', d_t=30.0, r_nucleus=5.0). Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ____________________ test_oxygen_lem_dose_calculation[0.1] _____________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) alpha_x = 0.1 @pytest.mark.parametrize("alpha_x", [0.1, 0.5]) def test_oxygen_lem_dose_calculation(test_data_oxygen, alpha_x): """Both LEM classes of the generic oxygen machine yield finite biological results.""" pln, ct, cst, stf, _dij, _result = test_data_oxygen pln.bio_model = "LEM" _set_tissue(cst, LEMTissueProperties(alpha_x=alpha_x, beta_x=0.05, d_t=30.0, r_nucleus=5.0)) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:131: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_oxygen_lem_dose_calculation[0.5] _____________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) alpha_x = 0.5 @pytest.mark.parametrize("alpha_x", [0.1, 0.5]) def test_oxygen_lem_dose_calculation(test_data_oxygen, alpha_x): """Both LEM classes of the generic oxygen machine yield finite biological results.""" pln, ct, cst, stf, _dij, _result = test_data_oxygen pln.bio_model = "LEM" _set_tissue(cst, LEMTissueProperties(alpha_x=alpha_x, beta_x=0.05, d_t=30.0, r_nucleus=5.0)) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:131: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________________ test_oxygen_mkm_dose_calculation _______________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) def test_oxygen_mkm_dose_calculation(test_data_oxygen): """z* kernels: alpha/beta from the oxygen machine's mMKM z* and the tissue's alpha_0.""" pln, ct, cst, stf, _dij, _result = test_data_oxygen pln.bio_model = "MKM" _set_tissue( cst, MKMTissueProperties( model="mMKM", r_nucleus=3.9, r_domain=0.32, alpha_0=0.172, beta_0=0.0615 ), ) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:151: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _________________ test_oxygen_mkm_rejects_unset_alpha_0[auto] __________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) calc_bio_dose = 'auto' @pytest.mark.parametrize("calc_bio_dose", [True, "auto"]) def test_oxygen_mkm_rejects_unset_alpha_0(test_data_oxygen, calc_bio_dose): """A tissue without alpha_0 must not yield NaN biological quantities.""" pln, ct, cst, stf, _dij, _result = test_data_oxygen pln.bio_model = "MKM" pln.prop_dose_calc["calc_bio_dose"] = calc_bio_dose _set_tissue( cst, MKMTissueProperties(model="mMKM", r_nucleus=3.9, r_domain=0.32, beta_0=0.0615) ) if calc_bio_dose is True: with pytest.raises(BioModelUnavailableError, match="lacks alpha_0"): calc_dose_influence(ct, cst, stf, pln) return > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_default_bio_models.py:179: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'zstar_kernels' cannot be evaluated for this machine and these structures: Target: Biological model 'zstar_kernels' reads the tissue parameter(s) alpha_0 of every structure, but MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.1, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=nan, beta_0=0.0615, reference_radiation='xray_200kV') lacks alpha_0.; Body: Biological model 'zstar_kernels' reads the tissue parameter(s) alpha_0 of every structure, but MKMTissueProperties(cell_line=None, model='mMKM', alpha_x=0.1, beta_x=0.0615, r_nucleus=3.9, r_domain=0.32, alpha_0=nan, beta_0=0.0615, reference_radiation='xray_200kV') lacks alpha_0. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ___________________ test_reused_engine_repeats_forward_dose ____________________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_reused_engine_repeats_forward_dose(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons w = np.ones(stf.total_number_of_bixels) engine = get_engine(pln) > first = _dose(engine.calc_dose_forward(ct, cst, stf, w)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_engine_reuse.py:18: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff _____________ test_reused_engine_uses_the_structures_of_each_call ______________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_reused_engine_uses_the_structures_of_each_call(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons w = np.ones(stf.total_number_of_bixels) targets = cst.model_copy(update={"vois": [v for v in cst.vois if v.voi_type == "TARGET"]}) engine = get_engine(pln) > engine.calc_dose_forward(ct, targets, stf, w) test/dose/test_engine_reuse.py:33: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.8866995, 1.0837438], [ 0.7856742, -0.7856742]], [[ 2.35...67 , 1.767767 ], [ 0.8866995, 1.0837438], [-0.7856742, 0.7856742]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ________________ test_forward_dose_leaves_the_stf_weights_alone ________________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_forward_dose_leaves_the_stf_weights_alone(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons before = [b.weight for beam in stf.beams for ray in beam.rays for b in ray.beamlets] w = np.linspace(0.1, 1.0, stf.total_number_of_bixels) > get_engine(pln).calc_dose_forward(ct, cst, stf, w) test/dose/test_engine_reuse.py:47: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff __________________________ test_keep_rad_depth_cubes ___________________________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_keep_rad_depth_cubes(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons pln.prop_dose_calc["keep_rad_depth_cubes"] = True engine = get_engine(pln) for _ in range(2): > dij = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_engine_reuse.py:59: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: keep_rad_depth_cubes __________ test_reused_engine_resolves_the_bio_model_per_calculation ___________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_reused_engine_resolves_the_bio_model_per_calculation(test_data_protons): pln, ct, cst, stf, _, _ = test_data_protons pln.bio_model = "MCN" no_beta = cst.model_copy(deep=True) for voi in no_beta.vois: voi.beta_x = 0.0 # McNamara needs beta_x > 0, so the first calculation drops the model ... engine = get_engine(pln) > assert engine.calc_dose_influence(ct, no_beta, stf).bio_model is None ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_engine_reuse.py:75: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'MCN' cannot be evaluated for this machine and these structures: Target: Biological model 'MCN' is only defined for beta_x > 0, but the structure has beta_x = 0.0.; Body: Biological model 'MCN' is only defined for beta_x > 0, but the structure has beta_x = 0.0. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ________ test_reused_engine_resolves_the_lateral_model_per_calculation _________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_reused_engine_resolves_the_lateral_model_per_calculation(test_data_protons): # "auto" resolves to the most accurate model the machine supports, for each calculation pln, ct, cst, stf, _, _ = test_data_protons pln.prop_dose_calc["lateral_model"] = "auto" engine = get_engine(pln) > engine.calc_dose_influence(ct, cst, stf) test/dose/test_engine_reuse.py:90: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________________ test_protons_cd_forward ____________________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:27: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_protons_cd_forward_bio_model_none ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_none(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "none" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_protons_cd_forward_bio_model_WED _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_WED(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "WED" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:47: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_protons_cd_forward_bio_model_MCN _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_MCN(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "MCN" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:57: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_protons_cd_forward_bio_model_CAR _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_CAR(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "CAR" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:67: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_protons_cd_forward_bio_model_LSM _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_LSM(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "LSM" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:77: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_forward_bio_model_const ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_bio_model_const(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "constant_rbe" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:87: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________________ test_helium_cd_forward ____________________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_forward(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:96: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! ____________________ test_helium_cd_forward_bio_model_none _____________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_forward_bio_model_none(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium pln.bio_model = "none" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:106: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! _____________________ test_helium_cd_forward_bio_model_LSM _____________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_forward_bio_model_LSM(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium pln.bio_model = "LSM" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! ____________________________ test_carbon_cd_forward ____________________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_carbon_cd_forward(test_data_carbon): pln, ct, cst, stf, dij, result = test_data_carbon > result_py = calc_dose_forward(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:125: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________ test_carbon_cd_forward_bio_model_none _____________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_carbon_cd_forward_bio_model_none(test_data_carbon): pln, ct, cst, stf, dij, result = test_data_carbon pln.bio_model = "none" > result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:135: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________________________ test_oxygen_cd_forward ____________________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) def test_oxygen_cd_forward(test_data_oxygen): pln, ct, cst, stf, dij, result = test_data_oxygen > result_py = calc_dose_forward(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:144: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model __________________________ test_protons_cd_influence ___________________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:153: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_influence_bio_model_none ___________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence_bio_model_none(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "none" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:163: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_influence_bio_model_WED ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence_bio_model_WED(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "WED" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:173: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_influence_bio_model_MCN ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence_bio_model_MCN(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "MCN" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:183: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_influence_bio_model_CAR ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence_bio_model_CAR(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "CAR" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:193: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________ test_protons_cd_influence_bio_model_LSM ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_influence_bio_model_LSM(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "LSM" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:203: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________________ test_helium_cd_influence ___________________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_influence(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:212: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! ___________________ test_helium_cd_influence_bio_model_none ____________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_influence_bio_model_none(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium pln.bio_model = "none" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:222: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! ____________________ test_helium_cd_influence_bio_model_LSM ____________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_cd_influence_bio_model_LSM(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium pln.bio_model = "LSM" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:232: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! ___________________ test_carbon_cd_influence_bio_model_none ____________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_carbon_cd_influence_bio_model_none(test_data_carbon): pln, ct, cst, stf, dij, result = test_data_carbon pln.bio_model = "none" pln > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:243: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___________________________ test_oxygen_cd_influence ___________________________ test_data_oxygen = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'iso_c...0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), ...}) def test_oxygen_cd_influence(test_data_oxygen): pln, ct, cst, stf, dij, result = test_data_oxygen > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:252: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ______ test_carbon_cd_influence_bio_model_unavailable_keeps_physical_dose ______ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) caplog = <_pytest.logging.LogCaptureFixture object at 0xffff82019370> def test_carbon_cd_influence_bio_model_unavailable_keeps_physical_dose(test_data_carbon, caplog): """Without calc_bio_dose=True, an unavailable model leaves a physical-dose dij.""" pln, ct, cst, stf, dij, result = test_data_carbon pln.bio_model = "LSM" with caplog.at_level("WARNING"): > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:275: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'LSM' cannot be evaluated for this machine and these structures: Biological model 'LSM' not available: Required quantities not provided by Dose Engine or selected Machine Dataset: let. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _________________ test_carbon_multi_gaussian_reduces_to_single _________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff8292e040> def test_carbon_multi_gaussian_reduces_to_single(test_data_carbon, monkeypatch): """A multi-Gaussian kernel with all extra weights zero equals the single-Gaussian model.""" from pathlib import Path import pyRadPlan from pyRadPlan.dose.engines._base import DoseEngineBase from pyRadPlan.machines import load_machine_from_mat, validate_machine pln, ct, cst, stf, dij, result = test_data_carbon machine_file = Path(pyRadPlan.__file__).parent / "data" / "machines" / "carbon_Generic.mat" machine = validate_machine(load_machine_from_mat(machine_file)) for kernel in machine.pb_kernels.values(): kernel.sigma_multi = np.stack([kernel.sigma, 2 * kernel.sigma, 3 * kernel.sigma]) kernel.weight_multi = np.zeros((2, kernel.depths.shape[0])) assert machine.has_multi_gaussian_kernel monkeypatch.setattr(DoseEngineBase, "load_machine", staticmethod(lambda *_: machine)) pln.prop_dose_calc["lateral_model"] = "single" > dose_single = calc_dose_influence(ct, cst, stf, pln).physical_dose.flat[0].toarray() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:312: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________ test_protons_cd_forward_uses_loaded_plan_machine _______________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_cd_forward_uses_loaded_plan_machine(test_data_protons): from pyRadPlan.machines import load_from_name pln, ct, cst, stf, dij, result = test_data_protons > reference = sitk.GetArrayFromImage(calc_dose_forward(ct, cst, stf, pln)["physical_dose"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb.py:323: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _____________________ test_protons_WED_alpha_beta_matrices _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_WED_alpha_beta_matrices(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "WED" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:229: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _____________________ test_protons_MCN_alpha_beta_matrices _____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_MCN_alpha_beta_matrices(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "MCN" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:242: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _____________________ test_helium_HEL_alpha_beta_matrices ______________________ test_data_helium = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_helium_HEL_alpha_beta_matrices(test_data_helium): pln, ct, cst, stf, dij, result = test_data_helium pln.bio_model = "HEL" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:255: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base_pencilbeam_particle:_base_pencilbeam_particle.py:124 Chosen Machine does not support a single Gaussian Pencil-Beam model! __________________________ test_protons_constant_rbe ___________________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_constant_rbe(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "constant_rbe" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:267: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ________________ test_protons_constant_rbe_parameter_from_plan _________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_constant_rbe_parameter_from_plan(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = {"model": "constant_rbe", "rbe": 1.0} > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:283: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ____________ test_calc_bio_dose_off_keeps_let_for_on_the_fly_models ____________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_calc_bio_dose_off_keeps_let_for_on_the_fly_models(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "WED" pln.prop_dose_calc = {"calc_bio_dose": False} > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:291: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.6793786 , -1.8561553 ], [ 0.98141724, 1.0012388 ], [ 0.8396893 , -0.92807764]], [... 1.8561553 ], [ 0.98141724, 1.0012388 ], [-0.8396893 , 0.92807764]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_bio_dose ________________ test_calc_let_off_still_feeds_let_based_model _________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_calc_let_off_still_feeds_let_based_model(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "WED" pln.prop_dose_calc = {"calc_let": False} > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:301: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.6793786 , -1.8561553 ], [ 0.98141724, 1.0012388 ], [ 0.8396893 , -0.92807764]], [... 1.8561553 ], [ 0.98141724, 1.0012388 ], [-0.8396893 , 0.92807764]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: calc_let _______________ test_protons_bio_model_none_has_no_bio_matrices ________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_protons_bio_model_none_has_no_bio_matrices(test_data_protons): pln, ct, cst, stf, dij, result = test_data_protons pln.bio_model = "none" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:318: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________ test_carbon_kernel_based_lq_alpha_beta_matrices ________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_carbon_kernel_based_lq_alpha_beta_matrices(test_data_carbon): pln, ct, cst, stf, dij, result = test_data_carbon pln.bio_model = "kernel_based_lq" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:328: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model __________________ test_carbon_tabulated_alpha_beta_matrices ___________________ test_data_carbon = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff825494e0> def test_carbon_tabulated_alpha_beta_matrices(test_data_carbon, monkeypatch): pln, ct, cst, stf, dij, result = test_data_carbon machine_file = Path(pyRadPlan.__file__).parent / "data" / "machines" / "carbon_Generic.mat" machine = validate_machine(load_machine_from_mat(machine_file)) _attach_synthetic_spectra(machine) assert "fluence" in machine.provided_quantities() monkeypatch.setattr(DoseEngineBase, "load_machine", staticmethod(lambda *_: machine)) pln.bio_model = "dose_average_alpha_beta" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:408: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ________________ test_bio_tissue_arrays_use_the_selected_device ________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_bio_tissue_arrays_use_the_selected_device(test_data_protons): """Tissue inputs are created on the engine's device, not the namespace default one.""" import array_api_compat import array_api_strict pln, ct, cst, stf, _dij, _result = test_data_protons pln.bio_model = "WED" pln.prop_dose_calc["calc_bio_dose"] = False > device = array_api_strict.Device("device1") ^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:445: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _ test_out_of_domain_reference_parameters_without_bio_request_keep_physical_dose _ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_out_of_domain_reference_parameters_without_bio_request_keep_physical_dose( test_data_protons, ): """Outside the model's domain, only a requested biological dose is an error.""" pln, ct, cst, stf, _dij, _result = test_data_protons pln.bio_model = "MCN" _with_reference_params(cst, beta_x=0.0) > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:492: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'MCN' cannot be evaluated for this machine and these structures: Target: Biological model 'MCN' is only defined for beta_x > 0, but the structure has beta_x = 0.0. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. ____________________ test_bio_influence_matrices_are_finite ____________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_bio_influence_matrices_are_finite(test_data_protons): """No NaN/Inf ever reaches the stored biological influence matrices.""" pln, ct, cst, stf, _dij, _result = test_data_protons pln.bio_model = "MCN" > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_hongpb_bio.py:527: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ___ test_cutoff_matches_scalar_reference[array_api_strict-1-integral-single] ___ xp = model = 'single', method = 'integral', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_cutoff_matches_scalar_reference[array_api_strict-1-integral-double] ___ xp = model = 'double', method = 'integral', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_cutoff_matches_scalar_reference[array_api_strict-1-integral-multi] ____ xp = model = 'multi', method = 'integral', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_cutoff_matches_scalar_reference[array_api_strict-1-integral-multi_1d] __ xp = model = 'multi_1d', method = 'integral', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_cutoff_matches_scalar_reference[array_api_strict-1-integral-singleXY] __ xp = model = 'singleXY', method = 'integral', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_cutoff_matches_scalar_reference[array_api_strict-1-relative-single] ___ xp = model = 'single', method = 'relative', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_cutoff_matches_scalar_reference[array_api_strict-1-relative-double] ___ xp = model = 'double', method = 'relative', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ___ test_cutoff_matches_scalar_reference[array_api_strict-1-relative-multi] ____ xp = model = 'multi', method = 'relative', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_cutoff_matches_scalar_reference[array_api_strict-1-relative-multi_1d] __ xp = model = 'multi_1d', method = 'relative', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __ test_cutoff_matches_scalar_reference[array_api_strict-1-relative-singleXY] __ xp = model = 'singleXY', method = 'relative', max_samples = 1 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-single] _ xp = model = 'single', method = 'integral', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-double] _ xp = model = 'double', method = 'integral', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-multi] _ xp = model = 'multi', method = 'integral', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-multi_1d] _ xp = model = 'multi_1d', method = 'integral', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-singleXY] _ xp = model = 'singleXY', method = 'integral', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-single] _ xp = model = 'single', method = 'relative', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-double] _ xp = model = 'double', method = 'relative', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-multi] _ xp = model = 'multi', method = 'relative', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-multi_1d] _ xp = model = 'multi_1d', method = 'relative', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-singleXY] _ xp = model = 'singleXY', method = 'relative', max_samples = 100000 @pytest.mark.parametrize("model", ["single", "double", "multi", "multi_1d", "singleXY"]) @pytest.mark.parametrize("method", ["integral", "relative"]) @pytest.mark.parametrize("max_samples", [1, 100_000]) def test_cutoff_matches_scalar_reference(xp, model, method, max_samples): """Batching preserves radii, compensation and numerical integration error.""" engine, kernel, host_grid = _inputs(model) depths = np.array([0.0, 1.2, 4.5, 8.0]) idd = 1.6021766208e-02 * np.interp(depths, kernel["depths"], kernel["idd"]) cutoff = 0.95 expected = [] for depth, reference_idd in zip(depths, idd): dose = _scalar_reference(engine, kernel, host_grid, depth, 0.4) area = np.cumsum(host_grid.radii * dose * host_grid.dr * host_grid.angular_weights) condition = ( area >= reference_idd * cutoff if method == "integral" else dose <= (1 - cutoff) * dose.max() ) ix = condition.argmax() comp = cutoff**-1 if method == "integral" else (area[ix] / area[-1]) ** -1 expected.append([host_grid.radii[ix], comp, abs(area[-1] / reference_idd - 1) * 100]) backend_kernel = { key: to_namespace(xp, value) if isinstance(value, np.ndarray) else value for key, value in kernel.items() } grid = host_grid.to_namespace(xp) batches = [] def profile(batch, quadrature): batches.append(batch.shape[0]) return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) > actual = evaluate_cutoff( xp.asarray(depths), xp.asarray(idd), grid, profile, cutoff=cutoff, method=method, max_samples=max_samples, ) test/dose/test_particle_cutoff.py:137: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_particle_cutoff.py:207: in evaluate_cutoff dose = dose_profile(depths[start:stop], quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_cutoff.py:135: in profile return engine._cutoff_dose_profile(batch, backend_kernel, 0.4, quadrature) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_hongpb.py:112: in _cutoff_dose_profile kernels = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.7, 3.7, 8.7], dtype=array_api_strict.float64) key = Array([0, 0, 1, 1], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 1] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ____________ test_quadrature_respects_explicit_and_inferred_device _____________ def test_quadrature_respects_explicit_and_inferred_device(): """Native creation and custom boundaries stay on a non-default logical device.""" xp = pytest.importorskip("array_api_strict") > device = xp.Device("device1") ^^^^^^^^^ test/dose/test_particle_cutoff.py:281: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_particle_support_selection[strict2023-table-False-empty] _________ xp = selection = 'empty', optional_fields = False, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = empty((0,), dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_particle_support_selection[strict2023-table-False-none] _________ xp = selection = 'none', optional_fields = False, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_particle_support_selection[strict2023-table-False-all] __________ xp = selection = 'all', optional_fields = False, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________ test_particle_support_selection[strict2023-table-False-mixed] _________ xp = selection = 'mixed', optional_fields = False, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_particle_support_selection[strict2023-table-True-empty] _________ xp = selection = 'empty', optional_fields = True, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = empty((0,), dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_particle_support_selection[strict2023-table-True-none] __________ xp = selection = 'none', optional_fields = True, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________ test_particle_support_selection[strict2023-table-True-all] __________ xp = selection = 'all', optional_fields = True, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _________ test_particle_support_selection[strict2023-table-True-mixed] _________ xp = selection = 'mixed', optional_fields = True, cutoff = 'table' @pytest.mark.parametrize("selection", ["empty", "none", "all", "mixed"]) @pytest.mark.parametrize("optional_fields", [False, True]) @pytest.mark.parametrize("cutoff", ["full", "constant", "table"]) def test_particle_support_selection(xp, selection, optional_fields, cutoff): """Select physical rows, preserving unsorted voxel IDs and field shapes/dtypes.""" engine = object.__new__(ParticleHongPencilBeamEngine) engine.dosimetric_lateral_cutoff = 1.0 if cutoff == "full" else 0.995 engine._calc_bio_dose = optional_fields n = 0 if selection == "empty" else 5 depths = np.array([2, 6, 1, 3, 0], dtype=np.float32)[:n] radial = np.array([1, 1, 9, 4, 1], dtype=np.float32)[:n] if selection == "none": depths[:] = 99 elif selection == "all": depths[:] = 2 radial[:] = 1 source = { "ix": np.array([29, 8, 17, 42, 3], dtype=np.int64)[:n], "rad_depths": depths, "radial_dist_sq": radial, } if optional_fields: source.update( lat_dists=np.arange(n * 2, dtype=np.float32).reshape(n, 2), v_alpha_x=np.arange(n, dtype=np.float64).reshape(n, 1), v_beta_x=np.arange(n, dtype=np.float32), v_tissue_class_ix=np.array([2, 0, 1, 2, 1], dtype=np.int32)[:n], ) ray = {name: xp.asarray(value) for name, value in source.items()} cut_off = [2.0, 2.0] if cutoff == "table" else [2.0] bixel = { "rad_depth_offset": 0.5, "kernel": { "offset": 1.5, "depths": xp.asarray([0.0, 3.0]), "lateral_cut_off": { "depths": xp.asarray([0.0, 3.0]), "cut_off": xp.asarray(cut_off), }, }, } if selection in ("empty", "none"): selected = [] elif selection == "all": selected = list(range(n)) else: selected = {"full": [0, 2, 3, 4], "constant": [0, 3, 4], "table": [0, 3]}[cutoff] > result = engine._get_bixel_indices_on_ray(bixel, ray) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_indexing.py:78: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:425: in _get_bixel_indices_on_ray interp_vals = array_interp( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:413: in interp1d return _interpolation(xq, x, y, left, right) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([1., 4.], dtype=array_api_strict.float64) key = Array([0, 0, 0, 0, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 0 0 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________ test_translated_depths_and_cache[float32-array_api_strict] __________ backend = dtype = 'float32' @pytest.mark.parametrize("backend", ["numpy", "torch", "array_api_strict"]) @pytest.mark.parametrize("dtype", ["float32", "float64"]) def test_translated_depths_and_cache(backend, dtype): """Compare translated field values and invalidate preparation with geometry.""" backend = pytest.importorskip(backend) xp = array_api_compat.array_namespace(backend.asarray([0.0])) engine = engine_stub() kernel = { "depths": xp.asarray([0.0, 0.1, 0.8, 2.0], dtype=getattr(xp, dtype)), "offset": 0.03217, "idd": xp.asarray([1.0, 2.0, 3.0, 0.2], dtype=getattr(xp, dtype)), "sigma": xp.asarray([0.1, 0.2, 0.4, 0.7], dtype=getattr(xp, dtype)), "let": xp.asarray([2.0, 4.0, 5.0, 0.0], dtype=getattr(xp, dtype)), } prepare = Mock(wraps=engine._prepare_depth_interpolator) engine._prepare_depth_interpolator = prepare for offset in (0.0, 0.134, -0.23, 8.5): grid = kernel["depths"] + kernel["offset"] - offset q = xp.concat([grid, grid + 0.01, grid - 0.01]) bixel = dict(kernel=kernel, rad_depths=q, rad_depth_offset=offset) > expected = interp1d( q, grid, { "idd": kernel["idd"] * 1.6021766208e-02, "sigma": kernel["sigma"], "let": kernel["let"], }, ) test/dose/test_particle_interpolators.py:48: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.03217, 0.13217, 0.83217, 2.03217], dtype=array_api_strict.float32) key = Array([0, 0, 1, 2, 0, 1, 2, 2, 0, 0, 1, 2], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 1 2 2 0 0 1 2] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError __________ test_translated_depths_and_cache[float64-array_api_strict] __________ backend = dtype = 'float64' @pytest.mark.parametrize("backend", ["numpy", "torch", "array_api_strict"]) @pytest.mark.parametrize("dtype", ["float32", "float64"]) def test_translated_depths_and_cache(backend, dtype): """Compare translated field values and invalidate preparation with geometry.""" backend = pytest.importorskip(backend) xp = array_api_compat.array_namespace(backend.asarray([0.0])) engine = engine_stub() kernel = { "depths": xp.asarray([0.0, 0.1, 0.8, 2.0], dtype=getattr(xp, dtype)), "offset": 0.03217, "idd": xp.asarray([1.0, 2.0, 3.0, 0.2], dtype=getattr(xp, dtype)), "sigma": xp.asarray([0.1, 0.2, 0.4, 0.7], dtype=getattr(xp, dtype)), "let": xp.asarray([2.0, 4.0, 5.0, 0.0], dtype=getattr(xp, dtype)), } prepare = Mock(wraps=engine._prepare_depth_interpolator) engine._prepare_depth_interpolator = prepare for offset in (0.0, 0.134, -0.23, 8.5): grid = kernel["depths"] + kernel["offset"] - offset q = xp.concat([grid, grid + 0.01, grid - 0.01]) bixel = dict(kernel=kernel, rad_depths=q, rad_depth_offset=offset) > expected = interp1d( q, grid, { "idd": kernel["idd"] * 1.6021766208e-02, "sigma": kernel["sigma"], "let": kernel["let"], }, ) test/dose/test_particle_interpolators.py:48: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:411: in interp1d return {key: _interpolation(xq, x, ytmp, left, right) for key, ytmp in y.items()} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/compat.py:117: in _interp1d_core x0 = x[i0] ^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([0.03217, 0.13217, 0.83217, 2.03217], dtype=array_api_strict.float64) key = Array([0, 0, 1, 2, 0, 1, 2, 2, 0, 0, 1, 2], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 0 1 2 0 1 2 2 0 0 1 2] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ______________ test_reused_engine_rebuilds_prepared_state[False] _______________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) trace_on_dose_grid = False @pytest.mark.parametrize("trace_on_dose_grid", [False, True]) def test_reused_engine_rebuilds_prepared_state(test_data_protons, trace_on_dose_grid): """Rebuild every per-calculation cache on engine reuse for both tracing grids.""" pln, ct, cst, stf, _, _ = test_data_protons engine = ParticleHongPencilBeamEngine(pln) engine.console_progress = False engine.trace_on_dose_grid = trace_on_dose_grid > first = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_interpolators.py:123: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________ test_reused_engine_rebuilds_prepared_state[True] _______________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) trace_on_dose_grid = True @pytest.mark.parametrize("trace_on_dose_grid", [False, True]) def test_reused_engine_rebuilds_prepared_state(test_data_protons, trace_on_dose_grid): """Rebuild every per-calculation cache on engine reuse for both tracing grids.""" pln, ct, cst, stf, _, _ = test_data_protons engine = ParticleHongPencilBeamEngine(pln) engine.console_progress = False engine.trace_on_dose_grid = trace_on_dose_grid > first = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_interpolators.py:123: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ______________ test_particle_beams_use_their_own_lateral_cutoffs _______________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_particle_beams_use_their_own_lateral_cutoffs(test_data_protons): # Lateral cutoffs are recomputed per beam from its SSDs; a later beam must not reuse # kernels cached with an earlier beam's cutoffs. Off-center, the beams' SSDs differ. pln, ct, cst, stf, _, _ = test_data_protons assert len(stf.beams) > 1 stf = _shifted_stf(stf, np.array([0.0, -3.0, 0.0])) > dij = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_particle_lateral_cutoff.py:23: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806892, 1.0004952], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806892, 1.0004952], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _________ test_ssd_metadata_transferred_in_batches[array_api_strict-1] _________ engine = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff829f3070> rays = 1 @pytest.mark.parametrize("rays", [1, 7]) def test_ssd_metadata_transferred_in_batches(engine, monkeypatch, rays): """Transfer SSD values and validity flags once each, independent of ray count.""" xp = engine.xp beam = { "num_of_rays": rays, "sad": 1000.0, "iso_center": xp.zeros(3, dtype=xp.float32), "source_point": xp.asarray([0.0, -1000.0, 0.0], dtype=xp.float32), "rays": [ { "ray_pos_bev": xp.asarray([float(i), 0.0, 0.0], dtype=xp.float32), "target_point": xp.asarray([float(i), 1000.0, 0.0], dtype=xp.float32), } for i in range(rays) ], } alpha = xp.asarray(np.tile([0.1, 0.3, 0.8], (rays, 1)), dtype=xp.float32) rho = xp.asarray(np.tile([0.0, 0.5, 1.0], (rays, 1)), dtype=xp.float32) d12 = xp.asarray(np.arange(rays) + 2000, dtype=xp.float32) engine._raytracer = SimpleNamespace(trace_rays=lambda *args: (alpha, None, [rho], d12, None)) transfers = [] def download(value): transfers.append(value.shape) return to_numpy(value) monkeypatch.setattr("pyRadPlan.dose.engines._base_pencilbeam.to_numpy", download) > engine._compute_ssd({"beam": beam}, None) test/dose/test_ray_geometry_preparation.py:187: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:717: in _compute_ssd alpha = to_namespace(xp, alpha, device=self.device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________ test_ssd_metadata_transferred_in_batches[array_api_strict-7] _________ engine = monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff82a9c910> rays = 7 @pytest.mark.parametrize("rays", [1, 7]) def test_ssd_metadata_transferred_in_batches(engine, monkeypatch, rays): """Transfer SSD values and validity flags once each, independent of ray count.""" xp = engine.xp beam = { "num_of_rays": rays, "sad": 1000.0, "iso_center": xp.zeros(3, dtype=xp.float32), "source_point": xp.asarray([0.0, -1000.0, 0.0], dtype=xp.float32), "rays": [ { "ray_pos_bev": xp.asarray([float(i), 0.0, 0.0], dtype=xp.float32), "target_point": xp.asarray([float(i), 1000.0, 0.0], dtype=xp.float32), } for i in range(rays) ], } alpha = xp.asarray(np.tile([0.1, 0.3, 0.8], (rays, 1)), dtype=xp.float32) rho = xp.asarray(np.tile([0.0, 0.5, 1.0], (rays, 1)), dtype=xp.float32) d12 = xp.asarray(np.arange(rays) + 2000, dtype=xp.float32) engine._raytracer = SimpleNamespace(trace_rays=lambda *args: (alpha, None, [rho], d12, None)) transfers = [] def download(value): transfers.append(value.shape) return to_numpy(value) monkeypatch.setattr("pyRadPlan.dose.engines._base_pencilbeam.to_numpy", download) > engine._compute_ssd({"beam": beam}, None) test/dose/test_ray_geometry_preparation.py:187: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:717: in _compute_ssd alpha = to_namespace(xp, alpha, device=self.device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:797: in to_namespace device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________________ test_nominal_set_has_one_flat_slot[protons] __________________ case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 2, 1, 1]), num_of_rays=5, total_number_of_bixels=6)])) def test_nominal_set_has_one_flat_slot(case): pln, ct, cst, stf = case > engine, dij, slots = _calc(pln, ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:104: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _________________ test_nominal_set_has_one_flat_slot[photons] __________________ case = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 1, 1, 1]), num_of_rays=5, total_number_of_bixels=5)])) def test_nominal_set_has_one_flat_slot(case): pln, ct, cst, stf = case > engine, dij, slots = _calc(pln, ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:104: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff _______________ test_scenarios_are_recorded_on_the_dij[protons] ________________ case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 2, 1, 1]), num_of_rays=5, total_number_of_bixels=6)])) def test_scenarios_are_recorded_on_the_dij(case): pln, ct, cst, stf = case engine = get_engine(pln) > dij = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________ test_scenarios_are_recorded_on_the_dij[photons] ________________ case = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 1, 1, 1]), num_of_rays=5, total_number_of_bixels=5)])) def test_scenarios_are_recorded_on_the_dij(case): pln, ct, cst, stf = case engine = get_engine(pln) > dij = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:116: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ___________________ test_setup_and_range_scenarios[protons] ____________________ case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 2, 1, 1]), num_of_rays=5, total_number_of_bixels=6)])) monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff821adef0> def test_setup_and_range_scenarios(case, monkeypatch): pln, ct, cst, stf = case scen_set = _scenario_set( setup=[(0.0, 0.0, 0.0), SHIFT_X, (0.0, 0.0, 0.0)], range_=[(0.0, 0.0), (0.0, 0.0), RANGE_ABS], ) > engine, dij, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:128: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 def test_setup_and_range_scenarios(case, monkeypatch): pln, ct, cst, stf = case scen_set = _scenario_set( setup=[(0.0, 0.0, 0.0), SHIFT_X, (0.0, 0.0, 0.0)], range_=[(0.0, 0.0), (0.0, 0.0), RANGE_ABS], ) > engine, dij, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:128: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 _, dij, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:159: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 _, _, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:183: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.873833 , -1.661701 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.49...33 , 1.661701 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/4 [00:00 _, _, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:183: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.873833 , -1.661701 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.661701 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/4 [00:00 _, _, nominal = _calc(pln, ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:222: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _________ test_ct_phase_with_moved_outline_matches_standalone[photons] _________ case = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 1, 1, 1]), num_of_rays=5, total_number_of_bixels=5)])) def test_ct_phase_with_moved_outline_matches_standalone(case): """SSD-dependent quantities follow the phase, also when phase 0 is not computed.""" pln, ct, cst, stf = case ct2, ct_phase1 = _two_phase_ct_moved_outline(ct) > _, _, nominal = _calc(pln, ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:222: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff _______________ test_ct_phase_selection_bio_single_and_reordered _______________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_ct_phase_selection_bio_single_and_reordered(test_data_protons): pln, ct, cst, stf, _, _ = test_data_protons pln.bio_model = "MCN" ct2, ct_phase1 = _two_phase_ct_moved_outline(ct) > _, ref, _ = _calc(pln, ct_phase1, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:244: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model _______________________ test_ct_phase_selection[protons] _______________________ case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 2, 1, 1]), num_of_rays=5, total_number_of_bixels=6)])) def test_ct_phase_selection(case): pln, ct, cst, stf = case ct2, ct_phase1 = _two_phase_ct(ct) assert ct2.num_of_ct_scen == 2 scen_set = _scenario_set(ct_phase=[1, 0], phases=(0, 1)) > _, dij, slots = _calc(pln, ct2, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 _, dij, slots = _calc(pln, ct2, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:265: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = engine.calc_dose_influence(ct2, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:304: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 engine, dij, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:318: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 engine, dij, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:318: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = engine.calc_dose_influence(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:333: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = calc_dose_influence(ct, cst, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:383: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 result = calc_dose_forward(ct, cst, stf, pln, w, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:397: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.873833 , -1.661701 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.661701 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 result = calc_dose_forward(ct, cst, stf, pln, w, scenarios=alias_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:431: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff __________________ test_shift_scenarios_in_biological_results __________________ test_data_protons = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... 0., 0., ..., 0., 0., 0.]]], shape=(20, 10, 10)), 'MU': array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8), ...}) def test_shift_scenarios_in_biological_results(test_data_protons): """Result assembly reads the reference alpha/beta of every shift scenario correctly.""" > dij, refs = _bio_shift_dijs(test_data_protons) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:455: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:448: in _bio_shift_dijs _, dij, _ = _calc(pln, ct, cst, stf, scenarios=_scenario_set(setup=BIO_SHIFTS)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.873833 , -1.661701 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.49...33 , 1.661701 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/4 [00:00 dij, refs = _bio_shift_dijs(test_data_protons) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:469: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:448: in _bio_shift_dijs _, dij, _ = _calc(pln, ct, cst, stf, scenarios=_scenario_set(setup=BIO_SHIFTS)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.873833 , -1.661701 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.49...33 , 1.661701 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/4 [00:00 _calc(pln, ct, cst, stf, scenarios=scen_set) test/dose/test_scenarios_pencilbeam.py:500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 _calc(pln, ct, cst, stf, scenarios=scen_set) test/dose/test_scenarios_pencilbeam.py:500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 _, _, separate = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:526: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 _, _, separate = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:526: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/3 [00:00 _, _, nominal = _calc(pln, ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:542: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine HongPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model ________ test_rays_missing_the_patient_take_the_ssd_of_their_neighbors _________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_rays_missing_the_patient_take_the_ssd_of_their_neighbors(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons scen_set = _scenario_set(setup=[(0.0, 0.0, 0.0), (0.0, 0.0, 60.0)]) with pytest.warns(UserWarning, match="do not hit patient"): > _, _, slots = _calc(pln, ct, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:557: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError During handling of the above exception, another exception occurred: test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_rays_missing_the_patient_take_the_ssd_of_their_neighbors(test_data_photons): pln, ct, cst, stf, _, _ = test_data_photons scen_set = _scenario_set(setup=[(0.0, 0.0, 0.0), (0.0, 0.0, 60.0)]) > with pytest.warns(UserWarning, match="do not hit patient"): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E Failed: DID NOT WARN. No warnings of type (,) matching the regex were emitted. E Regex: do not hit patient E Emitted warnings: [ UserWarning('Property "lateral_model" not found in PhotonPencilBeamSVDEngine!'), E UserWarning('Requested GPU device is not available on array_api_strict. Falling back to CPU.'), E UserWarning('Requested GPU device is not available on array_api_strict. Falling back to CPU.'), E RuntimeWarning('divide by zero encountered in divide'), E RuntimeWarning('divide by zero encountered in divide')]. test/dose/test_scenarios_pencilbeam.py:556: Failed ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = calc_dose_influence(ct2, cst, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:574: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff _______ test_4d_structure_set_gives_the_same_influence_matrices[protons] _______ case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...gnore_outside_densities=None, num_of_bixels_per_ray=array([1, 1, 2, 1, 1]), num_of_rays=5, total_number_of_bixels=6)])) def test_4d_structure_set_gives_the_same_influence_matrices(case): from pyRadPlan.cst import validate_cst pln, ct, cst, stf = case ct2, _ = _two_phase_ct(ct) cst4d = validate_cst(cst, ct=ct2) assert cst4d.num_of_scenarios == 2 scen_set = _scenario_set(ct_phase=[0, 1], phases=(0, 1)) > _, _, with_3d = _calc(pln, ct2, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:594: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam_particle.py:558: in _init_beam beam_info = super()._init_beam(dij, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.9806835, 1.0004953], [ 0.8838835, -0.8838835]], [[ 2.35...67 , 1.767767 ], [ 0.9806835, 1.0004953], [-0.8838835, 0.8838835]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 _, _, with_3d = _calc(pln, ct2, cst, stf, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:594: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:76: in _calc dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = calc_dose_influence(ct2, cst, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:606: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, dij = _moving_structure_problem(test_data_photons, robustness) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:654: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, dij = _moving_structure_problem(test_data_photons, robustness) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:654: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, dij = _moving_structure_problem(test_data_photons, robustness) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:654: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, dij = _moving_structure_problem(test_data_photons, robustness) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:654: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, dij = _moving_structure_problem(test_data_photons, "none") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:679: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 problem, _ = _moving_structure_problem(test_data_photons, "none") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:696: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/dose/test_scenarios_pencilbeam.py:643: in _moving_structure_problem dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:723: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 dij = calc_dose_influence(ct2, moved, stf, pln, scenarios=scen_set) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_scenarios_pencilbeam.py:745: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.2963624 , -1.0606601 ], [ 0.80995476, 0.9909502 ], [ 0.9722718 , -0.79549515]], [... 1.0606601 ], [ 0.80995476, 0.9909502 ], [-0.9722718 , 0.79549515]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- Scenarios: 0%| | 0/2 [00:00 result_py = calc_dose_forward(ct, cst, stf, pln, weights=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb.py:17: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ___________________________ test_photons_field_based ___________________________ def test_photons_field_based(): """Exercise the per-ray kernel interpolation path (_init_ray) on the configured backend. Field-based dose calculation is the one configuration that reaches ``_init_ray``'s custom fluence branch, which builds its own kernel interpolators via FFT convolution. The default configuration skips it entirely, so it needs its own coverage. """ ct, cst = load_tg119() leaf_width = 5.0 positions = [[-20.0, 20.0]] * 4 boundaries = np.arange(-2 * leaf_width, 2 * leaf_width, leaf_width) mlc = create_bld( { "device_type": "MLC", "device_orientation": "X", "leaf_position_boundaries": boundaries, "leaf_positions": positions, "leaf_width": leaf_width, "leaf_leakage": 0.1, } ) pln = PhotonPlan(machine="Generic") pln.prop_stf = { "gantry_angles": [0.0], "couch_angles": [0.0], "generator": "photonSingleBixel", "field_based": True, "blds": [mlc], "resolution": 2.0, "energy": 6.0, } pln.prop_dose_calc["dosimetric_lateral_cutoff"] = 0.995 pln.prop_dose_calc["lateral_model"] = "single" stf = generate_stf(ct, cst, pln) masks = [b.mask.copy() for beam in stf.beams for ray in beam.rays for b in ray.beamlets] > dose = sitk.GetArrayFromImage(calc_dose_forward(ct, cst, stf, pln)["physical_dose"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb.py:63: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:93: in calc_dose_forward return engine.calc_dose_forward(ct, cst, stf, weights, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 35.75258 , -35.6652 ], [ 0.69623196, 1.1575938 ], [ 2.1070771 , -2.0712812 ]], ...65203 ], [ 0.69623196, 1.1575938 ], [ -2.1070771 , 2.0712812 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ____________ test_bixel_based_lateral_cutoff_includes_half_diagonal ____________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_bixel_based_lateral_cutoff_includes_half_diagonal(test_data_photons): """matRad widens the lateral cutoff by bixelWidth/sqrt(2) for bixel-based dose too.""" pln, ct, cst, stf, _, _ = test_data_photons engine = get_engine(pln) > engine.calc_dose_forward(ct, cst, stf, None) test/dose/test_svdpb.py:91: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:469: in calc_dose_forward dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff _______________ test_photons_constant_rbe_is_stored_and_applied ________________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_photons_constant_rbe_is_stored_and_applied(test_data_photons): """A constant-RBE photon plan yields dij.rbe and rbe * physical_dose.""" pln, ct, cst, stf, _dij, result = test_data_photons pln.bio_model = {"model": "constant_rbe", "rbe": 1.5} > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb_bio.py:24: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ____________________ test_photons_default_model_is_recorded ____________________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) def test_photons_default_model_is_recorded(test_data_photons): pln, ct, cst, stf, _dij, _result = test_data_photons > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb_bio.py:40: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff ______________ test_photon_engine_drops_a_model_it_cannot_compute ______________ test_data_photons = (PhotonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'is... [0. , 0. , 0. , ..., 0. , 0. , 0. ]]], shape=(20, 10, 10)), ...}) caplog = <_pytest.logging.LogCaptureFixture object at 0xffff825875d0> def test_photon_engine_drops_a_model_it_cannot_compute(test_data_photons, caplog): """A model with outputs the engine cannot compute falls back to physical dose, reported.""" pln, ct, cst, stf, _dij, _result = test_data_photons pln.bio_model = _PhotonLQModel() with caplog.at_level(logging.WARNING): > dij_py = calc_dose_influence(ct, cst, stf, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb_bio.py:63: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/_calc_dose.py:51: in calc_dose_influence dij = engine.calc_dose_influence(ct, cst, stf, scenarios=scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:523: in calc_dose_influence dij = self._calc_dose_with_scenarios(ct, cst, stf, scenarios) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:535: in _calc_dose_with_scenarios return self._calc_dose(ct, cst, stf) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:230: in _calc_dose curr_beam = self._init_beam(dij, ct, cst, scen_stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_svdpb.py:163: in _init_beam beam_info = super()._init_beam(beam_info, ct, cst, stf, i) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:597: in _init_beam rad_depth_cubes = self._raytracer.trace_cubes_array( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.767767 , -1.767767 ], [ 0.82191783, 1.0045662 ], [ 0.7856742 , -0.7856742 ]], [... 1.767767 ], [ 0.82191783, 1.0045662 ], [-0.7856742 , 0.7856742 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.dose.engines._factory:_factory.py:143 No engine specified in Plan. Using first available engine SVDPB. WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: lateral_model WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dose_grid WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: enable_dij_sampling WARNING pyRadPlan.core._configurable:_configurable.py:336 Property overwritten from pln.propDoseCalc: dosimetric_lateral_cutoff WARNING pyRadPlan.dose.engines._base:_base.py:1006 Biological model 'photon_lq_capability_test' cannot be evaluated for this machine and these structures: Biological model 'photon_lq_capability_test' not available: The dose engine SVDPB does not compute biological influence matrices. Biological quantities (e.g. RBExDose) will not be available; only the physical dose influence is computed. Choose a biological model and tissue parameters matching the machine base data, or set calc_bio_dose=True to make this an error. _ test_kernel_interpolators_reuse_and_fluence_isolation[array_api_strict-float32] _ interpolation_backend = dtype_name = 'float32' @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_kernel_interpolators_reuse_and_fluence_isolation(interpolation_backend, dtype_name): """Repeated queries preserve values; another field cannot overwrite the first.""" xp = interpolation_backend dtype = getattr(xp, dtype_name) engine = SimpleNamespace(xp=xp, device=None) grid = xp.asarray([-2, -1, 0, 1, 2], dtype=dtype) kernels = xp.asarray(np.arange(18).reshape(2, 3, 3) / 20, dtype=dtype) fluence = xp.asarray([[0.0, 1.0], [0.5, 0.25]], dtype=dtype) info = { "kernel": SimpleNamespace(num_kernel_components=2), "kernel_conv_grid": grid, "kernel_conv_size": 5, "kernel_mxs": kernels, } queries = xp.asarray([[-2, -2], [2, 2], [0.25, -0.75], [-1, 1]], dtype=dtype) expected = [] for c in range(kernels.shape[0]): kernel = kernels[c, ...] values = xp.real(_ifft2(_fft2(fluence, s=(5, 5)) * _fft2(kernel, s=(5, 5)))) > expected.append(interpnd(queries, (grid, grid), values, bounds_error=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb_interpolators.py:45: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., -1., 0., 1., 2.], dtype=array_api_strict.float32) key = Array([0, 3, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 3 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _ test_kernel_interpolators_reuse_and_fluence_isolation[array_api_strict-float64] _ interpolation_backend = dtype_name = 'float64' @pytest.mark.parametrize("dtype_name", ["float32", "float64"]) def test_kernel_interpolators_reuse_and_fluence_isolation(interpolation_backend, dtype_name): """Repeated queries preserve values; another field cannot overwrite the first.""" xp = interpolation_backend dtype = getattr(xp, dtype_name) engine = SimpleNamespace(xp=xp, device=None) grid = xp.asarray([-2, -1, 0, 1, 2], dtype=dtype) kernels = xp.asarray(np.arange(18).reshape(2, 3, 3) / 20, dtype=dtype) fluence = xp.asarray([[0.0, 1.0], [0.5, 0.25]], dtype=dtype) info = { "kernel": SimpleNamespace(num_kernel_components=2), "kernel_conv_grid": grid, "kernel_conv_size": 5, "kernel_mxs": kernels, } queries = xp.asarray([[-2, -2], [2, 2], [0.25, -0.75], [-1, 1]], dtype=dtype) expected = [] for c in range(kernels.shape[0]): kernel = kernels[c, ...] values = xp.real(_ifft2(_fft2(fluence, s=(5, 5)) * _fft2(kernel, s=(5, 5)))) > expected.append(interpnd(queries, (grid, grid), values, bounds_error=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/dose/test_svdpb_interpolators.py:45: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:230: in interpnd return ArrayBackendGridInterpolator( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:154: in __call__ result = self._evaluate(xi) ^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_interpolation.py:248: in _interp2d_core gx0 = gx[ix] ^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([-2., -1., 0., 1., 2.], dtype=array_api_strict.float64) key = Array([0, 3, 2, 0], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 3 2 0] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError _______________________ test_import_ct_matches_reference _______________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') dicom_reference_mat = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom/dicom_testData.mat') def test_import_ct_matches_reference(dicom_dir, dicom_reference_mat): ref_ct = validate_ct(matfile.load(dicom_reference_mat)["ct"]) ct = DicomImporter(dicom_dir).load_ct() assert isinstance(ct, CT) assert ct.cube_hu.GetSize() == ref_ct.cube_hu.GetSize() > assert np.allclose(ct.cube_hu.GetSpacing(), ref_ct.cube_hu.GetSpacing()) E AssertionError: assert False E + where False = ((15.0, 10.0, 5.0), (10.0, 15.0, 5.0)) E + where = np.allclose E + and (15.0, 10.0, 5.0) = GetSpacing() E + where GetSpacing = >.GetSpacing E + where > = CT(cube_hu= >, reso...10., 0., 10., 20.,\n 30., 40.]), z=array([-25., -20., -15., -10., -5., 0., 5., 10., 15., 20.])).cube_hu E + and (10.0, 15.0, 5.0) = GetSpacing() E + where GetSpacing = >.GetSpacing E + where > = CT(cube_hu= >, reso...60., 75., 90., 105.,\n 120., 135.]), z=array([-25., -20., -15., -10., -5., 0., 5., 10., 15., 20.])).cube_hu test/io/test_io_dicom.py:76: AssertionError ----------------------------- Captured stderr call ----------------------------- ______________________ test_import_cst_matches_reference _______________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') dicom_reference_mat = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom/dicom_testData.mat') def test_import_cst_matches_reference(dicom_dir, dicom_reference_mat): m = matfile.load(dicom_reference_mat) ref_ct = validate_ct(m["ct"]) ref_cst = validate_cst(m["cst"], ref_ct) importer = DicomImporter(dicom_dir) ct = importer.load_ct() cst = importer.load_cst(ct) assert isinstance(cst, StructureSet) sets = _voxel_sets(cst) ref_sets = _voxel_sets(ref_cst) assert set(sets) == set(ref_sets) for name, voxels in ref_sets.items(): # The RTSTRUCT contour->mask conversion must reproduce the reference voxels exactly. > assert voxels == sets[name], f"VOI '{name}' voxels differ from reference" E AssertionError: VOI 'target' voxels differ from reference E assert {1341, 1342, ...57, 1358, ...} == {1399, 1400, ...29, 1430, ...} E E Extra items in the left set: E 1641 E 1642 E 1643 E 1356 E 1357... E E ...Full output truncated (21 lines hidden), use '-vv' to show test/io/test_io_dicom.py:101: AssertionError ----------------------------- Captured stderr call ----------------------------- _______________________ test_load_data_from_dicom_folder _______________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') dicom_reference_mat = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom/dicom_testData.mat') def test_load_data_from_dicom_folder(dicom_dir, dicom_reference_mat): data = load_data(dicom_dir) assert isinstance(data["ct"], CT) assert isinstance(data["cst"], StructureSet) assert isinstance(data["dose"], sitk.Image) # The folder holds per-beam doses and LET cubes (all modality RTDOSE); # load_data must select the plan-level physical dose, not an arbitrary one. ref_dose = np.asarray(matfile.load(dicom_reference_mat)["resultGUI"]["physicalDose"]) ref_zyx = np.transpose(ref_dose, (2, 0, 1)) arr = sitk.GetArrayFromImage(data["dose"]) assert arr.shape == ref_zyx.shape > assert np.allclose(arr, ref_zyx, atol=1e-3) E assert False E + where False = (array([[[0. , 0. , 0. , ..., 0. ,\n 0. , 0. ],\n [0. , 0... , 0. , 0. , ..., 0. ,\n 0. , 0. ]]], shape=(10, 20, 15), dtype=float32), array([[[0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]...0000000e+00, 0.00000000e+00, ...,\n 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]]],\n shape=(10, 20, 15)), atol=0.001) E + where = np.allclose test/io/test_io_dicom.py:165: AssertionError ----------------------------- Captured stderr call ----------------------------- ___________________________ test_dicom_roundtrip_ct ____________________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_dicom_roundtrip_ct0') def test_dicom_roundtrip_ct(dicom_dir, tmp_path): ct = DicomImporter(dicom_dir).load_ct() DicomExporter(tmp_path).save(ct=ct) ct2 = DicomImporter(tmp_path).load_ct() assert ct2.cube_hu.GetSize() == ct.cube_hu.GetSize() > assert np.allclose(ct2.cube_hu.GetSpacing(), ct.cube_hu.GetSpacing()) E AssertionError: assert False E + where False = ((10.0, 15.0, 5.0), (15.0, 10.0, 5.0)) E + where = np.allclose E + and (10.0, 15.0, 5.0) = GetSpacing() E + where GetSpacing = >.GetSpacing E + where > = CT(cube_hu= >, reso...60., 75., 90., 105.,\n 120., 135.]), z=array([-25., -20., -15., -10., -5., 0., 5., 10., 15., 20.])).cube_hu E + and (15.0, 10.0, 5.0) = GetSpacing() E + where GetSpacing = >.GetSpacing E + where > = CT(cube_hu= >, reso...10., 0., 10., 20.,\n 30., 40.]), z=array([-25., -20., -15., -10., -5., 0., 5., 10., 15., 20.])).cube_hu test/io/test_io_dicom.py:229: AssertionError ----------------------------- Captured stderr call ----------------------------- __________________________ test_dicom_roundtrip_dose ___________________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_dicom_roundtrip_dose0') def test_dicom_roundtrip_dose(dicom_dir, tmp_path): dose = import_dose(str(dicom_dir / "RTDose_6_physicalDose.dcm")) DicomExporter(tmp_path).save(ct=DicomImporter(dicom_dir).load_ct(), dose=dose) dose2 = DicomImporter(tmp_path).load_dose() a = sitk.GetArrayFromImage(dose) b = sitk.GetArrayFromImage(dose2) assert b.shape == a.shape # uint32 quantization -> values reproduced to high precision. > assert np.allclose(a, b, atol=1e-4 * max(a.max(), 1.0)) E assert False E + where False = (array([[[0. , 0. , 0. , ..., 0. ,\n 0. , 0. ],\n [0. , 0... , 0. , 0. , ..., 0. ,\n 0. , 0. ]]], shape=(10, 20, 15), dtype=float32), array([[[0. , 0. , 0. , ..., 0. ,\n 0. , 0. ],\n [0. , 0... , 0. , 0. , ..., 0. ,\n 0. , 0. ]]], shape=(10, 20, 15), dtype=float32), atol=(0.0001 * np.float32(1.6662134))) E + where = np.allclose E + and np.float32(1.6662134) = max(np.float32(1.6662134), 1.0) E + where np.float32(1.6662134) = () E + where = array([[[0. , 0. , 0. , ..., 0. ,\n 0. , 0. ],\n [0. , 0... , 0. , 0. , ..., 0. ,\n 0. , 0. ]]], shape=(10, 20, 15), dtype=float32).max test/io/test_io_dicom.py:245: AssertionError ----------------------------- Captured stderr call ----------------------------- _______________________ test_dicom_roundtrip_structures ________________________ dicom_dir = PosixPath('/builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/data/dicom') tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_dicom_roundtrip_structure0') def test_dicom_roundtrip_structures(dicom_dir, tmp_path): importer = DicomImporter(dicom_dir) ct = importer.load_ct() cst = importer.load_cst(ct) DicomHandler(tmp_path).save(ct=ct, cst=cst) cst2 = DicomImporter(tmp_path).load_cst() sets = _voxel_sets(cst) sets2 = _voxel_sets(cst2) assert set(sets) == set(sets2) for name, voxels in sets.items(): # Contour extraction then re-rasterization is near-lossless (boundary voxels). > assert _dice(voxels, sets2[name]) > 0.95, f"VOI '{name}' degraded in roundtrip" E AssertionError: VOI 'target' degraded in roundtrip E assert 0.0 > 0.95 E + where 0.0 = _dice({1399, 1400, 1414, 1415, 1429, 1430, ...}, {1341, 1342, 1343, 1356, 1357, 1358, ...}) test/io/test_io_dicom.py:261: AssertionError ----------------------------- Captured stderr call ----------------------------- _________________________ test_expected_value_operator _________________________ three_scenarios = ScenarioSet(num_scenarios=3, dimensions=('ct_phase', 'setup', 'range'), axes=(('ct_phase.index',), ('setup.x', 'setup.y', 'setup.z'), ('range.abs', 'range.rel'))) def test_expected_value_operator(three_scenarios): objective = SquaredDeviation(d_ref=1.0, priority=3.0) op = get_robustness_operator("STOCH", three_scenarios, RobustnessOptions()) assert op.scenario_indices == [0, 1, 2] np.testing.assert_allclose(op.weights, [0.5, 0.3, 0.2]) values = xp.asarray(np.array([[2.0, 0.0], [1.0, 1.0], [0.0, 3.0]])) entries = [RobustTermEntry(objective, "TARGET")] per_scenario = [float(objective.compute_objective(values[s, ...])) for s in range(3)] expected = 3.0 * np.dot([0.5, 0.3, 0.2], per_scenario) > assert float(op.evaluate(entries, [values])) == pytest.approx(expected) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_robustness_contract.py:163: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:34: in evaluate weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_gradient_follows_the_dtype_of_the_values[expected_value] _________ three_scenarios = ScenarioSet(num_scenarios=3, dimensions=('ct_phase', 'setup', 'range'), axes=(('ct_phase.index',), ('setup.x', 'setup.y', 'setup.z'), ('range.abs', 'range.rel'))) robustness = 'expected_value' @pytest.mark.parametrize("robustness", ["none", "expected_value", "scenario_stack"]) def test_gradient_follows_the_dtype_of_the_values(three_scenarios, robustness): objective = ( _Float64StackGradient(d_max=1.0) if robustness == "scenario_stack" else _Float64Gradient(d_max=1.0) ) op = get_robustness_operator(robustness, three_scenarios) values = xp.asarray(np.full((op.num_scenarios, 3), 2.0), dtype=xp.float32) > grad = op.gradient([RobustTermEntry(objective)], [values])[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_robustness_contract.py:254: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:42: in gradient weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ____________________________ test_expected_quantity ____________________________ three_scenarios = ScenarioSet(num_scenarios=3, dimensions=('ct_phase', 'setup', 'range'), axes=(('ct_phase.index',), ('setup.x', 'setup.y', 'setup.z'), ('range.abs', 'range.rel'))) operator_fd = ._fd at 0xffff81af81a0> def test_expected_quantity(three_scenarios, operator_fd): objective = SquaredDeviation(d_ref=2.0, priority=3.0) op = get_robustness_operator("expected_quantity", three_scenarios) assert isinstance(op, ExpectedQuantity) assert op.scenario_indices == [0, 1, 2] entries = [RobustTermEntry(objective, "TARGET")] values = [xp.asarray(VALUES)] expected = np.array([0.5, 0.3, 0.2]) @ VALUES > assert float(op.evaluate(entries, values)) == pytest.approx( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 3.0 * np.mean((expected - 2.0) ** 2) ) test/optimization/robustness/test_robustness_operators.py:44: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:37: in evaluate _, expected = self._expected(values[0]) ^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:31: in _expected weights = as_backend(self.weights / total if total > 0.0 else self.weights, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_expected_quantity_is_a_mean_for_any_weight_sum[weights0] _________ make_set = , weights = [1.0, 1.0] @pytest.mark.parametrize("weights", [[1.0, 1.0], [0.3, 0.3]]) def test_expected_quantity_is_a_mean_for_any_weight_sum(make_set, weights): scen_set = make_set([(0.0, 0.0, 0.0), (3.0, 0.0, 0.0)], weights=weights) op = ExpectedQuantity(scen_set) objective = SquaredDeviation(d_ref=2.0) entries = [RobustTermEntry(objective)] values = xp.asarray(np.array([[1.0, 1.0], [3.0, 3.0]])) > assert float(op.evaluate(entries, [values])) == pytest.approx(0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_robustness_operators.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:37: in evaluate _, expected = self._expected(values[0]) ^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:31: in _expected weights = as_backend(self.weights / total if total > 0.0 else self.weights, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________ test_expected_quantity_is_a_mean_for_any_weight_sum[weights1] _________ make_set = , weights = [0.3, 0.3] @pytest.mark.parametrize("weights", [[1.0, 1.0], [0.3, 0.3]]) def test_expected_quantity_is_a_mean_for_any_weight_sum(make_set, weights): scen_set = make_set([(0.0, 0.0, 0.0), (3.0, 0.0, 0.0)], weights=weights) op = ExpectedQuantity(scen_set) objective = SquaredDeviation(d_ref=2.0) entries = [RobustTermEntry(objective)] values = xp.asarray(np.array([[1.0, 1.0], [3.0, 3.0]])) > assert float(op.evaluate(entries, [values])) == pytest.approx(0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_robustness_operators.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:37: in evaluate _, expected = self._expected(values[0]) ^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_quantity.py:31: in _expected weights = as_backend(self.weights / total if total > 0.0 else self.weights, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ____ test_operators_on_phase_contours_match_equal_contours[expected_value] _____ make_set = , name = 'expected_value' @pytest.mark.parametrize( "name", ["none", "expected_value", "objective_worst_case", "composite_worst_case"] ) def test_operators_on_phase_contours_match_equal_contours(make_set, name): """A list per scenario gives the same as the stack, and works for unequal voxel counts.""" scen_set = make_set([(0.0, 0.0, 0.0), (0.0, 0.0, 0.0)], weights=[0.5, 0.5], ct_phase=[0, 1]) op = get_robustness_operator(name, scen_set, RobustnessOptions()) assert op.phase_contours entries = [RobustTermEntry(SquaredDeviation(d_ref=1.0, priority=2.0), "TARGET")] first = np.array([2.0, 0.0]) second = np.array([1.0, 3.0]) stacked = xp.asarray(np.stack([first, second])) listed = [xp.asarray(first), xp.asarray(second)] > assert float(op.evaluate(entries, [listed])) == pytest.approx( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ float(op.evaluate(entries, [stacked])) ) test/optimization/robustness/test_robustness_operators.py:239: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:34: in evaluate weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________________ test_variance_closed_form_uniform_default ___________________ def test_variance_closed_form_uniform_default(): objective = Variance() values = xp.asarray(np.array([[1.0, 2.0], [3.0, 4.0]])) > assert float(objective.compute_objective(values)) == pytest.approx(1.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_variance_objective.py:23: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:63: in compute_objective xp, weights, deviation = self._deviation(values, weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:43: in _deviation xp_utils.from_numpy( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________________ test_variance_weighted_value_and_gradient ___________________ finite_difference = def test_variance_weighted_value_and_gradient(finite_difference): objective = Variance() values = xp.asarray(VALUES) mean = WEIGHTS @ VALUES expected = np.mean(np.average((VALUES - mean) ** 2, axis=0, weights=WEIGHTS)) > assert float(objective.compute_objective(values, weights=WEIGHTS)) == pytest.approx(expected) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_variance_objective.py:36: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:63: in compute_objective xp, weights, deviation = self._deviation(values, weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:43: in _deviation xp_utils.from_numpy( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _____________________ test_variance_through_scenario_stack _____________________ three_scenarios = ScenarioSet(num_scenarios=3, dimensions=('ct_phase', 'setup', 'range'), axes=(('ct_phase.index',), ('setup.x', 'setup.y', 'setup.z'), ('range.abs', 'range.rel'))) operator_fd = ._fd at 0xffff824fc7d0> def test_variance_through_scenario_stack(three_scenarios, operator_fd): objective = Variance(priority=4.0, robustness="OWC") assert objective.robustness == "scenario_stack" assert Variance.available_robustness() == ["scenario_stack"] op = ScenarioStack(three_scenarios) entries = [RobustTermEntry(objective)] values = [xp.asarray(VALUES)] mean = WEIGHTS @ VALUES expected = 4.0 * np.mean(np.average((VALUES - mean) ** 2, axis=0, weights=WEIGHTS)) > assert float(op.evaluate(entries, values)) == pytest.approx(expected) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/robustness/test_variance_objective.py:64: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_base.py:191: in evaluate return objective.priority * objective.compute_objective(values[0], weights=self.weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:63: in compute_objective xp, weights, deviation = self._deviation(values, weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:43: in _deviation xp_utils.from_numpy( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.optimization.objectives._objective:_objective.py:384 Objective 'Variance' evaluates the scenarios itself; robustness 'OWC' is replaced by 'scenario_stack'. ___________________ test_solver_dict_configuration_survives ____________________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) def test_solver_dict_configuration_survives(small_proton_case): """max_iter/display from the solver dict are kept when not set at the top level.""" > solver = _solved_solver( small_proton_case, {"solver": {"name": "scipy", "max_iter": 42, "display": False}} ) test/optimization/test_fluence_optiprob.py:102: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/optimization/test_fluence_optiprob.py:96: in _solved_solver prob.solve(ct, cst, stf, dij) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _____________________ test_top_level_overrides_solver_dict _____________________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) def test_top_level_overrides_solver_dict(small_proton_case): """An explicitly set top-level value takes precedence over the same key in the dict.""" > solver = _solved_solver( small_proton_case, {"solver": {"name": "scipy", "max_iter": 42, "display": False}, "max_iter": 7}, ) test/optimization/test_fluence_optiprob.py:112: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/optimization/test_fluence_optiprob.py:96: in _solved_solver prob.solve(ct, cst, stf, dij) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________________ test_unset_properties_leave_solver_defaults __________________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) def test_unset_properties_leave_solver_defaults(small_proton_case): """Without any configuration the solver keeps its own defaults.""" reference = OptimizerSciPy() > solver = _solved_solver(small_proton_case, {"solver": "scipy"}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_fluence_optiprob.py:125: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/optimization/test_fluence_optiprob.py:96: in _solved_solver prob.solve(ct, cst, stf, dij) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________ test_constant_rbe_evaluates_only_the_quantities_it_uses ____________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...el(rbe=1.1), num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff7b7c3930> def test_constant_rbe_evaluates_only_the_quantities_it_uses(small_proton_case, monkeypatch): """The photon LQ effect a dij with alphax / betax allows is not evaluated for a constant RBE.""" pln, ct, cst, stf, dij = small_proton_case num_voxels = dij.dose_grid.num_voxels dij.alphax = np.full((num_voxels, 1), 0.1) dij.betax = np.full((num_voxels, 1), 0.05) dij.bio_model = {"model": "constant_rbe", "rbe": 1.1} pln.prop_opt = {"solver": {"name": "scipy", "max_iter": 2, "display": False}} prob = NonLinearFluencePlanningProblem(pln) > prob.solve(ct, cst, stf, dij) test/optimization/test_fluence_optiprob.py:182: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- ERROR pyRadPlan.optimization.problems._optiprob:_optiprob.py:449 Inconsistency found in bio parameters between biologocal reference alpha and beta parameters in CST and Dij. WARNING pyRadPlan.optimization.problems._optiprob:_optiprob.py:414 2 physical-dose objective(s) were converted to 'rbe_x_dose' for the biological model of the dose influence data. Set convert_dose_objectives=False to optimize physical dose instead. _________ test_objective_jacobian_has_one_row_per_objective[constant] __________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...el(rbe=1.1), num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) rbe_path = 'constant' @pytest.mark.parametrize("rbe_path", ["constant", "effect"]) def test_objective_jacobian_has_one_row_per_objective(small_proton_case, rbe_path): """Without the bypass, each objective gets its own gradient row, also across quantities.""" pln, ct, cst, stf, dij = small_proton_case if rbe_path == "constant": dij.bio_model = {"model": "constant_rbe", "rbe": 1.1} else: num_voxels = dij.dose_grid.num_voxels dij.alphax = np.full((num_voxels, 1), 0.1) dij.betax = np.full((num_voxels, 1), 0.05) alpha_dose = np.empty_like(dij.physical_dose) sqrt_beta_dose = np.empty_like(dij.physical_dose) for i, mat in enumerate(dij.physical_dose.flat): alpha_dose.flat[i] = 0.12 * mat sqrt_beta_dose.flat[i] = np.sqrt(0.05) * mat dij.alpha_dose = alpha_dose dij.sqrt_beta_dose = sqrt_beta_dose pln.prop_opt = {"solver": {"name": "scipy", "max_iter": 2, "display": False}} prob = NonLinearFluencePlanningProblem(pln) > prob.solve(ct, cst, stf, dij) test/optimization/test_fluence_optiprob.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.optimization.problems._optiprob:_optiprob.py:414 2 physical-dose objective(s) were converted to 'rbe_x_dose' for the biological model of the dose influence data. Set convert_dose_objectives=False to optimize physical dose instead. __________ test_objective_jacobian_has_one_row_per_objective[effect] ___________ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o... total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose', 'alpha_dose', 'sqrt_beta_dose'])) rbe_path = 'effect' @pytest.mark.parametrize("rbe_path", ["constant", "effect"]) def test_objective_jacobian_has_one_row_per_objective(small_proton_case, rbe_path): """Without the bypass, each objective gets its own gradient row, also across quantities.""" pln, ct, cst, stf, dij = small_proton_case if rbe_path == "constant": dij.bio_model = {"model": "constant_rbe", "rbe": 1.1} else: num_voxels = dij.dose_grid.num_voxels dij.alphax = np.full((num_voxels, 1), 0.1) dij.betax = np.full((num_voxels, 1), 0.05) alpha_dose = np.empty_like(dij.physical_dose) sqrt_beta_dose = np.empty_like(dij.physical_dose) for i, mat in enumerate(dij.physical_dose.flat): alpha_dose.flat[i] = 0.12 * mat sqrt_beta_dose.flat[i] = np.sqrt(0.05) * mat dij.alpha_dose = alpha_dose dij.sqrt_beta_dose = sqrt_beta_dose pln.prop_opt = {"solver": {"name": "scipy", "max_iter": 2, "display": False}} prob = NonLinearFluencePlanningProblem(pln) > prob.solve(ct, cst, stf, dij) test/optimization/test_fluence_optiprob.py:221: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- ERROR pyRadPlan.optimization.problems._optiprob:_optiprob.py:449 Inconsistency found in bio parameters between biologocal reference alpha and beta parameters in CST and Dij. WARNING pyRadPlan.optimization.problems._optiprob:_optiprob.py:414 2 physical-dose objective(s) were converted to 'rbe_x_dose' for the biological model of the dose influence data. Set convert_dose_objectives=False to optimize physical dose instead. ___ test_multi_scenario_gradient_backprojects_each_scenario_separately[None] ___ small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o...nstantRBEModel(rbe=1.1), num_of_scenarios=2, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose'])) backend = None @pytest.mark.parametrize("backend", [None, "jax.numpy"]) def test_multi_scenario_gradient_backprojects_each_scenario_separately(small_proton_case, backend): """ Gradient over several scenarios is sum_s w_s D_s^T g_s, not sum_s D_s^T (sum_s' g_s'). Non-robust objectives evaluate the nominal scenario only, so the objectives use the expected value over the set; equal weights keep the expectation a plain (scaled) sum over the scenarios, which is what this test checks the back-projection of. """ xp_new = None if backend is None else pytest.importorskip(backend) from pyRadPlan.scenarios import ( CTPhaseUncertainty, RangeUncertainty, ScenarioSet, SetupUncertainty, ) pln, ct, cst, stf, dij = small_proton_case rbe = 1.1 dij.bio_model = {"model": "constant_rbe", "rbe": rbe} base = dij.physical_dose.flat[0] for name in dij.quantities: if name != "physical_dose": setattr(dij, name, None) container = np.empty((2,), dtype=object) container[0] = base container[1] = 0.8 * base dij.physical_dose = container dij.scenarios = ScenarioSet.from_points( (CTPhaseUncertainty(), SetupUncertainty(), RangeUncertainty()), {"setup": [[0, 0, 0], [3, 0, 0]]}, weights=[0.5, 0.5], ) for voi in cst.vois: for obj in voi.objectives: obj.robustness = "expected_value" pln.prop_opt = {"solver": {"name": "scipy", "max_iter": 1, "display": False}} prob = NonLinearFluencePlanningProblem(pln) > prob.solve(ct, cst, stf, dij if xp_new is None else dij.to_namespace(xp_new)) test/optimization/test_fluence_optiprob.py:280: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.optimization.problems._optiprob:_optiprob.py:414 2 physical-dose objective(s) were converted to 'rbe_x_dose' for the biological model of the dose influence data. Set convert_dose_objectives=False to optimize physical dose instead. ______________ test_backend_arrays_and_vector_bounds[True-strict] ______________ backend = 'strict', force_cpu = True @pytest.mark.parametrize("backend", ["strict", "torch"]) @pytest.mark.parametrize("force_cpu", [False, True]) def test_backend_arrays_and_vector_bounds(backend, force_cpu): namespace = xp if backend == "strict" else pytest.importorskip("array_api_compat.torch") solver = get_solver("ipax") solver.allow_keyboard_cancel = False solver.force_cpu_inner_solve = force_cpu def objective(x): assert array_api_compat.array_namespace(x) is namespace return namespace.sum(x**2) solver.objective = objective solver.gradient = lambda x: 2 * x solver.bounds = ( namespace.asarray([1.0, 2.0], dtype=namespace.float64), namespace.asarray([3.0, 4.0], dtype=namespace.float64), ) x0 = namespace.asarray([2.0, 3.0], dtype=namespace.float64) > result, info = solver.solve(x0) ^^^^^^^^^^^^^^^^ test/optimization/test_ipax_solver.py:185: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_ipax_solver.py:222: in _solve_problem result = ipax.solve(problem, x0, options=options, callback=self._callback) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/ipax/solve.py:189: in solve problem_scaling = compute_scaling( /usr/lib/python3.14/site-packages/ipax/problem/scaling.py:221: in compute_scaling obj = _scalar_factor(xp, problem.gradient(x0), max_gradient) ^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/ipax/problem/derivatives.py:94: in gradient return self._gradient_fn(x) ^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/ipax/problem/function.py:152: in gradient return self._gradient(x) ^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_ipax_solver.py:197: in gradient xb = xp_utils.from_numpy(backend_xp, x, device=device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________________ test_problem_objective_fills_history[scipy] __________________ solver_name = 'scipy' small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.mark.parametrize("solver_name", SOLVERS) def test_problem_objective_fills_history(solver_name, small_proton_case): """Setting obj_history makes the problem's own objective record each evaluation.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": solver_name, "display": False, "max_iter": 25} prob = NonLinearFluencePlanningProblem(pln) prob.obj_history = [] > prob.solve(ct, cst, stf, dij) test/optimization/test_obj_history.py:25: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________________ test_history_stays_empty_when_disabled[scipy] _________________ solver_name = 'scipy' small_proton_case = (IonPlan(prop_stf={'gantry_angles': array([ 0, 180], dtype=uint8), 'couch_angles': array([0, 0], dtype=uint8), 'num_o..._model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose', 'let_dose'])) @pytest.mark.parametrize("solver_name", SOLVERS) def test_history_stays_empty_when_disabled(solver_name, small_proton_case): """A problem left with obj_history=None accumulates nothing while solving.""" pln, ct, cst, stf, dij = small_proton_case pln.prop_opt = {"solver": solver_name, "display": False, "max_iter": 25} prob = NonLinearFluencePlanningProblem(pln) > prob.solve(ct, cst, stf, dij) test/optimization/test_obj_history.py:38: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________________________ test_SquaredMimicking_cache __________________________ def test_SquaredMimicking_cache(): array = xp.full((2, 2, 2), 60.0) grid = Grid( resolution={"x": 3.0, "y": 3.0, "z": 3.0}, dimensions=(2, 2, 2), origin=[0.0, 0.0, 0.0] ) sq_mimic = SquaredMimicking(d_ref=(array, grid)) > sq_mimic.preprocess_image_reference_parameters(target_grid=grid, index_list=xp.arange(8)) test/optimization/test_objectives.py:223: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_objective.py:184: in preprocess_image_reference_parameters resampled_array = resampled_array[index_list] ^^^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:630: in __getitem__ self._validate_index(key) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Array([60., 60., 60., 60., 60., 60., 60., 60.], dtype=array_api_strict.float64) key = Array([0, 1, 2, 3, 4, 5, 6, 7], dtype=array_api_strict.int64) def _validate_index(self, key): """ Validate an index according to the array API. The array API specification only requires a subset of indices that are supported by NumPy. This function will reject any index that is allowed by NumPy but not required by the array API specification. We always raise ``IndexError`` on such indices (the spec does not require any specific behavior on them, but this makes the NumPy array API namespace a minimal implementation of the spec). See https://data-apis.org/array-api/latest/API_specification/indexing.html for the full list of required indexing behavior This function raises IndexError if the index ``key`` is invalid. It only raises ``IndexError`` on indices that are not already rejected by NumPy, as NumPy will already raise the appropriate error on such indices. ``shape`` may be None, in which case, only cases that are independent of the array shape are checked. The following cases are allowed by NumPy, but not specified by the array API specification: - Indices to not include an implicit ellipsis at the end. That is, every axis of an array must be explicitly indexed or an ellipsis included. This behaviour is sometimes referred to as flat indexing. - The start and stop of a slice may not be out of bounds. In particular, for a slice ``i:j:k`` on an axis of size ``n``, only the following are allowed: - ``i`` or ``j`` omitted (``None``). - ``-n <= i <= max(0, n - 1)``. - For ``k > 0`` or ``k`` omitted (``None``), ``-n <= j <= n``. - For ``k < 0``, ``-n - 1 <= j <= max(0, n - 1)``. - Boolean array indices are not allowed as part of a larger tuple index. - Integer array indices are not allowed (with the exception of 0-D arrays, which are treated the same as scalars). Additionally, it should be noted that indices that would return a scalar in NumPy will return a 0-D array. Array scalars are not allowed in the specification, only 0-D arrays. This is done in the ``Array._new`` constructor, not this function. """ _key = key if isinstance(key, tuple) else (key,) for i in _key: if isinstance(i, bool) or not ( isinstance(i, SupportsIndex) # i.e. ints or isinstance(i, slice) or i == Ellipsis or i is None or isinstance(i, Array) or isinstance(i, np.ndarray) ): raise IndexError( f"Single-axes index {i} has {type(i)=}, but only " "integers, slices (:), ellipsis (...), newaxis (None), " "zero-dimensional integer arrays and boolean arrays " "are specified in the Array API." ) nonexpanding_key = [] single_axes = [] n_ellipsis = 0 key_has_mask = False for i in _key: if i is not None: nonexpanding_key.append(i) if isinstance(i, np.ndarray): raise IndexError("Index arrays for array_api_strict must be array_api_strict arrays") if isinstance(i, Array): if i.dtype in _boolean_dtypes: key_has_mask = True single_axes.append(i) else: # i must not be an array here, to avoid elementwise equals if i == Ellipsis: n_ellipsis += 1 else: single_axes.append(i) n_single_axes = len(single_axes) if n_ellipsis > 1: return # handled by ndarray elif n_ellipsis == 0: # Note boolean masks must be the sole index, which we check for # later on. if not key_has_mask and n_single_axes < self.ndim: raise IndexError( f"{self.ndim=}, but the multi-axes index only specifies " f"{n_single_axes} dimensions. If this was intentional, " "add a trailing ellipsis (...) which expands into as many " "slices (:) as necessary - this is what np.ndarray arrays " "implicitly do, but such flat indexing behaviour is not " "specified in the Array API." ) if n_ellipsis == 0: indexed_shape = self.shape else: ellipsis_start = None for pos, i in enumerate(nonexpanding_key): if not (isinstance(i, Array) or isinstance(i, np.ndarray)): if i == Ellipsis: ellipsis_start = pos break assert ellipsis_start is not None # sanity check ellipsis_end = self.ndim - (n_single_axes - ellipsis_start) indexed_shape = ( self.shape[:ellipsis_start] + self.shape[ellipsis_end:] ) for i, side in zip(single_axes, indexed_shape): if isinstance(i, slice): if side == 0: f_range = "0 (or None)" else: f_range = f"between -{side} and {side - 1} (or None)" if i.start is not None: try: start = operator.index(i.start) except TypeError: pass # handled by ndarray else: if not (-side <= start <= side): raise IndexError( f"Slice {i} contains {start=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds starts are not specified in " "the Array API)" ) if i.stop is not None: try: stop = operator.index(i.stop) except TypeError: pass # handled by ndarray else: if not (-side <= stop <= side): raise IndexError( f"Slice {i} contains {stop=}, but should be " f"{f_range} for an axis of size {side} " "(out-of-bounds stops are not specified in " "the Array API)" ) elif isinstance(i, Array): if i.dtype in _boolean_dtypes: if len(_key) != 1: assert isinstance(key, tuple) # sanity check raise IndexError( f"Single-axes index {i} is a boolean array and " f"{len(key)=}, but masking is only specified in the " "Array API when the array is the sole index." ) if not get_array_api_strict_flags()['boolean_indexing']: raise RuntimeError("The boolean_indexing flag has been disabled for array-api-strict") elif i.dtype in _integer_dtypes and i.ndim != 0: > raise IndexError( f"Single-axes index {i} is a non-zero-dimensional " "integer array, but advanced integer indexing is not " "specified in the Array API." E IndexError: Single-axes index [0 1 2 3 4 5 6 7] is a non-zero-dimensional integer array, but advanced integer indexing is not specified in the Array API. /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:445: IndexError ________________________ test_MinDVH_compute_objective _________________________ def test_MinDVH_compute_objective(): min_dvh = MinDVH(d=30.0, v_min=95) dose = xp.ones(100) dose_2 = xp.ones(100) * 50 > assert min_dvh.compute_objective(dose) == 841 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_objectives.py:391: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_min_dvh.py:52: in compute_objective deviation = xp.where( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([False, False, False, False, False, False, False, False, False, False, False, False, False, False,...alse, False, False, False, False, False, False, False, False, False, False], dtype=array_api_strict.bool) x1 = 0 x2 = Array([-29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -... -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29.], dtype=array_api_strict.float64) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'int' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _________________________ test_MinDVH_compute_gradient _________________________ def test_MinDVH_compute_gradient(): min_dvh = MinDVH(d=30.0, v_min=95) dose = xp.ones(100) dose_2 = xp.ones(100) * 50 grad_expected = xp.ones(100) * -0.58 grad_expected2 = xp.zeros(100) > assert xp.all(min_dvh.compute_gradient(dose) == grad_expected) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_objectives.py:401: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_min_dvh.py:65: in compute_gradient deviation = xp.where( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([False, False, False, False, False, False, False, False, False, False, False, False, False, False,...alse, False, False, False, False, False, False, False, False, False, False], dtype=array_api_strict.bool) x1 = 0 x2 = Array([-29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -... -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29.], dtype=array_api_strict.float64) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'int' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ________________________ test_MaxDVH_compute_objective _________________________ def test_MaxDVH_compute_objective(): max_dvh = MaxDVH(d=30.0, v_max=50) dose = xp.ones(100) dose_2 = xp.ones(100) * 50 > assert max_dvh.compute_objective(dose) == 0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_objectives.py:420: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_max_dvh.py:52: in compute_objective deviation = xp.where( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = 0 x2 = Array([-29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -... -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29.], dtype=array_api_strict.float64) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'int' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _________________________ test_MaxDVH_compute_gradient _________________________ def test_MaxDVH_compute_gradient(): max_dvh = MaxDVH(d=30.0, v_max=50) dose = xp.ones(100) dose_2 = xp.ones(100) * 50 grad_expected = xp.zeros(100) grad_expected2 = xp.ones(100) * 0.4 > assert xp.all(max_dvh.compute_gradient(dose) == grad_expected) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_objectives.py:430: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_max_dvh.py:65: in compute_gradient deviation = xp.where( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = 0 x2 = Array([-29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -... -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29., -29.], dtype=array_api_strict.float64) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'int' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError __________ test_expected_value_is_the_weighted_sum_of_scenario_values __________ proton_case = ({'machine': 'Generic', 'numOfFractions': 30, 'propDoseCalc': {'doseGrid': {'resolution': {'x': 10, 'y': 10, 'z': 10}}...es=None, bio_model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose'])) def test_expected_value_is_the_weighted_sum_of_scenario_values(proton_case): pln, ct, cst, stf, dij = proton_case _set_robustness(cst, "expected_value") robust = _problem(proton_case, _dij_with(dij, SCALES, _scenario_set())) x = _fluence(robust) _set_robustness(cst, "none") expected = sum( w * _value(_problem(proton_case, _dij_with(dij, (scale,))), x) for scale, w in zip(SCALES, WEIGHTS) ) > assert _value(robust, x) == pytest.approx(expected, rel=1e-12) ^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:217: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/optimization/test_robust_fluence_optiprob.py:174: in _value return float(prob._objective_function(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:138: in _objective_function f = xp.sum(self._objective_functions(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:130: in _objective_functions value = xp.asarray(term.operator.evaluate(term.entries, values)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:34: in evaluate weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ________________ test_mixed_gradient_matches_finite_differences ________________ mixed_problem = def test_mixed_gradient_matches_finite_differences(mixed_problem): prob = mixed_problem rng = np.random.default_rng(1) for seed in range(3): x = _fluence(prob, seed) > gradient = xp_utils.to_numpy(prob._objective_gradient(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:269: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:267: in _objective_gradient jac = xp.sum(self._objective_jacobian(x), axis=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:237: in _objective_jacobian grads = term.operator.gradient(term.entries, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:42: in gradient weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ______________________ test_jacobian_has_one_row_per_term ______________________ mixed_problem = def test_jacobian_has_one_row_per_term(mixed_problem): prob = mixed_problem x = _fluence(prob) > gradient = xp_utils.to_numpy(prob._objective_gradient(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:284: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:267: in _objective_gradient jac = xp.sum(self._objective_jacobian(x), axis=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:237: in _objective_jacobian grads = term.operator.gradient(term.entries, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:42: in gradient weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________ test_shipped_operators_match_finite_differences[logsumexp] __________ worst_case_problem = @pytest.mark.parametrize("worst_case_problem", ["logsumexp", "pnorm"], indirect=True) def test_shipped_operators_match_finite_differences(worst_case_problem): prob = worst_case_problem names = [term.operator.name for term in prob._terms] assert names == [ "objective_worst_case", "composite_worst_case", "voxel_worst_case", "scenario_stack", "voxel_worst_case_inverted", "expected_quantity", ] assert len(prob._terms[1].items) == 2 rng = np.random.default_rng(2) for seed in range(2): x = _fluence(prob, seed) > gradient = xp_utils.to_numpy(prob._objective_gradient(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:386: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:267: in _objective_gradient jac = xp.sum(self._objective_jacobian(x), axis=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:237: in _objective_jacobian grads = term.operator.gradient(term.entries, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_base.py:197: in gradient grad = objective.compute_gradient(values[0], weights=self.weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:69: in compute_gradient _, weights, deviation = self._deviation(values, weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:43: in _deviation xp_utils.from_numpy( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ____________ test_shipped_operators_match_finite_differences[pnorm] ____________ worst_case_problem = @pytest.mark.parametrize("worst_case_problem", ["logsumexp", "pnorm"], indirect=True) def test_shipped_operators_match_finite_differences(worst_case_problem): prob = worst_case_problem names = [term.operator.name for term in prob._terms] assert names == [ "objective_worst_case", "composite_worst_case", "voxel_worst_case", "scenario_stack", "voxel_worst_case_inverted", "expected_quantity", ] assert len(prob._terms[1].items) == 2 rng = np.random.default_rng(2) for seed in range(2): x = _fluence(prob, seed) > gradient = xp_utils.to_numpy(prob._objective_gradient(x)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:386: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:267: in _objective_gradient jac = xp.sum(self._objective_jacobian(x), axis=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:237: in _objective_jacobian grads = term.operator.gradient(term.entries, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_base.py:197: in gradient grad = objective.compute_gradient(values[0], weights=self.weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:69: in compute_gradient _, weights, deviation = self._deviation(values, weights) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/objectives/_variance.py:43: in _deviation xp_utils.from_numpy( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _________________ test_robust_fluence_optimization_end_to_end __________________ proton_case = ({'machine': 'Generic', 'numOfFractions': 30, 'propDoseCalc': {'doseGrid': {'resolution': {'x': 10, 'y': 10, 'z': 10}}...es=None, bio_model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose'])) def test_robust_fluence_optimization_end_to_end(proton_case): from pyRadPlan.optimization import fluence_optimization from pyRadPlan.plan import validate_pln pln, ct, cst, stf, dij = proton_case cst.vois[0].objectives = [ SquaredDeviation(priority=100.0, d_ref=1.0, robustness="composite_worst_case") ] cst.vois[1].objectives = [ SquaredOverdosing(priority=10.0, d_max=0.3, robustness="expected_value") ] pln = validate_pln( { **dict(pln), "prop_opt": { "solver": {"name": "scipy", "max_iter": 3, "display": False}, "convert_dose_objectives": False, "max_approximation": "logsumexp", }, } ) robust_dij = _dij_with(dij, SCALES, _scenario_set()) > w = fluence_optimization(ct, cst, stf, robust_dij, pln) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:420: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/_fluence_optimization.py:95: in fluence_optimization x, result_info = planning_prob.solve(_ct, _cst, _stf, _dij) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_optiprob.py:604: in solve x, info = self._solve() ^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:303: in _solve result = self.solver.solve(x0) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.optimization.problems._factory:_factory.py:138 No PlanningProblem specified in Plan. Using first available problem nonlin_fluence. _ test_reinitializing_a_problem_with_other_scenarios_resets_the_gradient_caches _ proton_case = ({'machine': 'Generic', 'numOfFractions': 30, 'propDoseCalc': {'doseGrid': {'resolution': {'x': 10, 'y': 10, 'z': 10}}...es=None, bio_model=None, num_of_scenarios=1, total_num_of_bixels=12, num_of_voxels=2000, quantities=['physical_dose'])) def test_reinitializing_a_problem_with_other_scenarios_resets_the_gradient_caches(proton_case): pln, ct, cst, stf, dij = proton_case _set_robustness(cst, "none") prob = _problem(proton_case, _dij_with(dij, SCALES, _scenario_set())) x = _fluence(prob) prob._objective_gradient(x) _set_robustness(cst, "expected_value") prob._initialize() > gradient = prob._objective_gradient(x) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_robust_fluence_optiprob.py:465: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:267: in _objective_gradient jac = xp.sum(self._objective_jacobian(x), axis=0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/problems/_nonlin_fluence.py:237: in _objective_jacobian grads = term.operator.gradient(term.entries, values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_expected_value.py:42: in gradient weights = as_backend(self.weights, first) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/robustness/_utils.py:26: in as_backend xp_utils.from_numpy(xp, np.asarray(array), device=array_api_compat.device(like)), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________________________ test_simple_problem_scipy ___________________________ def test_simple_problem_scipy(): solver = get_solver("scipy") # Define the problem def objective(x): return xp.sum(x**2) def gradient(x): return 2 * x solver.objective = objective solver.gradient = gradient # Initial guess x0 = xp.asarray([1.0, 1.0], dtype=xp.float64) # Solve > result = solver.solve(x0) ^^^^^^^^^^^^^^^^ test/optimization/test_scipy_solver.py:40: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________________ test_scipy_emits_status_through_callback ___________________ def test_scipy_emits_status_through_callback(): solver = _quadratic_solver() reports = [] solver.status_callback = lambda message="", **data: reports.append(data) or True > solver.solve(xp.asarray([1.0, 1.0], dtype=xp.float64)) test/optimization/test_scipy_solver.py:57: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError __________ test_allow_keyboard_cancel_is_honoured_after_construction ___________ def test_allow_keyboard_cancel_is_honoured_after_construction(): """The flag is solver-level config, so a change after __init__ must reach the listener.""" solver = _quadratic_solver() assert solver._keyboard_listener.allow_keyboard_cancel is True # class default for scipy solver.allow_keyboard_cancel = False > solver.solve(xp.asarray([1.0, 1.0], dtype=xp.float64)) test/optimization/test_scipy_solver.py:71: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________ test_cancel_key_settings_are_honoured_after_construction ___________ def test_cancel_key_settings_are_honoured_after_construction(): """``cancel_key`` / ``allow_esc_cancel`` are solver-level config like the enable flag.""" solver = _quadratic_solver() solver.allow_keyboard_cancel = False # keep the listener thread out of the test solver.cancel_key = "x" solver.allow_esc_cancel = False > solver.solve(xp.asarray([1.0, 1.0], dtype=xp.float64)) test/optimization/test_scipy_solver.py:87: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError _____________________ test_scipy_status_callback_can_stop ______________________ def test_scipy_status_callback_can_stop(): solver = _quadratic_solver() calls = [] def _cb(message="", **data): calls.append(data) return False # request stop on the very first iteration solver.status_callback = _cb > x, _info = solver.solve(xp.asarray([5.0, 5.0], dtype=xp.float64)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/optimization/test_scipy_solver.py:102: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_base_solvers.py:118: in solve x, status = self._solve_problem(x0) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:192: in _solve_problem result = minimize( /usr/lib64/python3.14/site-packages/scipy/optimize/_minimize.py:784: in minimize res = _minimize_lbfgsb(fun, x0, args, jac, bounds, /usr/lib64/python3.14/site-packages/scipy/optimize/_lbfgsb_py.py:413: in _minimize_lbfgsb sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps, /usr/lib64/python3.14/site-packages/scipy/optimize/_optimize.py:310: in _prepare_scalar_function sf = ScalarFunction(fun, x0, args, grad, hess, /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:274: in __init__ self._update_fun() /usr/lib64/python3.14/site-packages/scipy/optimize/_differentiable_functions.py:353: in _update_fun fx = self._wrapped_fun(self.x) ^^^^^^^^^^^^^^^^^^^^^^^^^ /usr/lib64/python3.14/site-packages/scipy/_lib/_util.py:590: in __call__ fx = self.f(np.copy(x), *self.args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/optimization/solvers/_scipy_solver.py:185: in scipy_objective return xp_utils.to_numpy(self.objective(xp_utils.from_numpy(xp, x, device=device))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:691: in from_numpy device = _parse_device_to_dlpack(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:198: in _parse_device_to_dlpack if array_api_strict is not None and isinstance(device, array_api_strict.Device): ^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Device' def __getattr__(name): if name in ['linalg', 'fft']: if name in get_array_api_strict_flags()['enabled_extensions']: if name == 'linalg': from . import _linalg return _linalg elif name == 'fft': from . import _fft return _fft else: raise AttributeError(f"The {name!r} extension has been disabled for array_api_strict") > raise AttributeError(f"module {__name__!r} has no attribute {name!r}") E AttributeError: module 'array_api_strict' has no attribute 'Device'. Did you mean: 'divide'? /usr/lib/python3.14/site-packages/array_api_strict/__init__.py:344: AttributeError ___________________ test_rbe_x_dose_uses_voxel_param_column ____________________ two_scenario_dij = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=2, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_rbe_x_dose_uses_voxel_param_column(two_scenario_dij): dij = two_scenario_dij rbe = RBExDose(dij) assert list(rbe.scenarios) == [0, 1] > result = rbe(xp.arange(N_BIX, dtype=xp.float32)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/quantities/test_multi_scenario_quantities.py:305: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([ 9.238581 , 10.549352 , 11.840601 , 10.603649 , 11.9677725, 5.453381 , 12.007432 , 10.00074 , ... 7.3490834, 5.7154975, 10.329718 , 10.610678 , 13.411147 , 13.160281 ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _____________ test_alias_scenarios_share_dose_but_not_voxel_params _____________ alias_dij = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=2, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_alias_scenarios_share_dose_but_not_voxel_params(alias_dij): dij = alias_dij assert dij.voxel_param_column(0) == 0 assert dij.voxel_param_column(1) == 1 fluence = xp.arange(N_BIX, dtype=xp.float32) w = np.arange(N_BIX, dtype=np.float32) dose = Dose(dij, scenarios=[0, 1]) dose_result = dose(fluence) assert dose_result.flat[1] is dose_result.flat[0] rbe = RBExDose(dij, scenarios=[0, 1]) > result = rbe(fluence) ^^^^^^^^^^^^ test/quantities/test_multi_scenario_quantities.py:357: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([10.521754 , 7.7439156, 11.06683 , 10.885352 , 11.675577 , 15.50958 , 7.965419 , 9.880358 , 1... 10.343923 , 9.865118 , 6.355603 , 12.273873 , 12.153697 , 10.404238 ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ____________ test_derived_scenario_is_linear_combination[RBExDose] _____________ derived_dij = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=3, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) quantity_cls = @pytest.mark.parametrize("quantity_cls", [Dose, Effect, RBExDose]) def test_derived_scenario_is_linear_combination(derived_dij, quantity_cls): quantity = quantity_cls(derived_dij, scenarios=[0, 1, 2]) fluence = xp.arange(N_BIX, dtype=xp.float32) > result = quantity(fluence) ^^^^^^^^^^^^^^^^^ test/quantities/test_multi_scenario_quantities.py:385: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([ 7.3446918, 12.032897 , 8.084624 , 9.836628 , 6.6663136, 9.0304165, 7.7798643, 6.5125647, 1... 11.938342 , 11.604478 , 10.413534 , 8.711118 , 9.674815 , 12.916856 ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _____________ test_extend_scenarios_appends_containers_and_columns _____________ def test_extend_scenarios_appends_containers_and_columns(): rng = np.random.default_rng(3) first = _single_dij(rng, _phase_set([0]), alphas=(0.1,)) second = _single_dij(rng, _phase_set([1]), alphas=(0.5,)) merged = first.extend_scenarios(second) assert merged.num_of_scenarios == 2 assert merged.physical_dose.shape == (2,) assert merged.physical_dose.flat[0] is first.physical_dose.flat[0] assert merged.physical_dose.flat[1] is second.physical_dose.flat[0] assert [merged.voxel_param_column(i) for i in range(2)] == [0, 1] assert np.allclose(merged.alphax[:, merged.voxel_param_column(1)], 0.5) assert np.allclose(merged.scenarios.ct_phases(), [0, 1]) rbe = RBExDose(merged) > result = rbe(xp.arange(N_BIX, dtype=xp.float32)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/quantities/test_multi_scenario_quantities.py:469: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([11.840265 , 12.323431 , 8.011889 , 12.554123 , 8.772327 , 10.576969 , 7.7545686, 7.588301 , 1... 12.832273 , 9.58289 , 8.894093 , 12.701789 , 8.755135 , 10.094968 ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ________________ test_result_arrays_preserve_array_api_backend _________________ two_scenario_dij = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=2, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_result_arrays_preserve_array_api_backend(two_scenario_dij): dij = two_scenario_dij.to_namespace(xp, keep_sparse_compat=False) > result = dij.get_result_arrays_from_intensity(xp.arange(N_BIX, dtype=xp.float32)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/quantities/test_multi_scenario_quantities.py:553: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:1011: in get_result_arrays_from_intensity out = self._result_arrays(intensity, scenario_index) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:1155: in _result_arrays out["rbe_x_dose"] = lq_inverse_dose(out["effect"], alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([ 9.238581 , 10.549352 , 11.840601 , 10.603649 , 11.9677725, 5.453381 , 12.007432 , 10.00074 , ... 7.3490834, 5.7154975, 10.329718 , 10.610678 , 13.411147 , 13.160281 ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError __________________________ test_RBExDose_effect_dense __________________________ sample_dij_dense = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=1, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_RBExDose_effect_dense(sample_dij_dense): rbe_x_dose = RBExDose(sample_dij_dense) fluence = xp.arange(10, dtype=xp.float32) > ret_callable = rbe_x_dose(fluence) ^^^^^^^^^^^^^^^^^^^ test/quantities/test_rbe_x_dose_quantity.py:122: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92...., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92., 92.], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _________________________ test_RBExDose_effect_sparse __________________________ sample_dij_sparse = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=1, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_RBExDose_effect_sparse(sample_dij_sparse): rbe_x_dose = RBExDose(sample_dij_sparse) fluence = xp.arange(10, dtype=xp.float32) > ret_callable = rbe_x_dose(fluence) ^^^^^^^^^^^^^^^^^^^ test/quantities/test_rbe_x_dose_quantity.py:161: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([92., 2., 2., 2., 2., 2., 2., 2., 2., 92., 2., 92., 2., 2., 2., 2., 2., 2., 2., 2...., 2., 2., 2., 2., 92., 2., 2., 2., 92., 2., 2., 92., 2., 2.], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _______ test_lq_inverse_dose_supports_linear_limit_and_immutable_arrays ________ def test_lq_inverse_dose_supports_linear_limit_and_immutable_arrays(): effect = xp.asarray([2.0, 2.0, 2.0]) alpha_x = xp.asarray([1.0, 2.0, 0.0]) beta_x = xp.asarray([1.0, 0.0, 0.0]) > result = lq_inverse_dose(effect, alpha_x, beta_x) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/quantities/test_rbe_x_dose_quantity.py:323: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, False], dtype=array_api_strict.bool) x1 = Array([4., 4., 0.], dtype=array_api_strict.float64), x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ______ test_lq_inverse_dose_is_accurate_in_single_precision_at_low_effect ______ def test_lq_inverse_dose_is_accurate_in_single_precision_at_low_effect(): effect = np.asarray([1e-7, 1e-4, 0.5, 4.0]) alpha_x, beta_x = np.full(4, 0.1), np.full(4, 0.05) reference = (np.sqrt(alpha_x**2 + 4 * beta_x * effect) - alpha_x) / (2 * beta_x) > result = lq_inverse_dose( xp.asarray(effect, dtype=xp.float32), xp.asarray(alpha_x, dtype=xp.float32), xp.asarray(beta_x, dtype=xp.float32), ) test/quantities/test_rbe_x_dose_quantity.py:333: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True], dtype=array_api_strict.bool) x1 = Array([0.2000001 , 0.20009995, 0.43166247, 1. ], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ________ test_lq_inverse_dose_without_alpha_x_solves_the_quadratic_term ________ def test_lq_inverse_dose_without_alpha_x_solves_the_quadratic_term(): > result = lq_inverse_dose( xp.asarray([4.0, 0.0]), xp.asarray([0.0, 0.0]), xp.asarray([1.0, 1.0]) ) test/quantities/test_rbe_x_dose_quantity.py:343: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, False], dtype=array_api_strict.bool) x1 = Array([4., 0.], dtype=array_api_strict.float64), x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ___________ test_rbe_x_dose_effect_evaluates_in_the_matrix_precision ___________ sample_dij_sparse = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=1, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_rbe_x_dose_effect_evaluates_in_the_matrix_precision(sample_dij_sparse): """Double-precision reference parameters do not promote single-precision matrices.""" dij = sample_dij_sparse.model_copy() dij.alphax = np.full((125, 1), 0.1, dtype=np.float64) dij.betax = np.full((125, 1), 0.05, dtype=np.float64) quantity = RBExDose(dij) fluence = xp.ones(dij.total_num_of_bixels, dtype=xp.float32) > rbe_x_dose = quantity(fluence).flat[0] ^^^^^^^^^^^^^^^^^ test/quantities/test_rbe_x_dose_quantity.py:358: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:254: in __call__ return self.compute(fluence) ^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 ... , 4.7914815, 0.2 , 4.7914815, 4.7914815, 4.7914815, 4.7914815], dtype=array_api_strict.float32) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ___________ test_RBExDose_effect_gradient_matches_finite_differences ___________ sample_dij_float64_effect = Dij(dose_grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 3.0}, dimensions=(5, 5, 5), origin=array([0., 0., 0.]), direct...f_scenarios=1, total_num_of_bixels=10, num_of_voxels=125, quantities=['physical_dose', 'alpha_dose', 'sqrt_beta_dose']) def test_RBExDose_effect_gradient_matches_finite_differences(sample_dij_float64_effect): quantity = RBExDose(sample_dij_float64_effect) assert quantity.path == "effect" fluence = np.linspace(0.2, 1.4, 10) rng = np.random.default_rng(3) d_quantity = rng.random((1, 125)) # the effect path linearises around the current fluence, so evaluate it first > quantity.compute(xp.asarray(fluence, dtype=xp.float64)) test/quantities/test_rbe_x_dose_quantity.py:443: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:279: in compute self._compute_quantity_cache() ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:381: in _compute_quantity_cache self._q_cache.flat[scenario_index] = self._compute_quantity_single_scenario( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:154: in _compute_quantity_single_scenario return lq_inverse_dose(effect_slice, alphax, betax) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_rbe_x_dose.py:26: in lq_inverse_dose return xp.where(positive, 2 * effect / xp.where(positive, denominator, 1.0), 0.0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True,...True, True, True, True, True, True, True, True, True, True, True], dtype=array_api_strict.bool) x1 = Array([0.77934319, 0.6634629 , 0.68883752, 0.67811777, 0.75610558, 0.75023457, 0.77080284, 0.70231174, 0... 0.69353287, 0.71981528, 0.74937788, 0.66143098, 0.67821522, 0.73136959], dtype=array_api_strict.float64) x2 = 1.0 def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ______________________________ test_stfgen_to_stf ______________________________ tg119_raw = ({'cube': array([[[0.02670588, 0.02670588, 0.02670588, ..., 0.02670588, 0.02670588, 0.02670588], [0.0...0.1, 'betaX': 0.05, ...}, {'className': 'DoseObjectives.matRad_SquaredOverdosing', 'parameters': 30, 'penalty': 100}]]) def test_stfgen_to_stf(tg119_raw): ct_raw, cst_raw = tg119_raw ct = validate_ct(ct_raw) cst = validate_cst(cst_raw, ct=ct) pln = IonPlan(radiation_mode="protons", machine="Generic") stfgen = StfGeneratorIMPT(pln) stfgen.bixel_width = 5.0 stfgen.gantry_angles = [0.0] > stf_native = stfgen.generate(ct, cst) ^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf.py:165: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 3.1226115 , -3.1398883 ], [ 0.48825425, 0.51330423], [ 2.0174017 , -2.0138483 ]], [... 3.1398883 ], [ 0.48825425, 0.51330423], [-2.0174017 , 2.0138483 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ___________________________ test_from_and_to_matrad ____________________________ test_data_stf_n_beams_raw = {'__globals__': [], '__header__': b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Fri Nov 8 13:50:07 2024', '__...000, 10000], 'bixelWidth': [5, 5, 5, 5, 5], 'couchAngle': [0, 0, 0, 0, 0], 'gantryAngle': [0, 72, 144, 216, 288], ...}} def test_from_and_to_matrad(test_data_stf_n_beams_raw): stf_from_matRad = create_stf(test_data_stf_n_beams_raw) > stf_to_matrad = stf_from_matRad.to_matrad() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf.py:181: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_steeringinformation.py:120: in to_matrad export = super().to_matrad(context=context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/datamodel.py:191: in to_matrad return self_copy.model_dump(by_alias=True, context=context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = SteeringInformation(beams=[Beam(gantry_angle=0.0, couch_angle=0.0, bixel_width=5.0, radiation_mode='protons', machine=... 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]), num_of_rays=221, total_number_of_bixels=4140)]) def model_dump( self, *, mode: Literal['json', 'python'] | str = 'python', include: IncEx | None = None, exclude: IncEx | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, ) -> dict[str, Any]: """!!! abstract "Usage Documentation" [`model_dump`](../concepts/serialization.md#python-mode) Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. Args: mode: The mode in which `to_python` should run. If mode is 'json', the output will only contain JSON serializable types. If mode is 'python', the output may contain non-JSON-serializable Python objects. include: A set of fields to include in the output. exclude: A set of fields to exclude from the output. context: Additional context to pass to the serializer. by_alias: Whether to use the field's alias in the dictionary key if defined. exclude_unset: Whether to exclude fields that have not been explicitly set. exclude_defaults: Whether to exclude fields that are set to their default value. exclude_none: Whether to exclude fields that have a value of `None`. exclude_computed_fields: Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T]. warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError]. fallback: A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised. serialize_as_any: Whether to serialize fields with duck-typing serialization behavior. Returns: A dictionary representation of the model. """ > return self.__pydantic_serializer__.to_python( self, mode=mode, by_alias=by_alias, include=include, exclude=exclude, context=context, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, exclude_none=exclude_none, exclude_computed_fields=exclude_computed_fields, round_trip=round_trip, warnings=warnings, fallback=fallback, serialize_as_any=serialize_as_any, ) E pydantic_core._pydantic_core.PydanticSerializationError: Error calling function `custom_rays_serializer`: TypeError: Cannot interpret 'numpydantic.ndarray.NDArray[tuple[typing.Literal[3]], numpy.float64]' as a data type /usr/lib/python3.14/site-packages/pydantic/main.py:464: PydanticSerializationError ________ test_generate_with_round_tripped_plan_machine[protons-loaded] _________ sample_ct = CT(cube_hu= >, reso... 0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.])) sample_cst = StructureSet(vois=[VOI(name='testtarget', grid=Grid(resolution={'x': 2.0, 'y': 3.0, 'z': 4.0}, dimensions=(25, 15, 5),...0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.]))) radiation_mode = 'protons', default_mode = False @pytest.mark.parametrize("default_mode", [False, True], ids=["loaded", "default-mode"]) @pytest.mark.parametrize("radiation_mode", ["protons", "photons"]) def test_generate_with_round_tripped_plan_machine( sample_ct, sample_cst, radiation_mode, default_mode ): """Steering generation works with a loaded machine after a plan dump round trip.""" machine = load_from_name(radiation_mode, "Generic") if default_mode: data = machine.model_dump(exclude_unset=True) del data["radiation_mode"] machine = type(machine).model_validate(data) pln = create_pln(radiation_mode=radiation_mode, machine=machine, prop_stf={"bixel_width": 5}) pln = create_pln(pln.model_dump()) stf_gen = get_generator(pln) stf_gen.gantry_angles = [0.0] stf_gen.couch_angles = [0.0] > stf = stf_gen.generate(sample_ct, sample_cst) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:278: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 2.5 , -2.5 ], [ 0.49895, 0.5012 ], [ 1. , -1. ]], [[ 2.5 , -2.5 ... [[-2.5 , 2.5 ], [ 0.49895, 0.5012 ], [ -inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.stf.generators._factory:_factory.py:105 No generator specified in Plan. Using first available generator IMPT. _____ test_generate_with_round_tripped_plan_machine[protons-default-mode] ______ sample_ct = CT(cube_hu= >, reso... 0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.])) sample_cst = StructureSet(vois=[VOI(name='testtarget', grid=Grid(resolution={'x': 2.0, 'y': 3.0, 'z': 4.0}, dimensions=(25, 15, 5),...0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.]))) radiation_mode = 'protons', default_mode = True @pytest.mark.parametrize("default_mode", [False, True], ids=["loaded", "default-mode"]) @pytest.mark.parametrize("radiation_mode", ["protons", "photons"]) def test_generate_with_round_tripped_plan_machine( sample_ct, sample_cst, radiation_mode, default_mode ): """Steering generation works with a loaded machine after a plan dump round trip.""" machine = load_from_name(radiation_mode, "Generic") if default_mode: data = machine.model_dump(exclude_unset=True) del data["radiation_mode"] machine = type(machine).model_validate(data) pln = create_pln(radiation_mode=radiation_mode, machine=machine, prop_stf={"bixel_width": 5}) pln = create_pln(pln.model_dump()) stf_gen = get_generator(pln) stf_gen.gantry_angles = [0.0] stf_gen.couch_angles = [0.0] > stf = stf_gen.generate(sample_ct, sample_cst) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:278: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 2.5 , -2.5 ], [ 0.49895, 0.5012 ], [ 1. , -1. ]], [[ 2.5 , -2.5 ... [[-2.5 , 2.5 ], [ 0.49895, 0.5012 ], [ -inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ------------------------------ Captured log call ------------------------------- WARNING pyRadPlan.stf.generators._factory:_factory.py:105 No generator specified in Plan. Using first available generator IMPT. __________________________________ test_impt ___________________________________ sample_ct = CT(cube_hu= >, reso... 0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.])) sample_cst = StructureSet(vois=[VOI(name='testtarget', grid=Grid(resolution={'x': 2.0, 'y': 3.0, 'z': 4.0}, dimensions=(25, 15, 5),...0., 3., 6., 9., 12., 15., 18., 21., 24., 27., 30., 33., 36., 39., 42.]), z=array([ 0., 4., 8., 12., 16.]))) sample_proton_pln = IonPlan(prop_stf={'bixel_width': 2.0}, prop_opt={}, prop_dose_calc={}, prop_seq={}, num_of_fractions=30, dose_conventi...ies=[1.0]), wc_sigma=1.0, distribution='independent_gaussian'), bio_model=ConstantRBEModel(), radiation_mode='protons') def test_impt(sample_ct, sample_cst, sample_proton_pln): stf_gen = StfGeneratorIMPT(sample_proton_pln) stf_gen.gantry_angles = [0.0, 270.0] stf_gen.couch_angles = [0.0, 90.0] > stf = stf_gen.generate(sample_ct, sample_cst) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:291: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 1.25 , -1.25 ], [ 0.49895 , 0.5012 ], [ 0.625 , -0.625 ]], [[ 1.25... , 1.25 ], [ 0.49895 , 0.5012 ], [-1.25 , 1.25 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- _______________________________ test_impt_tg119 ________________________________ tg119 = {'cst': StructureSet(vois=[OAR(name='Core', grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 2.5}, dimensions=(167, 167,...130. , 132.5, 135. , 137.5, 140. , 142.5, 145. , 147.5, 150. , 152.5, 155. , 157.5, 160. ]))} sample_proton_pln = IonPlan(prop_stf={'bixel_width': 2.0}, prop_opt={}, prop_dose_calc={}, prop_seq={}, num_of_fractions=30, dose_conventi...ies=[1.0]), wc_sigma=1.0, distribution='independent_gaussian'), bio_model=ConstantRBEModel(), radiation_mode='protons') def test_impt_tg119(tg119, sample_proton_pln): ct = tg119["ct"] cst = tg119["cst"] stf_gen = StfGeneratorIMPT(sample_proton_pln) stf_gen.bixel_width = 5.0 > stf = stf_gen.generate(ct, cst) ^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:317: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 3.1226115 , -3.1398883 ], [ 0.48825425, 0.51330423], [ 2.0174017 , -2.0138483 ]], [... 3.1398883 ], [ 0.48825425, 0.51330423], [-2.0174017 , 2.0138483 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- ___________ test_impt_longitudinal_spot_spacing_thins_energy_layers ____________ tg119 = {'cst': StructureSet(vois=[OAR(name='Core', grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 2.5}, dimensions=(167, 167,...130. , 132.5, 135. , 137.5, 140. , 142.5, 145. , 147.5, 150. , 152.5, 155. , 157.5, 160. ]))} sample_proton_pln = IonPlan(prop_stf={'bixel_width': 2.0}, prop_opt={}, prop_dose_calc={}, prop_seq={}, num_of_fractions=30, dose_conventi...ies=[1.0]), wc_sigma=1.0, distribution='independent_gaussian'), bio_model=ConstantRBEModel(), radiation_mode='protons') def test_impt_longitudinal_spot_spacing_thins_energy_layers(tg119, sample_proton_pln): """Energy layers must be spaced by at least longitudinal_spot_spacing in peak position.""" ct, cst = tg119["ct"], tg119["cst"] def spots_and_layers(spacing): stf_gen = StfGeneratorIMPT(sample_proton_pln) stf_gen.bixel_width = 5.0 stf_gen.longitudinal_spot_spacing = spacing beams = stf_gen.generate(ct, cst) spots = sum(len(ray.beamlets) for beam in beams for ray in beam["rays"]) layers = np.unique( np.concatenate([ray.energies for beam in beams for ray in beam["rays"]]) ) return spots, layers, stf_gen > dense_spots, dense_layers, gen = spots_and_layers(0.0) ^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:361: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test/stf/test_stf_gen.py:354: in spots_and_layers beams = stf_gen.generate(ct, cst) ^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 3.1226115 , -3.1398883 ], [ 0.48825425, 0.51330423], [ 2.0174017 , -2.0138483 ]], [... 3.1398883 ], [ 0.48825425, 0.51330423], [-2.0174017 , 2.0138483 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- _________________ test_impt_zero_spot_spacing_keeps_all_layers _________________ tg119 = {'cst': StructureSet(vois=[OAR(name='Core', grid=Grid(resolution={'x': 3.0, 'y': 3.0, 'z': 2.5}, dimensions=(167, 167,...130. , 132.5, 135. , 137.5, 140. , 142.5, 145. , 147.5, 150. , 152.5, 155. , 157.5, 160. ]))} sample_proton_pln = IonPlan(prop_stf={'bixel_width': 2.0}, prop_opt={}, prop_dose_calc={}, prop_seq={}, num_of_fractions=30, dose_conventi...ies=[1.0]), wc_sigma=1.0, distribution='independent_gaussian'), bio_model=ConstantRBEModel(), radiation_mode='protons') def test_impt_zero_spot_spacing_keeps_all_layers(tg119, sample_proton_pln): """A spacing of zero disables the thinning entirely.""" ct, cst = tg119["ct"], tg119["cst"] counts = [] for spacing in (0.0, 1e-9): stf_gen = StfGeneratorIMPT(sample_proton_pln) stf_gen.bixel_width = 5.0 stf_gen.longitudinal_spot_spacing = spacing > beams = stf_gen.generate(ct, cst) ^^^^^^^^^^^^^^^^^^^^^^^^^ test/stf/test_stf_gen.py:387: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_base.py:86: in generate stf = self._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:228: in _generate_source_geometry stf = super()._generate_source_geometry() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_externalbeam.py:237: in _generate_source_geometry beam["rays"] = self._create_rays(beam) ^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/generators/_ions.py:293: in _create_rays _, lengths, rhos, _, _ = rt.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ 3.1226115 , -3.1398883 ], [ 0.48825425, 0.51330423], [ 2.0174017 , -2.0138483 ]], [... 3.1398883 ], [ 0.48825425, 0.51330423], [-2.0174017 , 2.0138483 ]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ----------------------------- Captured stderr call ----------------------------- _______________________ test_raytracer_trace_single_ray ________________________ sample_cube = > def test_raytracer_trace_single_ray(sample_cube): raytracer = RayTracerSiddon(sample_cube) isocenter = sample_cube.TransformIndexToPhysicalPoint([3, 2, 1]) source_points = np.array([0, -5, 0]).astype(float) target_points = np.array([0, 5, 0]).astype(float) > alpha, l, rho, d12, ix = raytracer.trace_ray(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/test_raytracersiddon.py:51: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:57: in trace_ray alphas, lengths, rho, d12, ix = self.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[-inf, inf], [0.25, 0.75], [-inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ______________________ test_raytracer_trace_multiple_rays ______________________ sample_cube = > def test_raytracer_trace_multiple_rays(sample_cube): raytracer = RayTracerSiddon(sample_cube) isocenter = sample_cube.TransformIndexToPhysicalPoint([3, 2, 1]) source_points = np.array([[0, -5, 0], [0, -5, 0]]).astype(float) target_points = np.array([[0, 5, 0], [2, 5, 0]]).astype(float) > alpha, l, rho, d12, ix = raytracer.trace_rays(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/test_raytracersiddon.py:72: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ -inf, inf], [ 0.25, 0.75], [ -inf, inf]], [[-1.75, 1.75], [ 0.25, 0.75], [ -inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _____________________ test_raytracer_trace_multiple_cubes ______________________ sample_cube = > def test_raytracer_trace_multiple_cubes(sample_cube): raytracer = RayTracerSiddon([sample_cube, sample_cube]) isocenter = sample_cube.TransformIndexToPhysicalPoint([3, 2, 1]) source_points = np.array([[0, -5, 0], [0, -5, 0]]).astype(float) target_points = np.array([[0, 5, 0], [2, 5, 0]]).astype(float) > alpha, l, rho, d12, ix = raytracer.trace_rays(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/test_raytracersiddon.py:109: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ -inf, inf], [ 0.25, 0.75], [ -inf, inf]], [[-1.75, 1.75], [ 0.25, 0.75], [ -inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError _______________________ test_raytracer_ray_does_not_hit ________________________ sample_cube = > def test_raytracer_ray_does_not_hit(sample_cube): raytracer = RayTracerSiddon(sample_cube) isocenter = sample_cube.TransformIndexToPhysicalPoint([3, 2, 1]) source_point = np.array([100, -5, 100]).astype(float) target_point = np.array([100, 5, 100]).astype(float) > alpha, l, rho, d12, ix = raytracer.trace_ray(isocenter, source_point, target_point) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/test_raytracersiddon.py:130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:57: in trace_ray alphas, lengths, rho, d12, ix = self.trace_rays( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[-inf, -inf], [0.25, 0.75], [-inf, -inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError ______ test_readonly_sitk_buffer_is_copied_for_backend[array_api_strict] _______ sample_cube = > monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff8c80f0e0> backend = 'array_api_strict' @pytest.mark.parametrize("backend", ["array_api_strict", "torch"]) def test_readonly_sitk_buffer_is_copied_for_backend(sample_cube, monkeypatch, backend): if backend == "torch": pytest.importorskip("torch") monkeypatch.setattr(settings.xp, "prefer_gpu", False) monkeypatch.setattr(settings.xp, "preferred_cpu_array_backend", backend) cube_before = sitk.GetArrayViewFromImage(sample_cube).copy() raytracer = RayTracerSiddon(sample_cube) isocenter = sample_cube.TransformIndexToPhysicalPoint([3, 2, 1]) with warnings.catch_warnings(record=True) as caught: > _, _, rho, _, ix = raytracer.trace_rays( isocenter, np.array([[0.0, -5.0, 0.0]]), np.array([[0.0, 5.0, 0.0], [2.0, 5.0, 0.0]]), ) test/test_raytracersiddon.py:170: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:88: in trace_rays alphas, lengths, rho, d12, ix = self._trace_rays_core( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[ -inf, inf], [ 0.25, 0.75], [ -inf, inf]], [[-1.75, 1.75], [ 0.25, 0.75], [ -inf, inf]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError __________ test_trace_depth_arrays_stay_on_backend[array_api_strict] ___________ monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0xffff7af4fc40> backend = 'array_api_strict' @pytest.mark.parametrize("backend", ["numpy", "cupy", "array_api_strict"]) def test_trace_depth_arrays_stay_on_backend(monkeypatch, backend): """The array interface avoids host conversion while the image wrapper preserves metadata.""" module = pytest.importorskip(backend) if backend == "cupy" and not module.cuda.is_available(): pytest.skip("CUDA unavailable") monkeypatch.setattr(settings.xp, "prefer_gpu", backend == "cupy") monkeypatch.setattr( settings.xp, "preferred_cpu_array_backend", backend if backend != "cupy" else "numpy" ) monkeypatch.setattr(settings.xp, "preferred_gpu_array_backend", "cupy") cube = sitk.GetImageFromArray(np.ones((5, 6, 7), dtype=np.float32)) cube.SetSpacing((1.3, 1.7, 2.1)) cube.SetOrigin((-3.0, -4.0, -5.0)) tracer = RayTracerSiddon(cube) beam = Beam( gantry_angle=30.0, couch_angle=20.0, iso_center=np.zeros(3), SAD=10000.0, rays=[Ray(ray_pos_bev=np.zeros(3), ray_pos=np.zeros(3), beamlets=[Beamlet(energy=100.0)])], ) > expected = tracer.trace_cubes(beam)[0] ^^^^^^^^^^^^^^^^^^^^^^^^ test/test_raytracersiddon.py:274: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:183: in trace_cubes return self._depth_arrays_to_images(self.trace_cubes_array(beam, patient_coords)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_base.py:290: in trace_cubes_array lengths, rho, ix = self._trace_rays_device( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:116: in _trace_rays_device _, lengths, rho, _, ix = self._trace_rays_core(isocenter, source_points, target_points) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:161: in _trace_rays_core alphas = self._compute_all_alphas() ^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:258: in _compute_all_alphas alpha_limits = self._compute_alpha_limits() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:402: in _compute_alpha_limits alpha_axis_min = xp.min(xp.where(alpha_nans, -xp.inf, alpha_planes), axis=-1) # (N, 3) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ condition = Array([[[False, False], [False, False], [False, False]], [[False, False], [False, Fals...False, False]], [[False, False], [False, False], [False, False]]], dtype=array_api_strict.bool) x1 = -inf x2 = Array([[[0.9954338 , 0.9935073 ], [0.99896014, 1.0001373 ], [1.0225602 , 1.028861 ]], [[0.995...39 , 1.0026199 ], [0.99832463, 0.999501 ], [0.9701518 , 0.97612965]]], dtype=array_api_strict.float32) def where(condition: Array, x1: Array, x2: Array, /) -> Array: """ Array API compatible wrapper for :py:func:`np.where `. See its docstring for more information. """ # Call result type here just to raise on disallowed type combinations > _result_type(x1.dtype, x2.dtype) ^^^^^^^^ E AttributeError: 'float' object has no attribute 'dtype' /usr/lib/python3.14/site-packages/array_api_strict/_searching_functions.py:78: AttributeError =============================== warnings summary =============================== ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] origin: Union[NDArray[Shape["3"], np.float64], NDArray[Shape["4"], np.float64]] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:36: DeprecationWarning: String shape expressions like '4' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] origin: Union[NDArray[Shape["3"], np.float64], NDArray[Shape["4"], np.float64]] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39: DeprecationWarning: String shape expressions like '3,3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] direction: Union[NDArray[Shape["3,3"], np.float64], NDArray[Shape["4,4"], np.float64]] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_grids.py:39: DeprecationWarning: String shape expressions like '4,4' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] direction: Union[NDArray[Shape["3,3"], np.float64], NDArray[Shape["4,4"], np.float64]] = Field( ../../../../../usr/lib/python3.14/site-packages/array_api_strict/_flags.py:344 /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:344: UserWarning: The 2023.12 version of the array API specification is still preliminary. Some functions are not yet implemented, and it has not been fully tested. set_array_api_strict_flags(**kwargs) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_base.py:44 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_base.py:44 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_base.py:44: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] tissue_properties: Optional[NDArray[Shape["1-*"], TissueProperties]] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_external_beam.py:26 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_external_beam.py:26 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_external_beam.py:26: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] energies: NDArray[Shape["1-*"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:37 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:37 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:37: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] kernel_betas: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:40 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:40 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:40: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] kernel_ssds: NDArray[Shape["1-*"], np.float64] = Field(description="Kernel SSD points") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:41 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:41 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:41: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] kernel_pos: NDArray[Shape["1-*"], np.float64] = Field(description="Kernel position") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:42 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:42 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:42: DeprecationWarning: String shape expressions like '1-*,1-*, 1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] kernel_data: NDArray[Shape["1-*,1-*, 1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:46 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:46 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/photons/_svd_kernel.py:46: DeprecationWarning: String shape expressions like '1-*,2' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] primary_fluence: NDArray[Shape["1-*,2"], np.float64] = Field(description="Primary fluence") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:16 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:16 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:16: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] dist: NDArray[Shape["1-*"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:17 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:17 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_focus.py:17: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma: NDArray[Shape["1-*"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:58 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:58 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:58: DeprecationWarning: String shape expressions like '1-*, 1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] fluence_spectrum: NDArray[Shape["1-*, 1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:61 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:61 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:61: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] energy: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:64 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:64 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_fragment_spectrum.py:64: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] fluenceZ: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:16 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:16 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:16: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] cut_off: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:19 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:19 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_cutoff.py:19: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] depths: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:203 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:203: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] cls, v: Union[NDArray[Shape["1-*"], np.float64], None], info: ValidationInfo ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:204 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:204: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] ) -> Union[NDArray[Shape["1-*"], np.float64], None]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:258 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:258: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] @computed_field(return_type=NDArray[Shape["1-*"], np.float64], alias="alphaBetaRatio") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:28 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:28 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:28: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] depths: NDArray[Shape["1-*"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:31 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:31 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:31: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] idd: NDArray[Shape["1-*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:34 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:34 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:34: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:35 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:35 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:35: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma_1: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:36 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:36 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:36: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma_2: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:37 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:37 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:37: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma_x: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:38 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:38 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:38: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma_y: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:39 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:39 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:39: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] weight: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:40 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:40 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:40: DeprecationWarning: String shape expressions like '1-*,1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] sigma_multi: Optional[NDArray[Shape["1-*,1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] Union[NDArray[Shape["1-*"], np.float64], NDArray[Shape["1-*,1-*"], np.float64]] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:42: DeprecationWarning: String shape expressions like '1-*,1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] Union[NDArray[Shape["1-*"], np.float64], NDArray[Shape["1-*,1-*"], np.float64]] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:44 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:44 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:44: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] let: Optional[NDArray[Shape["1-*"], np.float64]] = Field(alias="LET", default=None) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:45 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:45 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:45: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] zs: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:46 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:46 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:46: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] alpha_x: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:47 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:47 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:47: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] beta_x: Optional[NDArray[Shape["1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:48 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:48 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:48: DeprecationWarning: String shape expressions like '1-*,1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] alpha: Optional[NDArray[Shape["1-*,1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:49 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:49 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/kernel/_base.py:49: DeprecationWarning: String shape expressions like '1-*,1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] beta: Optional[NDArray[Shape["1-*,1-*"], np.float64]] = None ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:73 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:73 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:73: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] energy: NDArray[Shape["*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:76 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:76 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_beam_energy.py:76: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] weight: NDArray[Shape["*"], np.float64] = Field(description="Weight of each energy bin") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_base.py:43 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_base.py:43 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_base.py:43: DeprecationWarning: String shape expressions like '2,*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] lut_spot_size: NDArray[Shape["2,*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_ions.py:44 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_ions.py:44 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/particles/_ions.py:44: DeprecationWarning: String shape expressions like '1-*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] peak_positions: NDArray[Shape["1-*"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:69 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:69: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] ) -> NDArray[Shape["3"], np.float64]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:57 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:57 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:57: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] ray_pos_bev: NDArray[Shape["3"], np.float64] = Field(alias="rayPos_bev") ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:58 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:58 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:58: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] ray_pos: NDArray[Shape["3"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:60 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:60 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:60: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] target_point: Optional[NDArray[Shape["3"], np.float64]] = Field(default=None) ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:61 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:61 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_ray.py:61: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] target_point_bev: Optional[NDArray[Shape["3"], np.float64]] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:79 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:79 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:79: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] iso_center: NDArray[Shape["3"], np.float64] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:84 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:84 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:84: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] source_point_bev: NDArray[Shape["3"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:87 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:87 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/stf/_beam.py:87: DeprecationWarning: String shape expressions like '3' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] source_point: NDArray[Shape["3"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:39 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:39: DeprecationWarning: String shape expressions like '*, ...' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] InfluenceMatrixContainer = NDArray[Shape["*, ..."], object] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:39 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dij/_dij.py:39: DeprecationWarning: Treating '...' in a string as meaning any number of dimensions of any size is now written as *Repeat. The old behavior is deprecated in 2.0 and will be removed in 3.0. InfluenceMatrixContainer = NDArray[Shape["*, ..."], object] ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:74 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:74 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:74: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] diff_volume: NDArray[Shape["*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:81 ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:81 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:81: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] bin_edges: NDArray[Shape["*"], np.float64] = Field( ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:128 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:128: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] def cum_volume(self) -> NDArray[Shape["*"], np.float64]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:140 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:140: DeprecationWarning: String shape expressions like '2,*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] def cumulative(self) -> NDArray[Shape["2,*"], np.float64]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:161 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:161: DeprecationWarning: String shape expressions like '2,*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] def differential(self) -> NDArray[Shape["2,*"], np.float64]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:197 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:197: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] def bins(self) -> NDArray[Shape["*"], np.float64]: ../BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:223 /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/analysis/_dvh.py:223: DeprecationWarning: String shape expressions like '*' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] def bin_centers(self) -> NDArray[Shape["*"], np.float64]: test/scenarios/test_scenario_models.py:7 test/scenarios/test_scenario_models.py:7 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:7: DeprecationWarning: NominalScenario is deprecated and will be removed after one release; use NominalScenarioModel. from pyRadPlan.scenarios import ( test/scenarios/test_scenario_set.py:351 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_set.py:351: SyntaxWarning: "\[" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\["? A raw string is also an option. with pytest.raises(ValueError, match="Derived scenarios \[3\]"): test/scenarios/test_scenario_set.py:353 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_set.py:353: SyntaxWarning: "\[" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\["? A raw string is also an option. with pytest.raises(ValueError, match="Derived scenarios \[2, 3\]"): test/test_plan.py:12 test/test_plan.py:12 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_plan.py:12: DeprecationWarning: NominalScenario is deprecated and will be removed after one release; use NominalScenarioModel. from pyRadPlan.scenarios import NominalScenario test/test_scenarios.py:10 test/test_scenarios.py:10 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:10: DeprecationWarning: NominalScenario is deprecated and will be removed after one release; use NominalScenarioModel. from pyRadPlan.scenarios import NominalScenario, NominalScenarioModel, ScenarioModel test/biology/models/test_custom_model_extension.py: 1 warning test/dose/test_base_pencilbeam.py: 5 warnings test/dose/test_bio_tissue_check.py: 26 warnings test/dose/test_default_bio_models.py: 17 warnings test/dose/test_dose_engine_base.py: 10 warnings test/dose/test_engine_reuse.py: 6 warnings test/dose/test_factory.py: 2 warnings test/dose/test_fred.py: 16 warnings test/dose/test_fred_bio.py: 17 warnings test/dose/test_hongpb.py: 29 warnings test/dose/test_hongpb_bio.py: 21 warnings test/dose/test_particle_interpolators.py: 2 warnings test/dose/test_particle_lateral_cutoff.py: 1 warning test/dose/test_pb_geodist.py: 4 warnings test/dose/test_scenarios_pencilbeam.py: 44 warnings test/dose/test_svdpb.py: 3 warnings test/dose/test_svdpb_bio.py: 3 warnings test/dose/test_topas.py: 15 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base.py:229: UserWarning: Requested GPU device is not available on array_api_strict. Falling back to CPU. self.device = choose_device() test/biology/models/test_custom_model_extension.py: 1 warning test/dose/test_bio_tissue_check.py: 19 warnings test/dose/test_default_bio_models.py: 14 warnings test/dose/test_engine_reuse.py: 2 warnings test/dose/test_fred_bio.py: 1 warning test/dose/test_hongpb.py: 27 warnings test/dose/test_hongpb_bio.py: 14 warnings test/dose/test_particle_interpolators.py: 2 warnings test/dose/test_particle_lateral_cutoff.py: 1 warning test/dose/test_scenarios_pencilbeam.py: 20 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_base_pencilbeam.py:392: UserWarning: stf does not record use_given_eq_density_cube and ignore_outside_densities (e.g. because it was imported), so its energy selection cannot be verified against the dose engine (use_given_eq_density_cube=False, ignore_outside_densities=False). Make sure the stf was generated with the same settings. warnings.warn( test/biology/models/test_custom_model_extension.py: 1 warning test/dose/test_bio_tissue_check.py: 19 warnings test/dose/test_default_bio_models.py: 14 warnings test/dose/test_engine_reuse.py: 6 warnings test/dose/test_fred_bio.py: 1 warning test/dose/test_hongpb.py: 27 warnings test/dose/test_hongpb_bio.py: 14 warnings test/dose/test_particle_interpolators.py: 2 warnings test/dose/test_particle_lateral_cutoff.py: 1 warning test/dose/test_scenarios_pencilbeam.py: 41 warnings test/dose/test_svdpb.py: 3 warnings test/dose/test_svdpb_bio.py: 3 warnings test/stf/test_stf.py: 1 warning test/stf/test_stf_gen.py: 6 warnings test/test_raytracersiddon.py: 6 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:29: UserWarning: Requested GPU device is not available on array_api_strict. Falling back to CPU. self.device = xp_utils.choose_device() test/biology/models/test_custom_model_extension.py: 1 warning test/dose/test_bio_tissue_check.py: 19 warnings test/dose/test_default_bio_models.py: 14 warnings test/dose/test_engine_reuse.py: 6 warnings test/dose/test_hongpb.py: 27 warnings test/dose/test_hongpb_bio.py: 12 warnings test/dose/test_particle_interpolators.py: 2 warnings test/dose/test_particle_lateral_cutoff.py: 1 warning test/dose/test_scenarios_pencilbeam.py: 42 warnings test/dose/test_svdpb.py: 3 warnings test/dose/test_svdpb_bio.py: 3 warnings test/stf/test_stf.py: 1 warning test/stf/test_stf_gen.py: 6 warnings test/test_raytracersiddon.py: 4 warnings /usr/lib/python3.14/site-packages/array_api_strict/_array_object.py:862: RuntimeWarning: divide by zero encountered in divide res = self._array.__truediv__(other._array) test/core/test_resample.py::test_resample_numpy_array /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/core/test_resample.py:36: DeprecationWarning: resample_numpy_array is deprecated; use resample_array instead. resampled_array = resample_numpy_array( test/core/test_resample.py::test_resample_numpy_array_with_target_image /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/core/test_resample.py:44: DeprecationWarning: resample_numpy_array is deprecated; use resample_array instead. resampled_array = resample_numpy_array(sample_array, sample_image, target_image=sample_image) test/core/xp_utils/test_initialization.py::test_choose_device_defaults /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/core/xp_utils/test_initialization.py:111: UserWarning: Requested GPU device is not available on array_api_strict. Falling back to CPU. dev = choose_device() test/core/xp_utils/test_initialization.py::test_choose_device_numpy /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/core/xp_utils/test_initialization.py:192: UserWarning: Requested GPU device is not available on array_api_compat.numpy. Falling back to CPU. dev = choose_device(xp) test/cst/test_cst_4d_ct.py::test_4d_structures_resample_phase_by_phase /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/cst/_voi.py:1125: UserWarning: Resampling created an empty structure warnings.warn("Resampling created an empty structure") test/dose/test_dose_engine_base.py::test_DoseEngineBase_init test/dose/test_dose_engine_base.py::test_assign_properties_from_pln test/dose/test_dose_engine_base.py::test_calc_dose_forward test/dose/test_dose_engine_base.py::test_calc_dose_influence test/dose/test_dose_engine_base.py::test_init_dose_calc test/dose/test_dose_engine_base.py::test_init_dose_calc_uses_plan_machine test/dose/test_dose_engine_base.py::test_plan_machine_dict_is_validated_once test/dose/test_dose_engine_base.py::test_init_dose_calc_rejects_plan_machine_not_matching_stf /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "dosimetric_lateral_cutoff" not found in DummyDoseEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_dose_engine_base.py::test_DoseEngineBase_init test/dose/test_dose_engine_base.py::test_assign_properties_from_pln test/dose/test_dose_engine_base.py::test_calc_dose_forward test/dose/test_dose_engine_base.py::test_calc_dose_influence test/dose/test_dose_engine_base.py::test_init_dose_calc test/dose/test_dose_engine_base.py::test_init_dose_calc_uses_plan_machine test/dose/test_dose_engine_base.py::test_plan_machine_dict_is_validated_once test/dose/test_dose_engine_base.py::test_init_dose_calc_rejects_plan_machine_not_matching_stf /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "lateral_model" not found in DummyDoseEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_dose_engine_base.py: 1 warning test/dose/test_engine_reuse.py: 4 warnings test/dose/test_scenarios_pencilbeam.py: 25 warnings test/dose/test_svdpb.py: 3 warnings test/dose/test_svdpb_bio.py: 3 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "lateral_model" not found in PhotonPencilBeamSVDEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_factory.py::test_get_engine_invalid /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/dose/engines/_factory.py:140: UserWarning: Engine 'InvalidEngine' not available for Plan. warnings.warn(f"Engine '{pln.prop_dose_calc['engine']}' not available for Plan.") test/dose/test_fred.py: 10 warnings test/dose/test_scenarios_pencilbeam.py: 1 warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "dosimetric_lateral_cutoff" not found in ParticleFredMCEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_fred.py: 10 warnings test/dose/test_scenarios_pencilbeam.py: 1 warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "lateral_model" not found in ParticleFredMCEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_particle_indexing.py: 24 warnings /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:311: UserWarning: The 2023.12 version of the array API specification is still preliminary. Some functions are not yet implemented, and it has not been fully tested. set_array_api_strict_flags(**self.kwargs) test/dose/test_particle_indexing.py: 24 warnings /usr/lib/python3.14/site-packages/array_api_strict/_flags.py:314: UserWarning: The 2023.12 version of the array API specification is still preliminary. Some functions are not yet implemented, and it has not been fully tested. set_array_api_strict_flags(**self.old_flags) test/dose/test_scenarios_pencilbeam.py: 10 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "enable_dij_sampling" not found in ParticleHongPencilBeamEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection_bio[False-numpy] test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection_bio[True-numpy] test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[False-numpy] test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[True-numpy] test/test_raytracersiddon.py::test_boundary_planes_do_not_create_duplicate_voxel_segments test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[0.0-0.0] test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[45.0-0.0] /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:388: RuntimeWarning: divide by zero encountered in divide (p_min - self._source_points) / self._ray_vec, # alpha to "near" plane test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection_bio[False-numpy] test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection_bio[True-numpy] test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[False-numpy] test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[True-numpy] test/test_raytracersiddon.py::test_boundary_planes_do_not_create_duplicate_voxel_segments test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[0.0-0.0] test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[45.0-0.0] /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_siddon.py:389: RuntimeWarning: divide by zero encountered in divide (p_max - self._source_points) / self._ray_vec, test/dose/test_scenarios_pencilbeam.py::test_two_phase_nominal_model_validates test/dose/test_scenarios_pencilbeam.py::test_explicit_model_is_accepted /usr/lib/python3.14/site-packages/pydantic/main.py:1073: DeprecationWarning: Plan.mult_scen is deprecated; use Plan.scenarios. return lambda model, _name, val: attr.__set__(model, val) test/dose/test_scenarios_pencilbeam.py::test_public_entry_point_scenario_override /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/dose/test_scenarios_pencilbeam.py:380: DeprecationWarning: Plan.mult_scen is deprecated; use Plan.scenarios. model_before = pln.mult_scen.model_dump() test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[False-numpy] test/dose/test_scenarios_pencilbeam.py::test_sampling_with_setup_range_and_ct_scenarios[True-numpy] test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[0.0-0.0] test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[45.0-0.0] /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/raytracer/_kernels.py:94: RuntimeWarning: invalid value encountered in multiply ijk = sp_scaled[:, :, None] + rv_scaled[:, :, None] * alphas_mid[:, None, :] test/dose/test_topas.py::test_init_topas test/dose/test_topas.py::test_default_simu_dir_is_in_user_data_dir /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "dosimetric_lateral_cutoff" not found in ParticleTOPASMCEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/dose/test_topas.py::test_init_topas test/dose/test_topas.py::test_default_simu_dir_is_in_user_data_dir /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/_configurable.py:310: UserWarning: Property "lateral_model" not found in ParticleTOPASMCEngine! warnings.warn(f'Property "{key}" not found in {type(self).__name__}!') test/io/test_io_dicom.py::test_import_ct_matches_reference test/io/test_io_dicom.py::test_import_cst_matches_reference test/io/test_io_dicom.py::test_import_dose_matches_reference test/io/test_io_dicom.py::test_load_data_from_dicom_folder /usr/lib/python3.14/site-packages/pymatreader/utils.py:393: UserWarning: Complex objects (like classes) are not supported. They are imported on a best effort base but your mileage will vary. warn( test/io/test_io_matlab.py::test_matlab_roundtrip_preserves_plan /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/io/test_io_matlab.py:212: DeprecationWarning: Plan.mult_scen is deprecated; use Plan.scenarios. assert reloaded.mult_scen.ct_scen_prob == [(0, 1.0)] test/io/test_io_matlab.py::test_matlab_roundtrip_preserves_plan /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/io/test_io_matlab.py:212: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert reloaded.mult_scen.ct_scen_prob == [(0, 1.0)] test/io/test_io_sitk.py::test_load_patient_single_nifti_file test/io/test_io_sitk.py::test_single_file_ct_roundtrip /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/io/_load_save.py:150: UserWarning: cst/StructureSet is missing from the patient file. warnings.warn("cst/StructureSet is missing from the patient file.") test/optimization/test_dose_convention.py: 21 warnings test/optimization/test_fluence_optiprob.py: 7 warnings test/optimization/test_obj_history.py: 6 warnings test/optimization/test_opt_info.py: 11 warnings test/optimization/test_robust_fluence_optiprob.py: 14 warnings test/quantities/test_effect_quantity.py: 3 warnings test/quantities/test_let_quantity.py: 5 warnings test/quantities/test_multi_scenario_quantities.py: 7 warnings test/quantities/test_rbe_x_dose_quantity.py: 12 warnings test/quantities/test_resolver.py: 13 warnings test/quantities/test_sqrt_beta_dose_quantity.py: 1 warning test/test_dij_scenarios.py: 1 warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_resolver.py:47: UserWarning: Requested GPU device is not available on array_api_strict. Falling back to CPU. device = compute_backend.choose_device(xp) test/optimization/test_dose_convention.py: 21 warnings test/optimization/test_fluence_optiprob.py: 7 warnings test/optimization/test_obj_history.py: 6 warnings test/optimization/test_opt_info.py: 11 warnings test/optimization/test_robust_fluence_optiprob.py: 14 warnings test/quantities/test_alpha_dose_quantity.py: 3 warnings test/quantities/test_dose_quantity.py: 3 warnings test/quantities/test_effect_quantity.py: 3 warnings test/quantities/test_let_dose_quantity.py: 3 warnings test/quantities/test_let_quantity.py: 5 warnings test/quantities/test_multi_scenario_quantities.py: 11 warnings test/quantities/test_rbe_x_dose_quantity.py: 12 warnings test/quantities/test_resolver.py: 11 warnings test/quantities/test_sqrt_beta_dose_quantity.py: 4 warnings test/test_dij_scenarios.py: 1 warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/quantities/_base.py:151: UserWarning: Requested GPU device is not available on array_api_strict. Falling back to CPU. device = compute_backend.choose_device(xp) test/optimization/test_obj_history.py: 4 warnings test/optimization/test_opt_info.py: 7 warnings test/optimization/test_robust_fluence_optiprob.py: 5 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/helpers.py:484: UserWarning: Synchronization helper for namespace 'array_api_strict' is not implemented. warnings.warn( test/scenarios/test_scenario_gridded.py: 31 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:81: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(model.scen_for_prob.shape, expected.shape) test/scenarios/test_scenario_gridded.py: 31 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:82: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.testing.assert_allclose(model.scen_for_prob, expected, rtol=1e-12, atol=1e-12) test/scenarios/test_scenario_gridded.py: 31 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:84: DeprecationWarning: ScenarioModel.scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.testing.assert_allclose(model.scen_prob, ref["scenProb"].reshape(-1), rtol=1e-10) test/scenarios/test_scenario_gridded.py: 31 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:85: DeprecationWarning: ScenarioModel.scen_weight is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.testing.assert_allclose(model.scen_weight, ref["scenWeight"].reshape(-1), rtol=1e-10) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:91: DeprecationWarning: ScenarioModel.linear_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(model.linear_mask, linear) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:93: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.scen_mask.shape == mask_shape test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:94: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(model.scen_mask, ref["scenMask"].astype(bool)) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:95: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_shift_scen == int(_scalar(ref["totNumShiftScen"])) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:96: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_range_scen == int(_scalar(ref["totNumRangeScen"])) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:97: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_scen == int(_scalar(ref["totNumScen"])) == len(scen) test/scenarios/test_scenario_gridded.py: 30 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:103: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. for i in range(model.tot_num_scen): test/scenarios/test_scenario_gridded.py: 9966 warnings test/scenarios/test_scenario_random.py: 1 warning test/test_scenarios.py: 3 warnings /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/_legacy.py:175: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.ravel_multi_index((ct_scen, shift_scen, range_shift_scen), self.scen_mask.shape) test/scenarios/test_scenario_gridded.py::test_even_grid_without_nominal_point_has_value_consistent_layout /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:129: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.tot_num_shift_scen == 9 test/scenarios/test_scenario_gridded.py::test_wc_scen_defaults_and_counts /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:140: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert (m.tot_num_shift_scen, m.tot_num_range_scen) == (7, 3) test/scenarios/test_scenario_gridded.py::test_wc_scen_defaults_and_counts /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:140: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert (m.tot_num_shift_scen, m.tot_num_range_scen) == (7, 3) test/scenarios/test_scenario_gridded.py::test_zero_sd_collapses_duplicates /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_gridded.py:177: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.tot_num_range_scen == 1 test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:125: DeprecationWarning: ScenarioModel.range_rel_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.range_rel_sd == 3.5 and m.range_abs_sd == 1.0 test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:125: DeprecationWarning: ScenarioModel.range_abs_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.range_rel_sd == 3.5 and m.range_abs_sd == 1.0 test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:126: DeprecationWarning: ScenarioModel.shift_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.shift_sd == (2.25, 2.25, 2.25) test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:127: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.ct_scen_prob == [(0, 1.0)] test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /usr/lib/python3.14/site-packages/pydantic/main.py:1073: DeprecationWarning: ScenarioModel.range_rel_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. return lambda model, _name, val: attr.__set__(model, val) test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /usr/lib/python3.14/site-packages/pydantic/main.py:1073: DeprecationWarning: ScenarioModel.range_abs_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. return lambda model, _name, val: attr.__set__(model, val) test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /usr/lib/python3.14/site-packages/pydantic/main.py:1073: DeprecationWarning: ScenarioModel.shift_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. return lambda model, _name, val: attr.__set__(model, val) test/scenarios/test_scenario_models.py::test_legacy_flat_properties_read_and_write /usr/lib/python3.14/site-packages/pydantic/main.py:1073: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. return lambda model, _name, val: attr.__set__(model, val) test/scenarios/test_scenario_models.py::test_validate_scenario_model_ctscenprob_shapes[ct_scen_prob0] test/scenarios/test_scenario_models.py::test_validate_scenario_model_ctscenprob_shapes[ct_scen_prob1] test/scenarios/test_scenario_models.py::test_validate_scenario_model_ctscenprob_shapes[ct_scen_prob2] /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_models.py:258: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.ct_scen_prob == [(0, 1.0)] test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:120: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.scen_mask.shape == (3, 4, 4) test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:121: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.tot_num_shift_scen == m.tot_num_range_scen == 4 test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:121: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.tot_num_shift_scen == m.tot_num_range_scen == 4 test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:122: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert m.tot_num_scen == 8 test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:125: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(m.scen_mask, expected) test/scenarios/test_scenario_random.py::test_legacy_mask_is_diagonal /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:126: DeprecationWarning: ScenarioModel.linear_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(m.linear_mask, [[p, i, i] for p in (0, 1) for i in range(4)]) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:147: DeprecationWarning: ScenarioModel.linear_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(model.linear_mask, ref["linearMask"].astype(int) - 1) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:148: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(model.scen_mask, ref["scenMask"].astype(bool)) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:149: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.scen_mask.shape == tuple(int(v) for v in ref["scenMaskSize"].reshape(-1)) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:150: DeprecationWarning: ScenarioModel.scen_weight is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.testing.assert_allclose(model.scen_weight, ref["scenWeight"].reshape(-1), rtol=1e-10) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:151: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_shift_scen == int(ref["totNumShiftScen"].item()) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:152: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_range_scen == int(ref["totNumRangeScen"].item()) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:153: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert model.tot_num_scen == int(ref["totNumScen"].item()) == len(s) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:154: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. np.testing.assert_array_equal(model.scen_for_prob[:, 0], ref["scenForProb"][:, 0] - 1) test/scenarios/test_scenario_random.py::test_matches_matrad_structure /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/scenarios/test_scenario_random.py:157: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.all(model.scen_for_prob[[0, 4], 1:] == 0) test/test_keyboard_listener.py: 10 warnings /usr/lib64/python3.14/pty.py:66: DeprecationWarning: This process (pid=3838) is multi-threaded, use of forkpty() may lead to deadlocks in the child. pid, fd = os.forkpty() test/test_machine_model.py::test_photon_machine_model_svdpb_get_kernel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_machine_model.py:97: DeprecationWarning: String shape expressions like '501, 3, 360' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] assert isinstance(kernel.kernel_data, NDArray[Shape[f"{nssds}, {nk}, {npos}"], np.float64]) test/test_machine_model.py::test_photon_machine_model_svdpb_get_kernel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_machine_model.py:100: DeprecationWarning: String shape expressions like '3, 360' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] assert isinstance(kernel1, NDArray[Shape[f"{nk}, {npos}"], np.float64]) test/test_machine_model.py::test_photon_machine_model_svdpb_get_kernel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_machine_model.py:102: DeprecationWarning: String shape expressions like '3, 360' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] assert isinstance(kernel2, NDArray[Shape[f"{nk}, {npos}"], np.float64]) test/test_machine_model.py::test_photon_machine_model_svdpb_get_kernel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_machine_model.py:108: DeprecationWarning: String shape expressions like '3, 360' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] assert isinstance(kernel_low, NDArray[Shape[f"{nk}, {npos}"], np.float64]) test/test_machine_model.py::test_photon_machine_model_svdpb_get_kernel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_machine_model.py:113: DeprecationWarning: String shape expressions like '3, 360' are deprecated, use type expressions instead, e.g. Shape[L[3], int, Range[L[2], L[4]], *Repeat] assert isinstance(kernel_high, NDArray[Shape[f"{nk}, {npos}"], np.float64]) test/test_plan.py::test_create_pln_dict_photons_snake /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_plan.py:107: DeprecationWarning: Plan.mult_scen is deprecated; use Plan.scenarios. assert isinstance(pln.mult_scen, NominalScenario) test/test_plan.py::test_create_pln_dict_photons_camel /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_plan.py:157: DeprecationWarning: Plan.mult_scen is deprecated; use Plan.scenarios. assert isinstance(pln.mult_scen, NominalScenario) test/test_plan.py::test_legacy_photon_kernels_are_rescaled_exactly_once /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/machines/base/_external_beam.py:41: UserWarning: Meta data key version is already present in the data dictionary. warnings.warn( test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[45.0-0.0] test/test_raytracersiddon.py::test_trace_cubes_traverses_full_cube_at_oblique_angles[30.0-45.0] test/test_raytracersiddon.py::test_trace_depth_arrays_stay_on_backend[numpy] /usr/lib64/python3.14/site-packages/numpy/lib/_function_base_impl.py:1529: RuntimeWarning: invalid value encountered in subtract a = op(a[slice1], a[slice2]) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:70: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.ct_scen_prob == [(0, 1.0)] test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:71: DeprecationWarning: ScenarioModel.num_of_ct_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.num_of_ct_scen == 1 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:72: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.tot_num_scen == 1 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:73: DeprecationWarning: ScenarioModel.tot_num_shift_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.tot_num_shift_scen == 1 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:74: DeprecationWarning: ScenarioModel.tot_num_range_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.tot_num_range_scen == 1 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:75: DeprecationWarning: ScenarioModel.rel_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.rel_range_shift == 0.0 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:76: DeprecationWarning: ScenarioModel.abs_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.abs_range_shift == 0.0 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:77: DeprecationWarning: ScenarioModel.iso_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.iso_shift, np.array([[0.0, 0.0, 0.0]])) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:78: DeprecationWarning: ScenarioModel.max_abs_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.max_abs_range_shift == 0.0 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:79: DeprecationWarning: ScenarioModel.max_rel_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.max_rel_range_shift == 0.0 test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:80: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.scen_mask, np.ones((1, 1, 1)).astype(bool)) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:81: DeprecationWarning: ScenarioModel.linear_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.linear_mask, np.array([[0, 0, 0]])) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:82: DeprecationWarning: ScenarioModel.ct_scen_ix is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.ct_scen_ix, [0]) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:83: DeprecationWarning: ScenarioModel.scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.allclose(scenario.scen_prob, helper_mvar_gauss(scenario)) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:31: DeprecationWarning: ScenarioModel.shift_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. scenario_model.shift_sd, test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:32: DeprecationWarning: ScenarioModel.range_abs_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. scenario_model.range_abs_sd, test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:33: DeprecationWarning: ScenarioModel.range_rel_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. scenario_model.range_rel_sd / 100.0, test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:40: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. tmp_standardized = np.linalg.solve(cs, scenario_model.scen_for_prob[:, 1:].T).T test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:49: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. for phase in scenario_model.scen_for_prob[:, 0] test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct test/test_scenarios.py::test_legacy_view_with_two_phases test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:48: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. [x[1] for x in scenario_model.ct_scen_prob if x[0] == phase][0] test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:84: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.scen_for_prob, np.zeros((1, 6))) test/test_scenarios.py::test_nominal_scenario_construct test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:85: DeprecationWarning: ScenarioModel.scen_weight is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.scen_weight, np.ones((1,), dtype=float)) test/test_scenarios.py::test_nominal_scenario_construct_with_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:98: DeprecationWarning: ScenarioModel.num_of_available_ct_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.num_of_available_ct_scen == 1 test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:103: DeprecationWarning: ScenarioModel.num_of_ct_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.num_of_ct_scen == 2 test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:104: DeprecationWarning: ScenarioModel.num_of_available_ct_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.num_of_available_ct_scen == 3 test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:105: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.tot_num_scen == 2 test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:106: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.scen_mask.shape == (3, 1, 1) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:107: DeprecationWarning: ScenarioModel.scen_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.scen_mask[:, 0, 0], [True, False, True]) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:108: DeprecationWarning: ScenarioModel.linear_mask is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.linear_mask, [[0, 0, 0], [2, 0, 0]]) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:109: DeprecationWarning: ScenarioModel.ct_scen_ix is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.ct_scen_ix, [0, 2]) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:114: DeprecationWarning: ScenarioModel.scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.allclose(scenario.scen_prob, helper_mvar_gauss(scenario)) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:115: DeprecationWarning: ScenarioModel.scen_weight is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.allclose(scenario.scen_weight, [0.5, 0.5]) test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/scenarios/_legacy.py:190: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. return self.scen_for_prob test/test_scenarios.py::test_legacy_view_with_two_phases /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:116: DeprecationWarning: ScenarioModel.scen_for_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.update_scenarios(), scenario.scen_for_prob) test/test_scenarios.py::test_nominal_scenario_creation_by_legacy_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:142: DeprecationWarning: ScenarioModel.range_rel_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.range_rel_sd == 5.0 test/test_scenarios.py::test_nominal_scenario_creation_by_legacy_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:143: DeprecationWarning: ScenarioModel.range_abs_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.range_abs_sd == 2.5 test/test_scenarios.py::test_nominal_scenario_creation_by_legacy_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:144: DeprecationWarning: ScenarioModel.shift_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.shift_sd == (3.0, 3.0, 3.0) test/test_scenarios.py::test_nominal_scenario_creation_by_legacy_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:145: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.ct_scen_prob == [(0, 0.5)] test/test_scenarios.py::test_nominal_scenario_creation_by_matrad_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:154: DeprecationWarning: ScenarioModel.range_rel_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.range_rel_sd == 5.0 test/test_scenarios.py::test_nominal_scenario_creation_by_matrad_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:155: DeprecationWarning: ScenarioModel.range_abs_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.range_abs_sd == 2.5 test/test_scenarios.py::test_nominal_scenario_creation_by_matrad_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:156: DeprecationWarning: ScenarioModel.shift_sd is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.shift_sd == (3.0, 3.0, 3.0) test/test_scenarios.py::test_nominal_scenario_creation_by_matrad_dict /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:157: DeprecationWarning: ScenarioModel.ct_scen_prob is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert scenario.ct_scen_prob == [(0, 0.5)] test/test_scenarios.py::test_scenario_serialization_emits_no_pydantic_warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:175: DeprecationWarning: ScenarioModel.rel_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.rel_range_shift, np.zeros(1)) test/test_scenarios.py::test_scenario_serialization_emits_no_pydantic_warning /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:176: DeprecationWarning: ScenarioModel.abs_range_shift is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert np.array_equal(scenario.abs_range_shift, np.zeros(1)) test/test_scenarios.py::test_nominal_scenario_extract_single_scenario /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0/test/test_scenarios.py:183: DeprecationWarning: ScenarioModel.tot_num_scen is deprecated and will be removed after one release; configure the setup, range and ct_phase dimensions and query the ScenarioSet. assert single.tot_num_scen == 1 test/visualization/test_plot_slice.py::test_plot_slice_ct /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/visualization/_plot_slice.py:410: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`. _, axes = plt.subplots(rows, cols, figsize=(5 * cols, 5 * rows)) -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ FAILED test/biology/models/test_custom_model_extension.py::test_custom_model_runs_in_particle_engine FAILED test/biology/models/test_fragment_species_selection.py::test_spectrum_tables_are_cached_per_logical_device FAILED test/biology/models/test_kernel_bio_model.py::test_KernelBasedLQModel_evaluate_mixed_tissue_classes FAILED test/biology/models/test_kernel_bio_model.py::test_declared_tissue_classes_are_mapped_onto_kernel_rows_by_value FAILED test/biology/models/test_kernel_bio_model.py::test_machine_without_tissue_parameters_uses_the_kernel_classes FAILED test/biology/models/test_kernel_let_model.py::test_LinearScaling_alpha_beta FAILED test/biology/models/test_reference_parameter_domain.py::test_outside_structure_voxels_evaluate_to_zero_array_api[LinearScaling] FAILED test/biology/models/test_tabulated_kernel_model.py::test_TabulatedAlphaBetaModel_evaluate FAILED test/biology/models/test_tissue_lookup.py::test_exact_gather - IndexEr... FAILED test/biology/models/test_tissue_lookup.py::test_exact_gather_takes_one_dimensional_kernels_per_voxel FAILED test/biology/models/test_tissue_lookup.py::test_exact_gather_skips_the_check_once_the_grid_is_validated FAILED test/biology/models/test_tissue_lookup.py::test_gather_tissue_parameters_matches_the_per_bixel_conversion FAILED test/biology/models/test_tissue_lookup.py::test_reference_cache_distinguishes_logical_devices FAILED test/biology/models/test_tissue_lookup.py::test_gather_works_on_a_non_default_logical_device FAILED test/biology/models/test_zstar_bio_model.py::test_MKM_evaluate_combines_kernel_rows_with_the_class_parameters FAILED test/biology/models/test_zstar_bio_model.py::test_mkm_copies_no_host_data_per_bixel FAILED test/biology/models/test_zstar_bio_model.py::test_MKM_evaluate_influence_weights_the_class_parameters_with_the_dose FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-nearest-23] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-nearest-4] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict--3.25-23] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict--3.25-4] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-False-23] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-False-4] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-True-23] FAILED test/core/test_resample_array_api.py::test_enums_extrapolation_and_backend[array_api_strict-True-4] FAILED test/core/test_resample_array_api.py::test_small_bspline_fallback_is_preserved[array_api_strict] FAILED test/core/xp_utils/compat/test_backend_consistency.py::test_interp1d_2d_boundaries[array_api_strict] FAILED test/core/xp_utils/compat/test_backend_consistency.py::test_interp1d_container_boundaries[array_api_strict] FAILED test/core/xp_utils/compat/test_backend_consistency.py::test_interp1d_multidimensional_queries[array_api_strict] FAILED test/core/xp_utils/compat/test_backend_consistency.py::test_interpnd_bounds_and_multiple_queries[array_api_strict] FAILED test/core/xp_utils/compat/test_interpnd.py::test_interpnd_generic_returns[2d] FAILED test/core/xp_utils/compat/test_interpnd.py::test_interpnd_generic_returns[3d] FAILED test/core/xp_utils/compat/test_interpnd.py::test_interpnd_generic_2d_handles_descending_axes FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_basic[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_basic[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_on_points[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_on_points[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_2darray[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_2darray[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_multiple_y_stack_sequence[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_multiple_y_stack_sequence[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1_multiple_y_sequence[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1_multiple_y_sequence[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_mixed_1d_2d_sequence[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_mixed_1d_2d_sequence[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_dict_input[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_dict_input[dtype1] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_out_of_bounds[dtype0] FAILED test/core/xp_utils/compat/test_math_interp1d.py::test_interp1d_out_of_bounds[dtype1] FAILED test/core/xp_utils/helpers/test_device_parsing.py::test_parse_array_api_strict_default_device FAILED test/core/xp_utils/helpers/test_device_parsing.py::test_device_repr_containing_cpu_is_not_classified_as_cpu FAILED test/core/xp_utils/helpers/test_device_parsing.py::test_device_cache_key_prefers_the_backend_device_object FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float32-2-True] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float32-2-False] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float32-3-True] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float32-3-False] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float64-2-True] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float64-2-False] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float64-3-True] FAILED test/core/xp_utils/test_interpolation.py::test_repeated_queries[array_api_strict-float64-3-False] FAILED test/core/xp_utils/test_interpolation.py::test_bounds_and_query_validation[array_api_strict-True] FAILED test/core/xp_utils/test_interpolation.py::test_bounds_and_query_validation[array_api_strict-False] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape0-2-True] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape0-2-False] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape0-3-True] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape0-3-False] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape1-2-True] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape1-2-False] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape1-3-True] FAILED test/core/xp_utils/test_interpolation.py::test_shared_value_dimensions[array_api_strict-value_shape1-3-False] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None-None-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-None--3.5-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723-None-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict--0.1723--3.5-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234-None-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-array-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-array-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-fields-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-fields-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_rows-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_rows-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_dtype-float32] FAILED test/core/xp_utils/test_interpolation1d.py::test_prepared_matches_one_shot[array_api_strict-13.234--3.5-mixed_dtype-float64] FAILED test/core/xp_utils/test_interpolation1d.py::test_dispatch_preference[array_api_strict-None] FAILED test/core/xp_utils/test_interpolation1d.py::test_dispatch_preference[array_api_strict-True] FAILED test/core/xp_utils/test_interpolation1d.py::test_dispatch_preference[array_api_strict-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue0-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue2-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue3-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[carbon-alpha_beta_kernels-tissue4-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-alpha_beta_kernels-tissue6-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-zstar_kernels-tissue8-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-zstar_kernels-tissue9-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[oxygen-LEM-tissue11-False] FAILED test/dose/test_bio_tissue_check.py::test_requested_bio_dose_raises_exactly_when_the_check_reports_errors[protons-WED-tissue14-False] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[carbon-alpha_beta_kernels-tissue0] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[carbon-zstar_kernels-tissue1] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-alpha_beta_kernels-tissue2] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-zstar_kernels-tissue3] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[oxygen-zstar_kernels-tissue4] FAILED test/dose/test_bio_tissue_check.py::test_automatic_bio_dose_falls_back_to_physical_dose_on_errors[protons-MCN-tissue5] FAILED test/dose/test_bio_tissue_check.py::test_differing_provenance_label_warns_and_evaluates_the_model[oxygen-zstar_kernels-tissue0-relabelled0-auto] FAILED test/dose/test_bio_tissue_check.py::test_differing_provenance_label_warns_and_evaluates_the_model[oxygen-zstar_kernels-tissue0-relabelled0-True] FAILED test/dose/test_bio_tissue_check.py::test_differing_provenance_label_warns_and_evaluates_the_model[carbon-alpha_beta_kernels-tissue1-relabelled1-auto] FAILED test/dose/test_bio_tissue_check.py::test_differing_provenance_label_warns_and_evaluates_the_model[carbon-alpha_beta_kernels-tissue1-relabelled1-True] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_matching_tissue[protons] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_matching_tissue[helium] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_matching_tissue[carbon] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_matching_tissue[oxygen] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[protons] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[helium] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[carbon] FAILED test/dose/test_default_bio_models.py::test_default_bio_model_with_unmatched_tissue_keeps_physical_workflow[oxygen] FAILED test/dose/test_default_bio_models.py::test_unmatched_tissue_with_physical_dose_only[carbon] FAILED test/dose/test_default_bio_models.py::test_unmatched_tissue_with_physical_dose_only[oxygen] FAILED test/dose/test_default_bio_models.py::test_oxygen_lem_dose_calculation[0.1] FAILED test/dose/test_default_bio_models.py::test_oxygen_lem_dose_calculation[0.5] FAILED test/dose/test_default_bio_models.py::test_oxygen_mkm_dose_calculation FAILED test/dose/test_default_bio_models.py::test_oxygen_mkm_rejects_unset_alpha_0[auto] FAILED test/dose/test_engine_reuse.py::test_reused_engine_repeats_forward_dose FAILED test/dose/test_engine_reuse.py::test_reused_engine_uses_the_structures_of_each_call FAILED test/dose/test_engine_reuse.py::test_forward_dose_leaves_the_stf_weights_alone FAILED test/dose/test_engine_reuse.py::test_keep_rad_depth_cubes - AttributeE... FAILED test/dose/test_engine_reuse.py::test_reused_engine_resolves_the_bio_model_per_calculation FAILED test/dose/test_engine_reuse.py::test_reused_engine_resolves_the_lateral_model_per_calculation FAILED test/dose/test_hongpb.py::test_protons_cd_forward - AttributeError: 'f... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_none - Att... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_WED - Attr... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_MCN - Attr... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_CAR - Attr... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_LSM - Attr... FAILED test/dose/test_hongpb.py::test_protons_cd_forward_bio_model_const - At... FAILED test/dose/test_hongpb.py::test_helium_cd_forward - AttributeError: 'fl... FAILED test/dose/test_hongpb.py::test_helium_cd_forward_bio_model_none - Attr... FAILED test/dose/test_hongpb.py::test_helium_cd_forward_bio_model_LSM - Attri... FAILED test/dose/test_hongpb.py::test_carbon_cd_forward - AttributeError: 'fl... FAILED test/dose/test_hongpb.py::test_carbon_cd_forward_bio_model_none - Attr... FAILED test/dose/test_hongpb.py::test_oxygen_cd_forward - AttributeError: 'fl... FAILED test/dose/test_hongpb.py::test_protons_cd_influence - AttributeError: ... FAILED test/dose/test_hongpb.py::test_protons_cd_influence_bio_model_none - A... FAILED test/dose/test_hongpb.py::test_protons_cd_influence_bio_model_WED - At... FAILED test/dose/test_hongpb.py::test_protons_cd_influence_bio_model_MCN - At... FAILED test/dose/test_hongpb.py::test_protons_cd_influence_bio_model_CAR - At... FAILED test/dose/test_hongpb.py::test_protons_cd_influence_bio_model_LSM - At... FAILED test/dose/test_hongpb.py::test_helium_cd_influence - AttributeError: '... FAILED test/dose/test_hongpb.py::test_helium_cd_influence_bio_model_none - At... FAILED test/dose/test_hongpb.py::test_helium_cd_influence_bio_model_LSM - Att... FAILED test/dose/test_hongpb.py::test_carbon_cd_influence_bio_model_none - At... FAILED test/dose/test_hongpb.py::test_oxygen_cd_influence - AttributeError: '... FAILED test/dose/test_hongpb.py::test_carbon_cd_influence_bio_model_unavailable_keeps_physical_dose FAILED test/dose/test_hongpb.py::test_carbon_multi_gaussian_reduces_to_single FAILED test/dose/test_hongpb.py::test_protons_cd_forward_uses_loaded_plan_machine FAILED test/dose/test_hongpb_bio.py::test_protons_WED_alpha_beta_matrices - A... FAILED test/dose/test_hongpb_bio.py::test_protons_MCN_alpha_beta_matrices - A... FAILED test/dose/test_hongpb_bio.py::test_helium_HEL_alpha_beta_matrices - At... FAILED test/dose/test_hongpb_bio.py::test_protons_constant_rbe - AttributeErr... FAILED test/dose/test_hongpb_bio.py::test_protons_constant_rbe_parameter_from_plan FAILED test/dose/test_hongpb_bio.py::test_calc_bio_dose_off_keeps_let_for_on_the_fly_models FAILED test/dose/test_hongpb_bio.py::test_calc_let_off_still_feeds_let_based_model FAILED test/dose/test_hongpb_bio.py::test_protons_bio_model_none_has_no_bio_matrices FAILED test/dose/test_hongpb_bio.py::test_carbon_kernel_based_lq_alpha_beta_matrices FAILED test/dose/test_hongpb_bio.py::test_carbon_tabulated_alpha_beta_matrices FAILED test/dose/test_hongpb_bio.py::test_bio_tissue_arrays_use_the_selected_device FAILED test/dose/test_hongpb_bio.py::test_out_of_domain_reference_parameters_without_bio_request_keep_physical_dose FAILED test/dose/test_hongpb_bio.py::test_bio_influence_matrices_are_finite FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-integral-single] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-integral-double] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-integral-multi] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-integral-multi_1d] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-integral-singleXY] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-relative-single] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-relative-double] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-relative-multi] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-relative-multi_1d] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-1-relative-singleXY] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-single] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-double] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-multi] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-multi_1d] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-integral-singleXY] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-single] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-double] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-multi] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-multi_1d] FAILED test/dose/test_particle_cutoff.py::test_cutoff_matches_scalar_reference[array_api_strict-100000-relative-singleXY] FAILED test/dose/test_particle_cutoff.py::test_quadrature_respects_explicit_and_inferred_device FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-False-empty] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-False-none] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-False-all] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-False-mixed] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-True-empty] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-True-none] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-True-all] FAILED test/dose/test_particle_indexing.py::test_particle_support_selection[strict2023-table-True-mixed] FAILED test/dose/test_particle_interpolators.py::test_translated_depths_and_cache[float32-array_api_strict] FAILED test/dose/test_particle_interpolators.py::test_translated_depths_and_cache[float64-array_api_strict] FAILED test/dose/test_particle_interpolators.py::test_reused_engine_rebuilds_prepared_state[False] FAILED test/dose/test_particle_interpolators.py::test_reused_engine_rebuilds_prepared_state[True] FAILED test/dose/test_particle_lateral_cutoff.py::test_particle_beams_use_their_own_lateral_cutoffs FAILED test/dose/test_ray_geometry_preparation.py::test_ssd_metadata_transferred_in_batches[array_api_strict-1] FAILED test/dose/test_ray_geometry_preparation.py::test_ssd_metadata_transferred_in_batches[array_api_strict-7] FAILED test/dose/test_scenarios_pencilbeam.py::test_nominal_set_has_one_flat_slot[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_nominal_set_has_one_flat_slot[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_recorded_on_the_dij[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_recorded_on_the_dij[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_setup_and_range_scenarios[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_setup_and_range_scenarios[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_proton_range_shift_pulls_the_dose_upstream FAILED test/dose/test_scenarios_pencilbeam.py::test_shifts_do_not_accumulate[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_shifts_do_not_accumulate[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_ct_phase_with_moved_outline_matches_standalone[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_ct_phase_with_moved_outline_matches_standalone[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection_bio_single_and_reordered FAILED test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_ct_phase_selection[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_two_phase_nominal_model_validates FAILED test/dose/test_scenarios_pencilbeam.py::test_derived_scenarios_are_not_computed[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_derived_scenarios_are_not_computed[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_explicit_model_is_accepted FAILED test/dose/test_scenarios_pencilbeam.py::test_public_entry_point_scenario_override FAILED test/dose/test_scenarios_pencilbeam.py::test_forward_dose_returns_every_scenario FAILED test/dose/test_scenarios_pencilbeam.py::test_forward_dose_single_scenario_has_no_scenario_lists FAILED test/dose/test_scenarios_pencilbeam.py::test_shift_scenarios_in_biological_results FAILED test/dose/test_scenarios_pencilbeam.py::test_shift_scenarios_in_biological_quantities FAILED test/dose/test_scenarios_pencilbeam.py::test_progress_counts_the_computed_scenarios[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_progress_counts_the_computed_scenarios[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_computed_scenarios_share_one_index_array[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_computed_scenarios_share_one_index_array[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_negative_range_shift_and_a_set_without_range_dimension FAILED test/dose/test_scenarios_pencilbeam.py::test_rays_missing_the_patient_take_the_ssd_of_their_neighbors FAILED test/dose/test_scenarios_pencilbeam.py::test_public_api_accepts_a_3d_structure_set_on_a_4d_ct FAILED test/dose/test_scenarios_pencilbeam.py::test_4d_structure_set_gives_the_same_influence_matrices[protons] FAILED test/dose/test_scenarios_pencilbeam.py::test_4d_structure_set_gives_the_same_influence_matrices[photons] FAILED test/dose/test_scenarios_pencilbeam.py::test_optimization_runs_on_a_4d_ct FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_evaluated_on_the_contour_of_their_ct_phase[none] FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_evaluated_on_the_contour_of_their_ct_phase[STOCH] FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_evaluated_on_the_contour_of_their_ct_phase[OWC] FAILED test/dose/test_scenarios_pencilbeam.py::test_scenarios_are_evaluated_on_the_contour_of_their_ct_phase[COWC] FAILED test/dose/test_scenarios_pencilbeam.py::test_none_robustness_sums_each_phase_on_its_own_contour FAILED test/dose/test_scenarios_pencilbeam.py::test_voxel_worst_case_uses_the_contour_of_its_selected_phase FAILED test/dose/test_scenarios_pencilbeam.py::test_image_reference_refused_on_moving_structures FAILED test/dose/test_scenarios_pencilbeam.py::test_moving_structures_on_a_coarser_dose_grid FAILED test/dose/test_svdpb.py::test_photons - AttributeError: 'float' object... FAILED test/dose/test_svdpb.py::test_photons_field_based - AttributeError: 'f... FAILED test/dose/test_svdpb.py::test_bixel_based_lateral_cutoff_includes_half_diagonal FAILED test/dose/test_svdpb_bio.py::test_photons_constant_rbe_is_stored_and_applied FAILED test/dose/test_svdpb_bio.py::test_photons_default_model_is_recorded - ... FAILED test/dose/test_svdpb_bio.py::test_photon_engine_drops_a_model_it_cannot_compute FAILED test/dose/test_svdpb_interpolators.py::test_kernel_interpolators_reuse_and_fluence_isolation[array_api_strict-float32] FAILED test/dose/test_svdpb_interpolators.py::test_kernel_interpolators_reuse_and_fluence_isolation[array_api_strict-float64] FAILED test/io/test_io_dicom.py::test_import_ct_matches_reference - Assertion... FAILED test/io/test_io_dicom.py::test_import_cst_matches_reference - Assertio... FAILED test/io/test_io_dicom.py::test_load_data_from_dicom_folder - assert False FAILED test/io/test_io_dicom.py::test_dicom_roundtrip_ct - AssertionError: as... FAILED test/io/test_io_dicom.py::test_dicom_roundtrip_dose - assert False FAILED test/io/test_io_dicom.py::test_dicom_roundtrip_structures - AssertionE... FAILED test/optimization/robustness/test_robustness_contract.py::test_expected_value_operator FAILED test/optimization/robustness/test_robustness_contract.py::test_gradient_follows_the_dtype_of_the_values[expected_value] FAILED test/optimization/robustness/test_robustness_operators.py::test_expected_quantity FAILED test/optimization/robustness/test_robustness_operators.py::test_expected_quantity_is_a_mean_for_any_weight_sum[weights0] FAILED test/optimization/robustness/test_robustness_operators.py::test_expected_quantity_is_a_mean_for_any_weight_sum[weights1] FAILED test/optimization/robustness/test_robustness_operators.py::test_operators_on_phase_contours_match_equal_contours[expected_value] FAILED test/optimization/robustness/test_variance_objective.py::test_variance_closed_form_uniform_default FAILED test/optimization/robustness/test_variance_objective.py::test_variance_weighted_value_and_gradient FAILED test/optimization/robustness/test_variance_objective.py::test_variance_through_scenario_stack FAILED test/optimization/test_fluence_optiprob.py::test_solver_dict_configuration_survives FAILED test/optimization/test_fluence_optiprob.py::test_top_level_overrides_solver_dict FAILED test/optimization/test_fluence_optiprob.py::test_unset_properties_leave_solver_defaults FAILED test/optimization/test_fluence_optiprob.py::test_constant_rbe_evaluates_only_the_quantities_it_uses FAILED test/optimization/test_fluence_optiprob.py::test_objective_jacobian_has_one_row_per_objective[constant] FAILED test/optimization/test_fluence_optiprob.py::test_objective_jacobian_has_one_row_per_objective[effect] FAILED test/optimization/test_fluence_optiprob.py::test_multi_scenario_gradient_backprojects_each_scenario_separately[None] FAILED test/optimization/test_ipax_solver.py::test_backend_arrays_and_vector_bounds[True-strict] FAILED test/optimization/test_obj_history.py::test_problem_objective_fills_history[scipy] FAILED test/optimization/test_obj_history.py::test_history_stays_empty_when_disabled[scipy] FAILED test/optimization/test_objectives.py::test_SquaredMimicking_cache - In... FAILED test/optimization/test_objectives.py::test_MinDVH_compute_objective - ... FAILED test/optimization/test_objectives.py::test_MinDVH_compute_gradient - A... FAILED test/optimization/test_objectives.py::test_MaxDVH_compute_objective - ... FAILED test/optimization/test_objectives.py::test_MaxDVH_compute_gradient - A... FAILED test/optimization/test_robust_fluence_optiprob.py::test_expected_value_is_the_weighted_sum_of_scenario_values FAILED test/optimization/test_robust_fluence_optiprob.py::test_mixed_gradient_matches_finite_differences FAILED test/optimization/test_robust_fluence_optiprob.py::test_jacobian_has_one_row_per_term FAILED test/optimization/test_robust_fluence_optiprob.py::test_shipped_operators_match_finite_differences[logsumexp] FAILED test/optimization/test_robust_fluence_optiprob.py::test_shipped_operators_match_finite_differences[pnorm] FAILED test/optimization/test_robust_fluence_optiprob.py::test_robust_fluence_optimization_end_to_end FAILED test/optimization/test_robust_fluence_optiprob.py::test_reinitializing_a_problem_with_other_scenarios_resets_the_gradient_caches FAILED test/optimization/test_scipy_solver.py::test_simple_problem_scipy - At... FAILED test/optimization/test_scipy_solver.py::test_scipy_emits_status_through_callback FAILED test/optimization/test_scipy_solver.py::test_allow_keyboard_cancel_is_honoured_after_construction FAILED test/optimization/test_scipy_solver.py::test_cancel_key_settings_are_honoured_after_construction FAILED test/optimization/test_scipy_solver.py::test_scipy_status_callback_can_stop FAILED test/quantities/test_multi_scenario_quantities.py::test_rbe_x_dose_uses_voxel_param_column FAILED test/quantities/test_multi_scenario_quantities.py::test_alias_scenarios_share_dose_but_not_voxel_params FAILED test/quantities/test_multi_scenario_quantities.py::test_derived_scenario_is_linear_combination[RBExDose] FAILED test/quantities/test_multi_scenario_quantities.py::test_extend_scenarios_appends_containers_and_columns FAILED test/quantities/test_multi_scenario_quantities.py::test_result_arrays_preserve_array_api_backend FAILED test/quantities/test_rbe_x_dose_quantity.py::test_RBExDose_effect_dense FAILED test/quantities/test_rbe_x_dose_quantity.py::test_RBExDose_effect_sparse FAILED test/quantities/test_rbe_x_dose_quantity.py::test_lq_inverse_dose_supports_linear_limit_and_immutable_arrays FAILED test/quantities/test_rbe_x_dose_quantity.py::test_lq_inverse_dose_is_accurate_in_single_precision_at_low_effect FAILED test/quantities/test_rbe_x_dose_quantity.py::test_lq_inverse_dose_without_alpha_x_solves_the_quadratic_term FAILED test/quantities/test_rbe_x_dose_quantity.py::test_rbe_x_dose_effect_evaluates_in_the_matrix_precision FAILED test/quantities/test_rbe_x_dose_quantity.py::test_RBExDose_effect_gradient_matches_finite_differences FAILED test/stf/test_stf.py::test_stfgen_to_stf - AttributeError: 'float' obj... FAILED test/stf/test_stf.py::test_from_and_to_matrad - pydantic_core._pydanti... FAILED test/stf/test_stf_gen.py::test_generate_with_round_tripped_plan_machine[protons-loaded] FAILED test/stf/test_stf_gen.py::test_generate_with_round_tripped_plan_machine[protons-default-mode] FAILED test/stf/test_stf_gen.py::test_impt - AttributeError: 'float' object h... FAILED test/stf/test_stf_gen.py::test_impt_tg119 - AttributeError: 'float' ob... FAILED test/stf/test_stf_gen.py::test_impt_longitudinal_spot_spacing_thins_energy_layers FAILED test/stf/test_stf_gen.py::test_impt_zero_spot_spacing_keeps_all_layers FAILED test/test_raytracersiddon.py::test_raytracer_trace_single_ray - Attrib... FAILED test/test_raytracersiddon.py::test_raytracer_trace_multiple_rays - Att... FAILED test/test_raytracersiddon.py::test_raytracer_trace_multiple_cubes - At... FAILED test/test_raytracersiddon.py::test_raytracer_ray_does_not_hit - Attrib... FAILED test/test_raytracersiddon.py::test_readonly_sitk_buffer_is_copied_for_backend[array_api_strict] FAILED test/test_raytracersiddon.py::test_trace_depth_arrays_stay_on_backend[array_api_strict] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-False-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-False-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-False-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-False-mixed] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-True-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-True-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-True-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-full-True-mixed] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-False-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-False-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-False-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-False-mixed] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-True-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-True-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-True-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-constant-True-mixed] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-False-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-False-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-False-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-False-mixed] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-True-empty] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-True-none] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-True-all] ERROR test/dose/test_particle_indexing.py::test_particle_support_selection[strict2025-table-True-mixed] ERROR test/optimization/test_opt_info.py::test_opt_info_is_populated[scipy] ERROR test/optimization/test_opt_info.py::test_result_info_is_a_dict[scipy] ERROR test/optimization/test_opt_info.py::test_num_iter_comes_from_the_solver[scipy] ERROR test/optimization/test_opt_info.py::test_obj_history_records_every_evaluation[scipy] = 365 failed, 2380 passed, 645 skipped, 11559 warnings, 28 errors in 152.07s (0:02:32) = error: Bad exit status from /var/tmp/rpm-tmp.KtJa7r (%check) Bad exit status from /var/tmp/rpm-tmp.KtJa7r (%check) RPM build errors: Finish: rpmbuild python-pyradplan-0.8.0-1.fc44.src.rpm Finish: build phase for python-pyradplan-0.8.0-1.fc44.src.rpm INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-44-aarch64-1794040424.031981/root/var/log/dnf5.log INFO: chroot_scan: creating tarball /var/lib/copr-rpmbuild/results/chroot_scan.tar.gz /bin/tar: Removing leading `/' from member names ERROR: Exception(/var/lib/copr-rpmbuild/results/python-pyradplan-0.8.0-1.fc44.src.rpm) Config(fedora-44-aarch64) 3 minutes 14 seconds INFO: Results and/or logs in: /var/lib/copr-rpmbuild/results INFO: Cleaning up build root ('cleanup_on_failure=True') Start: clean chroot INFO: unmounting tmpfs. Finish: clean chroot ERROR: Command failed: # /usr/bin/systemd-nspawn -q -M 310bb156f4bc4c24b2e8920eaa022d49 -D /var/lib/mock/fedora-44-aarch64-1794040424.031981/root -a -u mockbuild --capability=cap_ipc_lock --capability=cap_ipc_lock --bind=/dev/btrfs-control --bind=/dev/mapper/control --bind=/dev/fuse --bind=/dev/loop-control --bind=/dev/loop0 --bind=/dev/loop1 --bind=/dev/loop2 --bind=/dev/loop3 --bind=/dev/loop4 --bind=/dev/loop5 --bind=/dev/loop6 --bind=/dev/loop7 --bind=/dev/loop8 --bind=/dev/loop9 --bind=/dev/loop10 --bind=/dev/loop11 --resolv-conf=off --resolv-conf=off --console=pipe --setenv=TERM=vt100 --setenv=SHELL=/bin/bash --setenv=HOME=/builddir --setenv=HOSTNAME=mock --setenv=PATH=/usr/bin:/bin:/usr/sbin:/sbin '--setenv=PROMPT_COMMAND=printf "\033]0;\007"' '--setenv=PS1= \s-\v\$ ' --setenv=LANG=C.UTF-8 bash --login -c '/usr/bin/rpmbuild -ba --noprep --noclean --target aarch64 /builddir/build/originals/python-pyradplan.spec' Copr build error: Build failed