Warning: Permanently added '34.229.212.245' (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-43-x86_64 --chroot fedora-43-x86_64 Version: 1.11 PID: 11827 Logging PID: 11829 Task: {'allow_user_ssh': False, 'appstream': False, 'background': False, 'build_id': 11283289, 'buildroot_pkgs': [], 'chroot': 'fedora-43-x86_64', '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-43-x86_64/', '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-43-x86_64', '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-e025pw8w/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-e025pw8w/python-pyradplan', '--depth', '500', '--no-single-branch', '--recursive'] cwd: . rc: 0 stdout: stderr: Cloning into '/var/lib/copr-rpmbuild/workspace/workdir-e025pw8w/python-pyradplan'... Running: git checkout 8d50c187fa9c88e50d7f946c5f309e0fa9526e08 -- cmd: ['git', 'checkout', '8d50c187fa9c88e50d7f946c5f309e0fa9526e08', '--'] cwd: /var/lib/copr-rpmbuild/workspace/workdir-e025pw8w/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-e025pw8w/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 500.5M 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-e025pw8w/python-pyradplan/python-pyradplan.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-e025pw8w/python-pyradplan --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1794040424.263307 -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-e025pw8w/python-pyradplan/python-pyradplan.spec --sources /var/lib/copr-rpmbuild/workspace/workdir-e025pw8w/python-pyradplan --resultdir /var/lib/copr-rpmbuild/results --uniqueext 1794040424.263307 -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-e025pw8w/python-pyradplan/python-pyradplan.spec) Config(fedora-43-x86_64) 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-43-x86_64-bootstrap-1794040424.263307/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:43 INFO: Pulling image: registry.fedoraproject.org/fedora:43 INFO: Tagging container image as mock-bootstrap-e8eb2f3c-458f-4f64-9a9f-a08175a6d025 INFO: Checking that 07f45a24d0719212cd8dffda2b52f6cdc5cf22a8efd5a6dd0ff69729a80620d5 image matches host's architecture INFO: Copy content of container 07f45a24d0719212cd8dffda2b52f6cdc5cf22a8efd5a6dd0ff69729a80620d5 to /var/lib/mock/fedora-43-x86_64-bootstrap-1794040424.263307/root INFO: mounting 07f45a24d0719212cd8dffda2b52f6cdc5cf22a8efd5a6dd0ff69729a80620d5 with podman image mount INFO: image 07f45a24d0719212cd8dffda2b52f6cdc5cf22a8efd5a6dd0ff69729a80620d5 as /var/lib/containers/storage/overlay/9ce6879fdc11007a0da77be81259f03144e5c4e9df98e802de5b328a0cb867c2/merged INFO: umounting image 07f45a24d0719212cd8dffda2b52f6cdc5cf22a8efd5a6dd0ff69729a80620d5 (/var/lib/containers/storage/overlay/9ce6879fdc11007a0da77be81259f03144e5c4e9df98e802de5b328a0cb867c2/merged) with podman image umount INFO: Removing image mock-bootstrap-e8eb2f3c-458f-4f64-9a9f-a08175a6d025 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-43-x86_64-1794040424.263307/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.fc43.x86_64 rpm-sequoia-1.10.3-1.fc43.x86_64 dnf5-5.2.18.0-5.fc43.x86_64 dnf5-plugins-5.2.18.0-5.fc43.x86_64 Start: installing minimal buildroot with dnf5 Updating and loading repositories: fedora 100% | 27.7 MiB/s | 35.4 MiB | 00m01s Copr repository 100% | 676.5 KiB/s | 672.4 KiB | 00m01s updates 100% | 30.6 MiB/s | 34.9 MiB | 00m01s Repositories loaded. Package Arch Version Repository Size Installing group/module packages: bash x86_64 5.3.0-2.fc43 fedora 8.4 MiB bzip2 x86_64 1.0.8-21.fc43 fedora 95.3 KiB coreutils x86_64 9.7-10.fc43 updates 5.4 MiB cpio x86_64 2.15-6.fc43 fedora 1.1 MiB diffutils x86_64 3.12-3.fc43 fedora 1.6 MiB fedora-release-common noarch 43-27 updates 20.6 KiB findutils x86_64 1:4.10.0-6.fc43 fedora 1.8 MiB gawk x86_64 5.3.2-2.fc43 fedora 1.8 MiB glibc-minimal-langpack x86_64 2.42-17.fc43 updates 0.0 B grep x86_64 3.12-2.fc43 fedora 1.0 MiB gzip x86_64 1.13-4.fc43 fedora 388.8 KiB info x86_64 7.2-7.fc43 updates 353.9 KiB patch x86_64 2.8-2.fc43 fedora 222.8 KiB redhat-rpm-config noarch 343-14.fc43 updates 182.9 KiB rpm-build x86_64 6.0.2-1.fc43 updates 286.4 KiB sed x86_64 4.9-5.fc43 fedora 857.3 KiB shadow-utils x86_64 2:4.18.0-3.fc43 fedora 3.9 MiB tar x86_64 2:1.35-6.fc43 fedora 2.9 MiB unzip x86_64 6.0-67.fc43 fedora 386.3 KiB util-linux x86_64 2.41.6-1.fc43 updates 3.5 MiB which x86_64 2.23-3.fc43 fedora 83.5 KiB xz x86_64 1:5.8.1-4.fc43 updates 1.3 MiB Installing dependencies: add-determinism x86_64 0.6.0-3.fc43 updates 2.3 MiB alternatives x86_64 1.33-3.fc43 updates 62.2 KiB ansible-srpm-macros noarch 1-18.1.fc43 fedora 35.7 KiB audit-libs x86_64 4.2.1-1.fc43 updates 382.5 KiB binutils x86_64 2.45.1-5.fc43 updates 27.3 MiB build-reproducibility-srpm-macros noarch 0.6.0-3.fc43 updates 735.0 B bzip2-libs x86_64 1.0.8-21.fc43 fedora 80.6 KiB ca-certificates noarch 2026.2.92_v9.0.319-2.fc43 updates 2.7 MiB cmake-srpm-macros noarch 3.31.11-1.fc43 updates 524.0 B coreutils-common x86_64 9.7-10.fc43 updates 11.3 MiB crypto-policies noarch 20251125-1.git63291f8.fc43 updates 147.1 KiB curl x86_64 8.15.0-12.fc43 updates 461.4 KiB cyrus-sasl-lib x86_64 2.1.28-33.fc43 fedora 2.3 MiB debugedit x86_64 5.2-3.fc43 fedora 214.0 KiB dwz x86_64 0.16-2.fc43 fedora 287.1 KiB ed x86_64 1.22.2-1.fc43 fedora 148.1 KiB efi-srpm-macros noarch 6-4.fc43 fedora 40.1 KiB elfutils x86_64 0.197-1.fc43 updates 3.1 MiB elfutils-debuginfod-client x86_64 0.197-1.fc43 updates 83.8 KiB elfutils-default-yama-scope noarch 0.197-1.fc43 updates 1.8 KiB elfutils-libelf x86_64 0.197-1.fc43 updates 1.6 MiB elfutils-libs x86_64 0.197-1.fc43 updates 695.4 KiB fedora-gpg-keys noarch 43-2 updates 259.0 KiB fedora-release noarch 43-27 updates 0.0 B fedora-release-identity-basic noarch 43-27 updates 631.0 B fedora-repos noarch 43-2 updates 4.9 KiB file x86_64 5.46-9.fc43 updates 100.2 KiB file-libs x86_64 5.46-9.fc43 updates 11.9 MiB filesystem x86_64 3.18-50.fc43 fedora 112.0 B filesystem-srpm-macros noarch 3.18-50.fc43 fedora 38.2 KiB fonts-srpm-macros noarch 1:2.0.5-23.fc43 fedora 55.8 KiB forge-srpm-macros noarch 0.4.0-3.fc43 fedora 38.9 KiB fpc-srpm-macros noarch 1.3-15.fc43 fedora 144.0 B gap-srpm-macros noarch 2-1.fc43 fedora 2.1 KiB gdb-minimal x86_64 18.1-1.fc43 updates 13.8 MiB gdbm-libs x86_64 1:1.23-10.fc43 fedora 129.9 KiB ghc-srpm-macros noarch 1.9.2-3.fc43 fedora 779.0 B glibc x86_64 2.42-17.fc43 updates 6.7 MiB glibc-common x86_64 2.42-17.fc43 updates 1.0 MiB glibc-gconv-extra x86_64 2.42-17.fc43 updates 7.2 MiB gmp x86_64 1:6.3.0-4.fc43 fedora 811.2 KiB gnat-srpm-macros noarch 7-1.fc43 updates 1.0 KiB gnome-srpm-macros noarch 1.0-1.fc43 updates 3.5 KiB gnulib-l10n noarch 20241231-1.fc43 fedora 655.0 KiB gnupg2 x86_64 2.4.9-5.fc43 updates 6.6 MiB gnupg2-dirmngr x86_64 2.4.9-5.fc43 updates 618.4 KiB gnupg2-gpg-agent x86_64 2.4.9-5.fc43 updates 671.4 KiB gnupg2-gpgconf x86_64 2.4.9-5.fc43 updates 250.0 KiB gnupg2-keyboxd x86_64 2.4.9-5.fc43 updates 201.4 KiB gnupg2-verify x86_64 2.4.9-5.fc43 updates 348.5 KiB gnutls x86_64 3.8.13-1.fc43 updates 3.8 MiB go-srpm-macros noarch 3.8.0-1.fc43 fedora 61.9 KiB gpgverify noarch 2.2-3.fc43 fedora 8.7 KiB ima-evm-utils-libs x86_64 1.6.2-6.fc43 fedora 60.7 KiB jansson x86_64 2.14-3.fc43 fedora 89.1 KiB java-srpm-macros noarch 1-7.fc43 fedora 870.0 B json-c x86_64 0.18-7.fc43 fedora 82.7 KiB kernel-srpm-macros noarch 1.0-27.fc43 fedora 1.9 KiB keyutils-libs x86_64 1.6.3-6.fc43 fedora 54.3 KiB krb5-libs x86_64 1.22.2-4.fc43 updates 2.3 MiB libacl x86_64 2.4.0-1.fc43 updates 39.9 KiB libarchive x86_64 3.8.4-1.fc43 updates 955.3 KiB libassuan x86_64 2.5.7-4.fc43 fedora 163.8 KiB libattr x86_64 2.6.0-1.fc43 updates 24.3 KiB libblkid x86_64 2.41.6-1.fc43 updates 262.3 KiB libbrotli x86_64 1.2.1-1.fc43 updates 865.0 KiB libcap x86_64 2.76-4.fc43 updates 209.1 KiB libcap-ng x86_64 0.9.6-1.fc43 updates 68.8 KiB libcom_err x86_64 1.47.3-2.fc43 fedora 63.1 KiB libcurl x86_64 8.15.0-12.fc43 updates 907.0 KiB libeconf x86_64 0.7.9-2.fc43 fedora 64.9 KiB libevent x86_64 2.1.13-1.fc43 updates 884.4 KiB libfdisk x86_64 2.41.6-1.fc43 updates 380.3 KiB libffi x86_64 3.5.2-1.fc43 updates 83.8 KiB libfsverity x86_64 1.6-3.fc43 fedora 28.5 KiB libgcc x86_64 15.3.1-1.fc43 updates 266.6 KiB libgcrypt x86_64 1.11.1-4.fc43 updates 1.6 MiB libgomp x86_64 15.3.1-1.fc43 updates 541.8 KiB libgpg-error x86_64 1.55-2.fc43 fedora 915.3 KiB libidn2 x86_64 2.3.8-2.fc43 fedora 552.5 KiB libksba x86_64 1.6.7-4.fc43 fedora 398.5 KiB liblastlog2 x86_64 2.41.6-1.fc43 updates 37.6 KiB libmount x86_64 2.41.6-1.fc43 updates 376.6 KiB libnghttp2 x86_64 1.66.0-3.fc43 updates 162.1 KiB libpfm x86_64 4.14.1-2.fc43 updates 2.4 MiB libpkgconf x86_64 2.3.0-3.fc43 fedora 78.1 KiB libpsl x86_64 0.21.5-6.fc43 fedora 76.4 KiB libselinux x86_64 3.9-5.fc43 fedora 193.1 KiB libsemanage x86_64 3.9-4.fc43 fedora 308.5 KiB libsepol x86_64 3.9-2.fc43 fedora 822.0 KiB libsmartcols x86_64 2.41.6-1.fc43 updates 180.3 KiB libssh x86_64 0.11.5-1.fc43 updates 573.1 KiB libssh-config noarch 0.11.5-1.fc43 updates 277.0 B libstdc++ x86_64 15.3.1-1.fc43 updates 2.8 MiB libtasn1 x86_64 4.21.0-1.fc43 updates 176.7 KiB libtool-ltdl x86_64 2.5.4-8.fc43 updates 70.1 KiB libunistring x86_64 1.1-10.fc43 fedora 1.7 MiB libusb1 x86_64 1.0.30-1.fc43 updates 176.0 KiB libuuid x86_64 2.41.6-1.fc43 updates 37.2 KiB libverto x86_64 0.3.2-11.fc43 fedora 25.4 KiB libxcrypt x86_64 4.5.2-1.fc43 updates 285.3 KiB libxml2 x86_64 2.12.10-5.fc43 fedora 1.7 MiB libzstd x86_64 1.5.7-2.fc43 fedora 799.9 KiB lua-libs x86_64 5.4.8-4.fc43 updates 281.9 KiB lua-srpm-macros noarch 1-16.fc43 fedora 1.3 KiB lz4-libs x86_64 1.10.0-3.fc43 fedora 161.4 KiB mpfr x86_64 4.2.2-2.fc43 fedora 832.8 KiB ncurses-base noarch 6.5-7.20250614.fc43 fedora 328.1 KiB ncurses-libs x86_64 6.5-7.20250614.fc43 fedora 946.3 KiB nettle x86_64 3.10.1-2.fc43 fedora 790.6 KiB npth x86_64 1.8-3.fc43 fedora 49.6 KiB ocaml-srpm-macros noarch 11-2.fc43 fedora 1.9 KiB openblas-srpm-macros noarch 2-20.fc43 fedora 112.0 B openldap x86_64 2.6.15-1.fc43 updates 659.2 KiB openssl-libs x86_64 1:3.5.9-1.fc43 updates 8.9 MiB p11-kit x86_64 0.26.5-1.fc43 updates 2.5 MiB p11-kit-trust x86_64 0.26.5-1.fc43 updates 466.3 KiB package-notes-srpm-macros noarch 0.20-1.fc43 updates 1.6 KiB pam-libs x86_64 1.7.1-5.fc43 updates 126.5 KiB pcre2 x86_64 10.47-1.fc43 updates 702.6 KiB pcre2-syntax noarch 10.47-1.fc43 updates 281.9 KiB perl-srpm-macros noarch 1-60.fc43 fedora 861.0 B pkgconf x86_64 2.3.0-3.fc43 fedora 88.5 KiB pkgconf-m4 noarch 2.3.0-3.fc43 fedora 14.4 KiB pkgconf-pkg-config x86_64 2.3.0-3.fc43 fedora 989.0 B popt x86_64 1.19-9.fc43 fedora 132.8 KiB publicsuffix-list-dafsa noarch 20260116-1.fc43 updates 70.4 KiB pyproject-srpm-macros noarch 1.24.0-1.fc43 updates 3.4 KiB python-srpm-macros noarch 3.14-5.fc43 fedora 51.5 KiB qt5-srpm-macros noarch 5.15.18-1.fc43 updates 500.0 B qt6-srpm-macros noarch 6.10.3-1.fc43 updates 472.0 B readline x86_64 8.3-2.fc43 fedora 511.7 KiB rpm x86_64 6.0.2-1.fc43 updates 3.1 MiB rpm-build-libs x86_64 6.0.2-1.fc43 updates 264.3 KiB rpm-libs x86_64 6.0.2-1.fc43 updates 933.5 KiB rpm-sequoia x86_64 1.10.3-1.fc43 updates 2.4 MiB rpm-sign-libs x86_64 6.0.2-1.fc43 updates 39.6 KiB rust-srpm-macros noarch 28.5-1.fc43 updates 5.5 KiB setup noarch 2.15.0-26.fc43 fedora 725.0 KiB sqlite-libs x86_64 3.50.2-3.fc43 updates 1.5 MiB systemd-libs x86_64 258.11-1.fc43 updates 2.3 MiB systemd-standalone-sysusers x86_64 258.11-1.fc43 updates 297.4 KiB tpm2-tss x86_64 4.1.3-8.fc43 fedora 1.6 MiB tree-sitter-srpm-macros noarch 0.4.2-1.fc43 fedora 8.3 KiB util-linux-core x86_64 2.41.6-1.fc43 updates 1.5 MiB xxhash-libs x86_64 0.8.4-2.fc43 updates 90.0 KiB xz-libs x86_64 1:5.8.1-4.fc43 updates 217.8 KiB zig-srpm-macros noarch 1-5.fc43 fedora 1.1 KiB zip x86_64 3.0-44.fc43 fedora 694.5 KiB zlib-ng-compat x86_64 2.3.3-2.fc43 updates 161.7 KiB zstd x86_64 1.5.7-2.fc43 fedora 1.7 MiB Installing groups: Buildsystem building group Transaction Summary: Installing: 173 packages Total size of inbound packages is 60 MiB. Need to download 60 MiB. After this operation, 204 MiB extra will be used (install 204 MiB, remove 0 B). [ 1/173] bzip2-0:1.0.8-21.fc43.x86_64 100% | 5.6 MiB/s | 51.6 KiB | 00m00s [ 2/173] diffutils-0:3.12-3.fc43.x86_6 100% | 95.8 MiB/s | 392.3 KiB | 00m00s [ 3/173] cpio-0:2.15-6.fc43.x86_64 100% | 17.9 MiB/s | 293.1 KiB | 00m00s [ 4/173] bash-0:5.3.0-2.fc43.x86_64 100% | 85.0 MiB/s | 1.9 MiB | 00m00s [ 5/173] findutils-1:4.10.0-6.fc43.x86 100% | 59.7 MiB/s | 550.0 KiB | 00m00s [ 6/173] grep-0:3.12-2.fc43.x86_64 100% | 41.7 MiB/s | 299.1 KiB | 00m00s [ 7/173] gzip-0:1.13-4.fc43.x86_64 100% | 55.4 MiB/s | 170.1 KiB | 00m00s [ 8/173] patch-0:2.8-2.fc43.x86_64 100% | 37.0 MiB/s | 113.8 KiB | 00m00s [ 9/173] sed-0:4.9-5.fc43.x86_64 100% | 77.4 MiB/s | 317.1 KiB | 00m00s [ 10/173] tar-2:1.35-6.fc43.x86_64 100% | 104.5 MiB/s | 856.4 KiB | 00m00s [ 11/173] shadow-utils-2:4.18.0-3.fc43. 100% | 116.6 MiB/s | 1.3 MiB | 00m00s [ 12/173] unzip-0:6.0-67.fc43.x86_64 100% | 16.3 MiB/s | 183.7 KiB | 00m00s [ 13/173] which-0:2.23-3.fc43.x86_64 100% | 8.2 MiB/s | 41.7 KiB | 00m00s [ 14/173] fedora-release-common-0:43-27 100% | 5.5 MiB/s | 22.6 KiB | 00m00s [ 15/173] coreutils-0:9.7-10.fc43.x86_6 100% | 142.2 MiB/s | 1.1 MiB | 00m00s [ 16/173] glibc-minimal-langpack-0:2.42 100% | 15.3 MiB/s | 47.1 KiB | 00m00s [ 17/173] gawk-0:5.3.2-2.fc43.x86_64 100% | 112.5 MiB/s | 1.1 MiB | 00m00s [ 18/173] info-0:7.2-7.fc43.x86_64 100% | 25.5 MiB/s | 182.7 KiB | 00m00s [ 19/173] redhat-rpm-config-0:343-14.fc 100% | 12.4 MiB/s | 76.1 KiB | 00m00s [ 20/173] rpm-build-0:6.0.2-1.fc43.x86_ 100% | 33.0 MiB/s | 135.3 KiB | 00m00s [ 21/173] xz-1:5.8.1-4.fc43.x86_64 100% | 111.9 MiB/s | 572.7 KiB | 00m00s [ 22/173] util-linux-0:2.41.6-1.fc43.x8 100% | 149.1 MiB/s | 1.2 MiB | 00m00s [ 23/173] ncurses-libs-0:6.5-7.20250614 100% | 65.0 MiB/s | 332.7 KiB | 00m00s [ 24/173] filesystem-0:3.18-50.fc43.x86 100% | 111.1 MiB/s | 1.3 MiB | 00m00s [ 25/173] bzip2-libs-0:1.0.8-21.fc43.x8 100% | 7.0 MiB/s | 43.1 KiB | 00m00s [ 26/173] libselinux-0:3.9-5.fc43.x86_6 100% | 19.1 MiB/s | 97.7 KiB | 00m00s [ 27/173] libeconf-0:0.7.9-2.fc43.x86_6 100% | 17.2 MiB/s | 35.2 KiB | 00m00s [ 28/173] ed-0:1.22.2-1.fc43.x86_64 100% | 20.4 MiB/s | 83.7 KiB | 00m00s [ 29/173] libsemanage-0:3.9-4.fc43.x86_ 100% | 40.2 MiB/s | 123.5 KiB | 00m00s [ 30/173] setup-0:2.15.0-26.fc43.noarch 100% | 51.2 MiB/s | 157.3 KiB | 00m00s [ 31/173] gmp-1:6.3.0-4.fc43.x86_64 100% | 78.0 MiB/s | 319.3 KiB | 00m00s [ 32/173] mpfr-0:4.2.2-2.fc43.x86_64 100% | 67.8 MiB/s | 347.0 KiB | 00m00s [ 33/173] readline-0:8.3-2.fc43.x86_64 100% | 27.4 MiB/s | 224.6 KiB | 00m00s [ 34/173] coreutils-common-0:9.7-10.fc4 100% | 150.0 MiB/s | 2.1 MiB | 00m00s [ 35/173] glibc-common-0:2.42-17.fc43.x 100% | 36.2 MiB/s | 333.9 KiB | 00m00s [ 36/173] ansible-srpm-macros-0:1-18.1. 100% | 4.9 MiB/s | 19.9 KiB | 00m00s [ 37/173] dwz-0:0.16-2.fc43.x86_64 100% | 44.1 MiB/s | 135.5 KiB | 00m00s [ 38/173] efi-srpm-macros-0:6-4.fc43.no 100% | 7.3 MiB/s | 22.4 KiB | 00m00s [ 39/173] filesystem-srpm-macros-0:3.18 100% | 8.6 MiB/s | 26.4 KiB | 00m00s [ 40/173] fonts-srpm-macros-1:2.0.5-23. 100% | 8.8 MiB/s | 27.2 KiB | 00m00s [ 41/173] fpc-srpm-macros-0:1.3-15.fc43 100% | 2.6 MiB/s | 7.9 KiB | 00m00s [ 42/173] forge-srpm-macros-0:0.4.0-3.f 100% | 6.5 MiB/s | 20.1 KiB | 00m00s [ 43/173] gap-srpm-macros-0:2-1.fc43.no 100% | 4.4 MiB/s | 9.0 KiB | 00m00s [ 44/173] ghc-srpm-macros-0:1.9.2-3.fc4 100% | 2.8 MiB/s | 8.7 KiB | 00m00s [ 45/173] go-srpm-macros-0:3.8.0-1.fc43 100% | 9.2 MiB/s | 28.3 KiB | 00m00s [ 46/173] kernel-srpm-macros-0:1.0-27.f 100% | 4.4 MiB/s | 8.9 KiB | 00m00s [ 47/173] java-srpm-macros-0:1-7.fc43.n 100% | 2.6 MiB/s | 7.9 KiB | 00m00s [ 48/173] lua-srpm-macros-0:1-16.fc43.n 100% | 2.9 MiB/s | 8.8 KiB | 00m00s [ 49/173] openblas-srpm-macros-0:2-20.f 100% | 2.5 MiB/s | 7.6 KiB | 00m00s [ 50/173] ocaml-srpm-macros-0:11-2.fc43 100% | 1.8 MiB/s | 9.3 KiB | 00m00s [ 51/173] perl-srpm-macros-0:1-60.fc43. 100% | 1.6 MiB/s | 8.3 KiB | 00m00s [ 52/173] python-srpm-macros-0:3.14-5.f 100% | 5.7 MiB/s | 23.4 KiB | 00m00s [ 53/173] zig-srpm-macros-0:1-5.fc43.no 100% | 4.1 MiB/s | 8.4 KiB | 00m00s [ 54/173] tree-sitter-srpm-macros-0:0.4 100% | 4.3 MiB/s | 13.4 KiB | 00m00s [ 55/173] zip-0:3.0-44.fc43.x86_64 100% | 51.1 MiB/s | 261.6 KiB | 00m00s [ 56/173] cmake-srpm-macros-0:3.31.11-1 100% | 2.4 MiB/s | 9.9 KiB | 00m00s [ 57/173] gnome-srpm-macros-0:1.0-1.fc4 100% | 2.1 MiB/s | 8.6 KiB | 00m00s [ 58/173] debugedit-0:5.2-3.fc43.x86_64 100% | 16.7 MiB/s | 85.6 KiB | 00m00s [ 59/173] popt-0:1.19-9.fc43.x86_64 100% | 12.8 MiB/s | 65.7 KiB | 00m00s [ 60/173] zstd-0:1.5.7-2.fc43.x86_64 100% | 79.1 MiB/s | 485.9 KiB | 00m00s [ 61/173] util-linux-core-0:2.41.6-1.fc 100% | 107.8 MiB/s | 551.9 KiB | 00m00s [ 62/173] rpm-0:6.0.2-1.fc43.x86_64 100% | 80.1 MiB/s | 574.0 KiB | 00m00s [ 63/173] xz-libs-1:5.8.1-4.fc43.x86_64 100% | 18.4 MiB/s | 112.8 KiB | 00m00s [ 64/173] ncurses-base-0:6.5-7.20250614 100% | 28.7 MiB/s | 88.2 KiB | 00m00s [ 65/173] libsepol-0:3.9-2.fc43.x86_64 100% | 84.3 MiB/s | 345.4 KiB | 00m00s [ 66/173] gnulib-l10n-0:20241231-1.fc43 100% | 29.3 MiB/s | 150.2 KiB | 00m00s [ 67/173] lz4-libs-0:1.10.0-3.fc43.x86_ 100% | 19.0 MiB/s | 78.0 KiB | 00m00s [ 68/173] rpm-libs-0:6.0.2-1.fc43.x86_6 100% | 77.8 MiB/s | 398.4 KiB | 00m00s [ 69/173] glibc-0:2.42-17.fc43.x86_64 100% | 122.7 MiB/s | 2.2 MiB | 00m00s [ 70/173] libzstd-0:1.5.7-2.fc43.x86_64 100% | 23.6 MiB/s | 314.6 KiB | 00m00s [ 71/173] glibc-gconv-extra-0:2.42-17.f 100% | 83.6 MiB/s | 1.6 MiB | 00m00s [ 72/173] ima-evm-utils-libs-0:1.6.2-6. 100% | 837.8 KiB/s | 29.3 KiB | 00m00s [ 73/173] rpm-sign-libs-0:6.0.2-1.fc43. 100% | 688.7 KiB/s | 25.5 KiB | 00m00s [ 74/173] rpm-build-libs-0:6.0.2-1.fc43 100% | 3.2 MiB/s | 124.1 KiB | 00m00s [ 75/173] libfsverity-0:1.6-3.fc43.x86_ 100% | 3.6 MiB/s | 18.6 KiB | 00m00s [ 76/173] json-c-0:0.18-7.fc43.x86_64 100% | 11.0 MiB/s | 45.0 KiB | 00m00s [ 77/173] tpm2-tss-0:4.1.3-8.fc43.x86_6 100% | 69.3 MiB/s | 425.9 KiB | 00m00s [ 78/173] libblkid-0:2.41.6-1.fc43.x86_ 100% | 30.3 MiB/s | 124.1 KiB | 00m00s [ 79/173] libuuid-0:2.41.6-1.fc43.x86_6 100% | 6.6 MiB/s | 26.9 KiB | 00m00s [ 80/173] libmount-0:2.41.6-1.fc43.x86_ 100% | 26.8 MiB/s | 164.5 KiB | 00m00s [ 81/173] libgcc-0:15.3.1-1.fc43.x86_64 100% | 34.9 MiB/s | 142.9 KiB | 00m00s [ 82/173] libsmartcols-0:2.41.6-1.fc43. 100% | 16.5 MiB/s | 84.6 KiB | 00m00s [ 83/173] libxcrypt-0:4.5.2-1.fc43.x86_ 100% | 25.0 MiB/s | 128.1 KiB | 00m00s [ 84/173] audit-libs-0:4.2.1-1.fc43.x86 100% | 34.1 MiB/s | 139.6 KiB | 00m00s [ 85/173] systemd-libs-0:258.11-1.fc43. 100% | 116.1 MiB/s | 832.0 KiB | 00m00s [ 86/173] libcap-ng-0:0.9.6-1.fc43.x86_ 100% | 8.4 MiB/s | 34.3 KiB | 00m00s [ 87/173] libfdisk-0:2.41.6-1.fc43.x86_ 100% | 39.6 MiB/s | 162.3 KiB | 00m00s [ 88/173] liblastlog2-0:2.41.6-1.fc43.x 100% | 7.9 MiB/s | 24.3 KiB | 00m00s [ 89/173] pam-libs-0:1.7.1-5.fc43.x86_6 100% | 18.4 MiB/s | 56.4 KiB | 00m00s [ 90/173] zlib-ng-compat-0:2.3.3-2.fc43 100% | 21.7 MiB/s | 88.7 KiB | 00m00s [ 91/173] libcap-0:2.76-4.fc43.x86_64 100% | 16.8 MiB/s | 86.1 KiB | 00m00s [ 92/173] gpgverify-0:2.2-3.fc43.noarch 100% | 2.7 MiB/s | 11.1 KiB | 00m00s [ 93/173] libassuan-0:2.5.7-4.fc43.x86_ 100% | 16.5 MiB/s | 67.4 KiB | 00m00s [ 94/173] gnupg2-0:2.4.9-5.fc43.x86_64 100% | 148.8 MiB/s | 1.6 MiB | 00m00s [ 95/173] npth-0:1.8-3.fc43.x86_64 100% | 8.4 MiB/s | 25.7 KiB | 00m00s [ 96/173] libgpg-error-0:1.55-2.fc43.x8 100% | 39.8 MiB/s | 244.3 KiB | 00m00s [ 97/173] gnupg2-dirmngr-0:2.4.9-5.fc43 100% | 53.7 MiB/s | 275.0 KiB | 00m00s [ 98/173] gnupg2-gpg-agent-0:2.4.9-5.fc 100% | 66.7 MiB/s | 273.4 KiB | 00m00s [ 99/173] gnupg2-gpgconf-0:2.4.9-5.fc43 100% | 28.2 MiB/s | 115.3 KiB | 00m00s [100/173] gnupg2-keyboxd-0:2.4.9-5.fc43 100% | 23.1 MiB/s | 94.7 KiB | 00m00s [101/173] gnupg2-verify-0:2.4.9-5.fc43. 100% | 55.8 MiB/s | 171.6 KiB | 00m00s [102/173] libksba-0:1.6.7-4.fc43.x86_64 100% | 39.2 MiB/s | 160.4 KiB | 00m00s [103/173] libacl-0:2.4.0-1.fc43.x86_64 100% | 12.7 MiB/s | 26.1 KiB | 00m00s [104/173] lua-libs-0:5.4.8-4.fc43.x86_6 100% | 32.5 MiB/s | 133.1 KiB | 00m00s [105/173] libstdc++-0:15.3.1-1.fc43.x86 100% | 151.5 MiB/s | 931.1 KiB | 00m00s [106/173] rpm-sequoia-0:1.10.3-1.fc43.x 100% | 114.8 MiB/s | 940.6 KiB | 00m00s [107/173] sqlite-libs-0:3.50.2-3.fc43.x 100% | 105.9 MiB/s | 758.9 KiB | 00m00s [108/173] elfutils-libelf-0:0.197-1.fc4 100% | 42.7 MiB/s | 262.6 KiB | 00m00s [109/173] elfutils-libs-0:0.197-1.fc43. 100% | 66.7 MiB/s | 273.0 KiB | 00m00s [110/173] elfutils-debuginfod-client-0: 100% | 15.1 MiB/s | 46.3 KiB | 00m00s [111/173] elfutils-0:0.197-1.fc43.x86_6 100% | 128.1 MiB/s | 655.7 KiB | 00m00s [112/173] file-0:5.46-9.fc43.x86_64 100% | 15.8 MiB/s | 48.5 KiB | 00m00s [113/173] file-libs-0:5.46-9.fc43.x86_6 100% | 138.3 MiB/s | 849.9 KiB | 00m00s [114/173] libgomp-0:15.3.1-1.fc43.x86_6 100% | 74.9 MiB/s | 383.6 KiB | 00m00s [115/173] jansson-0:2.14-3.fc43.x86_64 100% | 14.7 MiB/s | 45.3 KiB | 00m00s [116/173] libarchive-0:3.8.4-1.fc43.x86 100% | 51.6 MiB/s | 422.6 KiB | 00m00s [117/173] libxml2-0:2.12.10-5.fc43.x86_ 100% | 112.7 MiB/s | 692.7 KiB | 00m00s [118/173] pkgconf-pkg-config-0:2.3.0-3. 100% | 2.3 MiB/s | 9.6 KiB | 00m00s [119/173] pkgconf-0:2.3.0-3.fc43.x86_64 100% | 10.9 MiB/s | 44.6 KiB | 00m00s [120/173] pkgconf-m4-0:2.3.0-3.fc43.noa 100% | 4.5 MiB/s | 13.9 KiB | 00m00s [121/173] libpkgconf-0:2.3.0-3.fc43.x86 100% | 7.4 MiB/s | 37.9 KiB | 00m00s [122/173] binutils-0:2.45.1-5.fc43.x86_ 100% | 185.5 MiB/s | 5.9 MiB | 00m00s [123/173] build-reproducibility-srpm-ma 100% | 1.5 MiB/s | 11.9 KiB | 00m00s [124/173] curl-0:8.15.0-12.fc43.x86_64 100% | 20.1 MiB/s | 226.8 KiB | 00m00s [125/173] gnat-srpm-macros-0:7-1.fc43.n 100% | 721.4 KiB/s | 8.7 KiB | 00m00s [126/173] package-notes-srpm-macros-0:0 100% | 821.1 KiB/s | 9.9 KiB | 00m00s [127/173] add-determinism-0:0.6.0-3.fc4 100% | 43.6 MiB/s | 893.7 KiB | 00m00s [128/173] pyproject-srpm-macros-0:1.24. 100% | 2.1 MiB/s | 15.4 KiB | 00m00s [129/173] qt5-srpm-macros-0:5.15.18-1.f 100% | 1.2 MiB/s | 8.6 KiB | 00m00s [130/173] qt6-srpm-macros-0:6.10.3-1.fc 100% | 4.5 MiB/s | 9.1 KiB | 00m00s [131/173] rust-srpm-macros-0:28.5-1.fc4 100% | 5.5 MiB/s | 11.2 KiB | 00m00s [132/173] libgcrypt-0:1.11.1-4.fc43.x86 100% | 58.2 MiB/s | 596.0 KiB | 00m00s [133/173] gnutls-0:3.8.13-1.fc43.x86_64 100% | 92.6 MiB/s | 1.4 MiB | 00m00s [134/173] openssl-libs-1:3.5.9-1.fc43.x 100% | 125.2 MiB/s | 2.6 MiB | 00m00s [135/173] libidn2-0:2.3.8-2.fc43.x86_64 100% | 21.3 MiB/s | 174.9 KiB | 00m00s [136/173] libunistring-0:1.1-10.fc43.x8 100% | 106.0 MiB/s | 542.9 KiB | 00m00s [137/173] nettle-0:3.10.1-2.fc43.x86_64 100% | 69.0 MiB/s | 424.2 KiB | 00m00s [138/173] openldap-0:2.6.15-1.fc43.x86_ 100% | 36.2 MiB/s | 259.7 KiB | 00m00s [139/173] cyrus-sasl-lib-0:2.1.28-33.fc 100% | 109.9 MiB/s | 787.9 KiB | 00m00s [140/173] gdbm-libs-1:1.23-10.fc43.x86_ 100% | 13.9 MiB/s | 56.8 KiB | 00m00s [141/173] fedora-repos-0:43-2.noarch 100% | 2.2 MiB/s | 8.9 KiB | 00m00s [142/173] elfutils-default-yama-scope-0 100% | 5.6 MiB/s | 11.5 KiB | 00m00s [143/173] fedora-gpg-keys-0:43-2.noarch 100% | 45.0 MiB/s | 184.2 KiB | 00m00s [144/173] libpfm-0:4.14.1-2.fc43.x86_64 100% | 67.2 MiB/s | 275.3 KiB | 00m00s [145/173] libattr-0:2.6.0-1.fc43.x86_64 100% | 8.7 MiB/s | 17.9 KiB | 00m00s [146/173] alternatives-0:1.33-3.fc43.x8 100% | 6.6 MiB/s | 40.6 KiB | 00m00s [147/173] libusb1-0:1.0.30-1.fc43.x86_6 100% | 13.1 MiB/s | 80.5 KiB | 00m00s [148/173] pcre2-0:10.47-1.fc43.x86_64 100% | 37.3 MiB/s | 267.2 KiB | 00m00s [149/173] pcre2-syntax-0:10.47-1.fc43.n 100% | 40.2 MiB/s | 164.7 KiB | 00m00s [150/173] ca-certificates-0:2026.2.92_v 100% | 136.7 MiB/s | 980.2 KiB | 00m00s [151/173] crypto-policies-0:20251125-1. 100% | 15.9 MiB/s | 97.8 KiB | 00m00s [152/173] libevent-0:2.1.13-1.fc43.x86_ 100% | 50.7 MiB/s | 259.5 KiB | 00m00s [153/173] libtool-ltdl-0:2.5.4-8.fc43.x 100% | 17.7 MiB/s | 36.2 KiB | 00m00s [154/173] libtasn1-0:4.21.0-1.fc43.x86_ 100% | 24.3 MiB/s | 74.5 KiB | 00m00s [155/173] p11-kit-trust-0:0.26.5-1.fc43 100% | 27.5 MiB/s | 140.6 KiB | 00m00s [156/173] p11-kit-0:0.26.5-1.fc43.x86_6 100% | 66.3 MiB/s | 542.8 KiB | 00m00s [157/173] libffi-0:3.5.2-1.fc43.x86_64 100% | 6.7 MiB/s | 41.1 KiB | 00m00s [158/173] systemd-standalone-sysusers-0 100% | 24.3 MiB/s | 149.4 KiB | 00m00s [159/173] xxhash-libs-0:0.8.4-2.fc43.x8 100% | 7.5 MiB/s | 38.6 KiB | 00m00s [160/173] fedora-release-0:43-27.noarch 100% | 3.8 MiB/s | 11.5 KiB | 00m00s [161/173] fedora-release-identity-basic 100% | 4.0 MiB/s | 12.3 KiB | 00m00s [162/173] libcurl-0:8.15.0-12.fc43.x86_ 100% | 78.9 MiB/s | 403.9 KiB | 00m00s [163/173] libpsl-0:0.21.5-6.fc43.x86_64 100% | 12.7 MiB/s | 65.0 KiB | 00m00s [164/173] gdb-minimal-0:18.1-1.fc43.x86 100% | 196.2 MiB/s | 4.5 MiB | 00m00s [165/173] libssh-config-0:0.11.5-1.fc43 100% | 1.1 MiB/s | 8.9 KiB | 00m00s [166/173] libssh-0:0.11.5-1.fc43.x86_64 100% | 28.6 MiB/s | 234.6 KiB | 00m00s [167/173] publicsuffix-list-dafsa-0:202 100% | 14.7 MiB/s | 60.3 KiB | 00m00s [168/173] keyutils-libs-0:1.6.3-6.fc43. 100% | 7.7 MiB/s | 31.4 KiB | 00m00s [169/173] krb5-libs-0:1.22.2-4.fc43.x86 100% | 94.0 MiB/s | 770.4 KiB | 00m00s [170/173] libcom_err-0:1.47.3-2.fc43.x8 100% | 6.5 MiB/s | 26.8 KiB | 00m00s [171/173] libverto-0:0.3.2-11.fc43.x86_ 100% | 5.0 MiB/s | 20.7 KiB | 00m00s [172/173] libbrotli-0:1.2.1-1.fc43.x86_ 100% | 85.3 MiB/s | 349.5 KiB | 00m00s [173/173] libnghttp2-0:1.66.0-3.fc43.x8 100% | 17.3 MiB/s | 71.0 KiB | 00m00s -------------------------------------------------------------------------------- [173/173] Total 100% | 141.8 MiB/s | 59.9 MiB | 00m00s Running transaction Importing OpenPGP key 0x31645531: UserID : "Fedora (43) " Fingerprint: C6E7F081CF80E13146676E88829B606631645531 From : file:///usr/share/distribution-gpg-keys/fedora/RPM-GPG-KEY-fedora-43-primary The key was successfully imported. [ 1/175] Verify package files 100% | 789.0 B/s | 173.0 B | 00m00s [ 2/175] Prepare transaction 100% | 4.3 KiB/s | 173.0 B | 00m00s [ 3/175] Installing libgcc-0:15.3.1-1. 100% | 262.0 MiB/s | 268.3 KiB | 00m00s [ 4/175] Installing publicsuffix-list- 100% | 0.0 B/s | 71.1 KiB | 00m00s [ 5/175] Installing libssh-config-0:0. 100% | 0.0 B/s | 816.0 B | 00m00s [ 6/175] Installing fedora-release-ide 100% | 867.2 KiB/s | 888.0 B | 00m00s [ 7/175] Installing fedora-gpg-keys-0: 100% | 57.8 MiB/s | 355.0 KiB | 00m00s [ 8/175] Installing fedora-repos-0:43- 100% | 0.0 B/s | 5.7 KiB | 00m00s [ 9/175] Installing fedora-release-com 100% | 24.3 MiB/s | 24.8 KiB | 00m00s [ 10/175] Installing fedora-release-0:4 100% | 15.1 KiB/s | 124.0 B | 00m00s >>> Running sysusers scriptlet: setup-0:2.15.0-26.fc43.noarch >>> Finished sysusers scriptlet: setup-0:2.15.0-26.fc43.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/175] Installing setup-0:2.15.0-26. 100% | 51.0 MiB/s | 730.6 KiB | 00m00s >>> [RPM] /etc/hosts created as /etc/hosts.rpmnew [ 12/175] Installing filesystem-0:3.18- 100% | 3.1 MiB/s | 212.8 KiB | 00m00s [ 13/175] Installing pcre2-syntax-0:10. 100% | 277.7 MiB/s | 284.3 KiB | 00m00s [ 14/175] Installing rust-srpm-macros-0 100% | 0.0 B/s | 6.4 KiB | 00m00s [ 15/175] Installing qt6-srpm-macros-0: 100% | 0.0 B/s | 748.0 B | 00m00s [ 16/175] Installing qt5-srpm-macros-0: 100% | 0.0 B/s | 776.0 B | 00m00s [ 17/175] Installing package-notes-srpm 100% | 0.0 B/s | 2.1 KiB | 00m00s [ 18/175] Installing gnat-srpm-macros-0 100% | 0.0 B/s | 1.3 KiB | 00m00s [ 19/175] Installing pkgconf-m4-0:2.3.0 100% | 0.0 B/s | 14.8 KiB | 00m00s [ 20/175] Installing gnulib-l10n-0:2024 100% | 215.5 MiB/s | 661.9 KiB | 00m00s [ 21/175] Installing coreutils-common-0 100% | 418.2 MiB/s | 11.3 MiB | 00m00s [ 22/175] Installing ncurses-base-0:6.5 100% | 86.3 MiB/s | 353.5 KiB | 00m00s [ 23/175] Installing bash-0:5.3.0-2.fc4 100% | 281.0 MiB/s | 8.4 MiB | 00m00s [ 24/175] Installing glibc-common-0:2.4 100% | 63.7 MiB/s | 1.0 MiB | 00m00s [ 25/175] Installing glibc-gconv-extra- 100% | 303.3 MiB/s | 7.3 MiB | 00m00s [ 26/175] Installing glibc-0:2.42-17.fc 100% | 191.2 MiB/s | 6.7 MiB | 00m00s [ 27/175] Installing ncurses-libs-0:6.5 100% | 310.1 MiB/s | 952.8 KiB | 00m00s [ 28/175] Installing glibc-minimal-lang 100% | 0.0 B/s | 124.0 B | 00m00s [ 29/175] Installing zlib-ng-compat-0:2 100% | 158.7 MiB/s | 162.6 KiB | 00m00s [ 30/175] Installing bzip2-libs-0:1.0.8 100% | 79.8 MiB/s | 81.7 KiB | 00m00s [ 31/175] Installing libgpg-error-0:1.5 100% | 64.3 MiB/s | 921.1 KiB | 00m00s [ 32/175] Installing libstdc++-0:15.3.1 100% | 407.0 MiB/s | 2.8 MiB | 00m00s [ 33/175] Installing xz-libs-1:5.8.1-4. 100% | 213.8 MiB/s | 218.9 KiB | 00m00s [ 34/175] Installing libassuan-0:2.5.7- 100% | 161.7 MiB/s | 165.6 KiB | 00m00s [ 35/175] Installing libgcrypt-0:1.11.1 100% | 393.7 MiB/s | 1.6 MiB | 00m00s [ 36/175] Installing readline-0:8.3-2.f 100% | 250.9 MiB/s | 513.9 KiB | 00m00s [ 37/175] Installing gmp-1:6.3.0-4.fc43 100% | 397.2 MiB/s | 813.5 KiB | 00m00s [ 38/175] Installing libuuid-0:2.41.6-1 100% | 0.0 B/s | 38.4 KiB | 00m00s [ 39/175] Installing libacl-0:2.4.0-1.f 100% | 0.0 B/s | 40.7 KiB | 00m00s [ 40/175] Installing popt-0:1.19-9.fc43 100% | 68.1 MiB/s | 139.4 KiB | 00m00s [ 41/175] Installing libzstd-0:1.5.7-2. 100% | 391.2 MiB/s | 801.1 KiB | 00m00s [ 42/175] Installing elfutils-libelf-0: 100% | 542.8 MiB/s | 1.6 MiB | 00m00s [ 43/175] Installing npth-0:1.8-3.fc43. 100% | 0.0 B/s | 50.7 KiB | 00m00s [ 44/175] Installing libblkid-0:2.41.6- 100% | 257.3 MiB/s | 263.5 KiB | 00m00s [ 45/175] Installing libxcrypt-0:4.5.2- 100% | 281.3 MiB/s | 288.0 KiB | 00m00s [ 46/175] Installing sqlite-libs-0:3.50 100% | 379.1 MiB/s | 1.5 MiB | 00m00s [ 47/175] Installing gnupg2-gpgconf-0:2 100% | 20.5 MiB/s | 252.1 KiB | 00m00s [ 48/175] Installing json-c-0:0.18-7.fc 100% | 0.0 B/s | 84.0 KiB | 00m00s [ 49/175] Installing libunistring-0:1.1 100% | 345.3 MiB/s | 1.7 MiB | 00m00s [ 50/175] Installing libidn2-0:2.3.8-2. 100% | 181.9 MiB/s | 558.7 KiB | 00m00s [ 51/175] Installing libtasn1-0:4.21.0- 100% | 21.8 MiB/s | 178.6 KiB | 00m00s [ 52/175] Installing crypto-policies-0: 100% | 42.0 MiB/s | 172.2 KiB | 00m00s [ 53/175] Installing gnupg2-verify-0:2. 100% | 26.3 MiB/s | 349.9 KiB | 00m00s [ 54/175] Installing dwz-0:0.16-2.fc43. 100% | 23.5 MiB/s | 288.5 KiB | 00m00s [ 55/175] Installing mpfr-0:4.2.2-2.fc4 100% | 271.6 MiB/s | 834.4 KiB | 00m00s [ 56/175] Installing gawk-0:5.3.2-2.fc4 100% | 106.8 MiB/s | 1.8 MiB | 00m00s [ 57/175] Installing libksba-0:1.6.7-4. 100% | 391.7 MiB/s | 401.1 KiB | 00m00s [ 58/175] Installing unzip-0:6.0-67.fc4 100% | 31.7 MiB/s | 389.8 KiB | 00m00s [ 59/175] Installing file-libs-0:5.46-9 100% | 697.7 MiB/s | 11.9 MiB | 00m00s [ 60/175] Installing file-0:5.46-9.fc43 100% | 8.3 MiB/s | 101.7 KiB | 00m00s [ 61/175] Installing libeconf-0:0.7.9-2 100% | 65.0 MiB/s | 66.5 KiB | 00m00s [ 62/175] Installing libsepol-0:3.9-2.f 100% | 401.8 MiB/s | 822.9 KiB | 00m00s [ 63/175] Installing lz4-libs-0:1.10.0- 100% | 158.6 MiB/s | 162.5 KiB | 00m00s [ 64/175] Installing libsmartcols-0:2.4 100% | 177.2 MiB/s | 181.5 KiB | 00m00s [ 65/175] Installing libcap-ng-0:0.9.6- 100% | 69.0 MiB/s | 70.6 KiB | 00m00s [ 66/175] Installing audit-libs-0:4.2.1 100% | 375.9 MiB/s | 384.9 KiB | 00m00s [ 67/175] Installing pam-libs-0:1.7.1-5 100% | 125.7 MiB/s | 128.8 KiB | 00m00s [ 68/175] Installing libcap-0:2.76-4.fc 100% | 17.4 MiB/s | 214.3 KiB | 00m00s [ 69/175] Installing systemd-libs-0:258 100% | 391.3 MiB/s | 2.3 MiB | 00m00s [ 70/175] Installing lua-libs-0:5.4.8-4 100% | 276.7 MiB/s | 283.3 KiB | 00m00s [ 71/175] Installing libattr-0:2.6.0-1. 100% | 0.0 B/s | 25.2 KiB | 00m00s [ 72/175] Installing alternatives-0:1.3 100% | 5.7 MiB/s | 63.8 KiB | 00m00s [ 73/175] Installing pcre2-0:10.47-1.fc 100% | 343.8 MiB/s | 704.1 KiB | 00m00s [ 74/175] Installing libselinux-0:3.9-5 100% | 189.8 MiB/s | 194.4 KiB | 00m00s [ 75/175] Installing grep-0:3.12-2.fc43 100% | 66.8 MiB/s | 1.0 MiB | 00m00s [ 76/175] Installing findutils-1:4.10.0 100% | 116.1 MiB/s | 1.9 MiB | 00m00s [ 77/175] Installing sed-0:4.9-5.fc43.x 100% | 60.4 MiB/s | 865.5 KiB | 00m00s [ 78/175] Installing xz-1:5.8.1-4.fc43. 100% | 83.2 MiB/s | 1.3 MiB | 00m00s [ 79/175] Installing libmount-0:2.41.6- 100% | 368.9 MiB/s | 377.8 KiB | 00m00s [ 80/175] Installing libffi-0:3.5.2-1.f 100% | 83.2 MiB/s | 85.2 KiB | 00m00s [ 81/175] Installing p11-kit-0:0.26.5-1 100% | 141.4 MiB/s | 2.5 MiB | 00m00s [ 82/175] Installing p11-kit-trust-0:0. 100% | 22.8 MiB/s | 467.9 KiB | 00m00s [ 83/175] Installing openssl-libs-1:3.5 100% | 406.5 MiB/s | 8.9 MiB | 00m00s [ 84/175] Installing coreutils-0:9.7-10 100% | 169.7 MiB/s | 5.4 MiB | 00m00s [ 85/175] Installing ca-certificates-0: 100% | 2.4 MiB/s | 2.5 MiB | 00m01s [ 86/175] Installing gzip-0:1.13-4.fc43 100% | 29.6 MiB/s | 394.4 KiB | 00m00s [ 87/175] Installing libfsverity-0:1.6- 100% | 0.0 B/s | 29.5 KiB | 00m00s [ 88/175] Installing rpm-sequoia-0:1.10 100% | 350.2 MiB/s | 2.5 MiB | 00m00s [ 89/175] Installing libevent-0:2.1.13- 100% | 289.1 MiB/s | 888.2 KiB | 00m00s [ 90/175] Installing util-linux-core-0: 100% | 86.8 MiB/s | 1.5 MiB | 00m00s [ 91/175] Installing tar-2:1.35-6.fc43. 100% | 155.7 MiB/s | 3.0 MiB | 00m00s [ 92/175] Installing libsemanage-0:3.9- 100% | 303.0 MiB/s | 310.2 KiB | 00m00s [ 93/175] Installing systemd-standalone 100% | 24.3 MiB/s | 298.1 KiB | 00m00s [ 94/175] Installing rpm-libs-0:6.0.2-1 100% | 304.4 MiB/s | 935.1 KiB | 00m00s [ 95/175] Installing libusb1-0:1.0.30-1 100% | 21.7 MiB/s | 177.7 KiB | 00m00s >>> Running sysusers scriptlet: tpm2-tss-0:4.1.3-8.fc43.x86_64 >>> Finished sysusers scriptlet: tpm2-tss-0:4.1.3-8.fc43.x86_64 >>> Scriptlet output: >>> Creating group 'tss' with GID 59. >>> Creating user 'tss' (Account used for TPM access) with UID 59 and GID 59. >>> [ 96/175] Installing tpm2-tss-0:4.1.3-8 100% | 314.4 MiB/s | 1.6 MiB | 00m00s [ 97/175] Installing ima-evm-utils-libs 100% | 60.5 MiB/s | 62.0 KiB | 00m00s [ 98/175] Installing gnupg2-gpg-agent-0 100% | 31.4 MiB/s | 675.4 KiB | 00m00s [ 99/175] Installing liblastlog2-0:2.41 100% | 6.5 MiB/s | 39.8 KiB | 00m00s [100/175] Installing zstd-0:1.5.7-2.fc4 100% | 106.9 MiB/s | 1.7 MiB | 00m00s [101/175] Installing zip-0:3.0-44.fc43. 100% | 52.5 MiB/s | 698.4 KiB | 00m00s [102/175] Installing gnupg2-keyboxd-0:2 100% | 28.3 MiB/s | 202.7 KiB | 00m00s [103/175] Installing libpsl-0:0.21.5-6. 100% | 75.7 MiB/s | 77.5 KiB | 00m00s [104/175] Installing libfdisk-0:2.41.6- 100% | 372.5 MiB/s | 381.4 KiB | 00m00s [105/175] Installing nettle-0:3.10.1-2. 100% | 258.4 MiB/s | 793.7 KiB | 00m00s [106/175] Installing gnutls-0:3.8.13-1. 100% | 376.7 MiB/s | 3.8 MiB | 00m00s [107/175] Installing libxml2-0:2.12.10- 100% | 106.5 MiB/s | 1.7 MiB | 00m00s [108/175] Installing libarchive-0:3.8.4 100% | 311.6 MiB/s | 957.2 KiB | 00m00s [109/175] Installing bzip2-0:1.0.8-21.f 100% | 8.1 MiB/s | 99.8 KiB | 00m00s [110/175] Installing add-determinism-0: 100% | 143.9 MiB/s | 2.3 MiB | 00m00s [111/175] Installing build-reproducibil 100% | 0.0 B/s | 1.0 KiB | 00m00s [112/175] Installing cpio-0:2.15-6.fc43 100% | 73.3 MiB/s | 1.1 MiB | 00m00s [113/175] Installing diffutils-0:3.12-3 100% | 97.6 MiB/s | 1.6 MiB | 00m00s [114/175] Installing ed-0:1.22.2-1.fc43 100% | 12.2 MiB/s | 150.4 KiB | 00m00s [115/175] Installing patch-0:2.8-2.fc43 100% | 18.3 MiB/s | 224.3 KiB | 00m00s [116/175] Installing libgomp-0:15.3.1-1 100% | 265.2 MiB/s | 543.2 KiB | 00m00s [117/175] Installing jansson-0:2.14-3.f 100% | 88.3 MiB/s | 90.5 KiB | 00m00s [118/175] Installing libpkgconf-0:2.3.0 100% | 0.0 B/s | 79.2 KiB | 00m00s [119/175] Installing pkgconf-0:2.3.0-3. 100% | 7.4 MiB/s | 91.0 KiB | 00m00s [120/175] Installing pkgconf-pkg-config 100% | 161.2 KiB/s | 1.8 KiB | 00m00s [121/175] Installing gdbm-libs-1:1.23-1 100% | 128.5 MiB/s | 131.6 KiB | 00m00s [122/175] Installing cyrus-sasl-lib-0:2 100% | 143.5 MiB/s | 2.3 MiB | 00m00s [123/175] Installing libpfm-0:4.14.1-2. 100% | 592.1 MiB/s | 2.4 MiB | 00m00s [124/175] Installing libtool-ltdl-0:2.5 100% | 69.6 MiB/s | 71.2 KiB | 00m00s [125/175] Installing openldap-0:2.6.15- 100% | 323.7 MiB/s | 663.0 KiB | 00m00s [126/175] Installing gnupg2-dirmngr-0:2 100% | 30.3 MiB/s | 621.1 KiB | 00m00s [127/175] Installing gnupg2-0:2.4.9-5.f 100% | 234.5 MiB/s | 6.6 MiB | 00m00s [128/175] Installing rpm-sign-libs-0:6. 100% | 0.0 B/s | 40.5 KiB | 00m00s [129/175] Installing gpgverify-0:2.2-3. 100% | 0.0 B/s | 9.4 KiB | 00m00s [130/175] Installing xxhash-libs-0:0.8. 100% | 89.2 MiB/s | 91.4 KiB | 00m00s [131/175] Installing keyutils-libs-0:1. 100% | 0.0 B/s | 55.7 KiB | 00m00s [132/175] Installing libcom_err-0:1.47. 100% | 0.0 B/s | 64.2 KiB | 00m00s [133/175] Installing libverto-0:0.3.2-1 100% | 26.6 MiB/s | 27.2 KiB | 00m00s [134/175] Installing krb5-libs-0:1.22.2 100% | 333.1 MiB/s | 2.3 MiB | 00m00s [135/175] Installing libssh-0:0.11.5-1. 100% | 280.8 MiB/s | 575.1 KiB | 00m00s [136/175] Installing libbrotli-0:1.2.1- 100% | 282.3 MiB/s | 867.3 KiB | 00m00s [137/175] Installing libnghttp2-0:1.66. 100% | 159.4 MiB/s | 163.2 KiB | 00m00s [138/175] Installing libcurl-0:8.15.0-1 100% | 295.6 MiB/s | 908.1 KiB | 00m00s [139/175] Installing curl-0:8.15.0-12.f 100% | 20.6 MiB/s | 463.9 KiB | 00m00s [140/175] Installing rpm-0:6.0.2-1.fc43 100% | 83.1 MiB/s | 2.6 MiB | 00m00s [141/175] Installing efi-srpm-macros-0: 100% | 40.2 MiB/s | 41.1 KiB | 00m00s [142/175] Installing java-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [143/175] Installing lua-srpm-macros-0: 100% | 0.0 B/s | 1.9 KiB | 00m00s [144/175] Installing tree-sitter-srpm-m 100% | 0.0 B/s | 9.3 KiB | 00m00s [145/175] Installing zig-srpm-macros-0: 100% | 0.0 B/s | 1.7 KiB | 00m00s [146/175] Installing cmake-srpm-macros- 100% | 0.0 B/s | 804.0 B | 00m00s [147/175] Installing filesystem-srpm-ma 100% | 0.0 B/s | 38.9 KiB | 00m00s [148/175] Installing elfutils-default-y 100% | 340.5 KiB/s | 2.0 KiB | 00m00s [149/175] Installing elfutils-libs-0:0. 100% | 227.0 MiB/s | 697.2 KiB | 00m00s [150/175] Installing elfutils-debuginfo 100% | 6.5 MiB/s | 86.0 KiB | 00m00s [151/175] Installing elfutils-0:0.197-1 100% | 164.3 MiB/s | 3.1 MiB | 00m00s [152/175] Installing binutils-0:2.45.1- 100% | 346.5 MiB/s | 27.4 MiB | 00m00s [153/175] Installing gdb-minimal-0:18.1 100% | 294.1 MiB/s | 13.8 MiB | 00m00s [154/175] Installing debugedit-0:5.2-3. 100% | 16.3 MiB/s | 217.3 KiB | 00m00s [155/175] Installing rpm-build-libs-0:6 100% | 258.9 MiB/s | 265.1 KiB | 00m00s [156/175] Installing gnome-srpm-macros- 100% | 0.0 B/s | 4.1 KiB | 00m00s [157/175] Installing perl-srpm-macros-0 100% | 0.0 B/s | 1.1 KiB | 00m00s [158/175] Installing openblas-srpm-macr 100% | 0.0 B/s | 392.0 B | 00m00s [159/175] Installing ocaml-srpm-macros- 100% | 0.0 B/s | 2.1 KiB | 00m00s [160/175] Installing kernel-srpm-macros 100% | 0.0 B/s | 2.3 KiB | 00m00s [161/175] Installing ghc-srpm-macros-0: 100% | 0.0 B/s | 1.0 KiB | 00m00s [162/175] Installing gap-srpm-macros-0: 100% | 0.0 B/s | 2.7 KiB | 00m00s [163/175] Installing fpc-srpm-macros-0: 100% | 0.0 B/s | 420.0 B | 00m00s [164/175] Installing ansible-srpm-macro 100% | 0.0 B/s | 36.2 KiB | 00m00s [165/175] Installing rpm-build-0:6.0.2- 100% | 20.6 MiB/s | 295.6 KiB | 00m00s [166/175] Installing pyproject-srpm-mac 100% | 0.0 B/s | 4.0 KiB | 00m00s [167/175] Installing redhat-rpm-config- 100% | 184.7 MiB/s | 189.1 KiB | 00m00s [168/175] Installing forge-srpm-macros- 100% | 0.0 B/s | 40.3 KiB | 00m00s [169/175] Installing fonts-srpm-macros- 100% | 0.0 B/s | 57.0 KiB | 00m00s [170/175] Installing go-srpm-macros-0:3 100% | 0.0 B/s | 63.0 KiB | 00m00s [171/175] Installing python-srpm-macros 100% | 51.6 MiB/s | 52.8 KiB | 00m00s [172/175] Installing util-linux-0:2.41. 100% | 101.8 MiB/s | 3.6 MiB | 00m00s [173/175] Installing shadow-utils-2:4.1 100% | 147.0 MiB/s | 4.0 MiB | 00m00s [174/175] Installing which-0:2.23-3.fc4 100% | 7.0 MiB/s | 85.7 KiB | 00m00s [175/175] Installing info-0:7.2-7.fc43. 100% | 258.4 KiB/s | 354.3 KiB | 00m01s Complete! Finish: installing minimal buildroot with dnf5 Start: creating root cache Finish: creating root cache Finish: chroot init INFO: Installed packages: INFO: add-determinism-0.6.0-3.fc43.x86_64 alternatives-1.33-3.fc43.x86_64 ansible-srpm-macros-1-18.1.fc43.noarch audit-libs-4.2.1-1.fc43.x86_64 bash-5.3.0-2.fc43.x86_64 binutils-2.45.1-5.fc43.x86_64 build-reproducibility-srpm-macros-0.6.0-3.fc43.noarch bzip2-1.0.8-21.fc43.x86_64 bzip2-libs-1.0.8-21.fc43.x86_64 ca-certificates-2026.2.92_v9.0.319-2.fc43.noarch cmake-srpm-macros-3.31.11-1.fc43.noarch coreutils-9.7-10.fc43.x86_64 coreutils-common-9.7-10.fc43.x86_64 cpio-2.15-6.fc43.x86_64 crypto-policies-20251125-1.git63291f8.fc43.noarch curl-8.15.0-12.fc43.x86_64 cyrus-sasl-lib-2.1.28-33.fc43.x86_64 debugedit-5.2-3.fc43.x86_64 diffutils-3.12-3.fc43.x86_64 dwz-0.16-2.fc43.x86_64 ed-1.22.2-1.fc43.x86_64 efi-srpm-macros-6-4.fc43.noarch elfutils-0.197-1.fc43.x86_64 elfutils-debuginfod-client-0.197-1.fc43.x86_64 elfutils-default-yama-scope-0.197-1.fc43.noarch elfutils-libelf-0.197-1.fc43.x86_64 elfutils-libs-0.197-1.fc43.x86_64 fedora-gpg-keys-43-2.noarch fedora-release-43-27.noarch fedora-release-common-43-27.noarch fedora-release-identity-basic-43-27.noarch fedora-repos-43-2.noarch file-5.46-9.fc43.x86_64 file-libs-5.46-9.fc43.x86_64 filesystem-3.18-50.fc43.x86_64 filesystem-srpm-macros-3.18-50.fc43.noarch findutils-4.10.0-6.fc43.x86_64 fonts-srpm-macros-2.0.5-23.fc43.noarch forge-srpm-macros-0.4.0-3.fc43.noarch fpc-srpm-macros-1.3-15.fc43.noarch gap-srpm-macros-2-1.fc43.noarch gawk-5.3.2-2.fc43.x86_64 gdb-minimal-18.1-1.fc43.x86_64 gdbm-libs-1.23-10.fc43.x86_64 ghc-srpm-macros-1.9.2-3.fc43.noarch glibc-2.42-17.fc43.x86_64 glibc-common-2.42-17.fc43.x86_64 glibc-gconv-extra-2.42-17.fc43.x86_64 glibc-minimal-langpack-2.42-17.fc43.x86_64 gmp-6.3.0-4.fc43.x86_64 gnat-srpm-macros-7-1.fc43.noarch gnome-srpm-macros-1.0-1.fc43.noarch gnulib-l10n-20241231-1.fc43.noarch gnupg2-2.4.9-5.fc43.x86_64 gnupg2-dirmngr-2.4.9-5.fc43.x86_64 gnupg2-gpg-agent-2.4.9-5.fc43.x86_64 gnupg2-gpgconf-2.4.9-5.fc43.x86_64 gnupg2-keyboxd-2.4.9-5.fc43.x86_64 gnupg2-verify-2.4.9-5.fc43.x86_64 gnutls-3.8.13-1.fc43.x86_64 go-srpm-macros-3.8.0-1.fc43.noarch gpg-pubkey-c6e7f081cf80e13146676e88829b606631645531-66b6dccf gpgverify-2.2-3.fc43.noarch grep-3.12-2.fc43.x86_64 gzip-1.13-4.fc43.x86_64 ima-evm-utils-libs-1.6.2-6.fc43.x86_64 info-7.2-7.fc43.x86_64 jansson-2.14-3.fc43.x86_64 java-srpm-macros-1-7.fc43.noarch json-c-0.18-7.fc43.x86_64 kernel-srpm-macros-1.0-27.fc43.noarch keyutils-libs-1.6.3-6.fc43.x86_64 krb5-libs-1.22.2-4.fc43.x86_64 libacl-2.4.0-1.fc43.x86_64 libarchive-3.8.4-1.fc43.x86_64 libassuan-2.5.7-4.fc43.x86_64 libattr-2.6.0-1.fc43.x86_64 libblkid-2.41.6-1.fc43.x86_64 libbrotli-1.2.1-1.fc43.x86_64 libcap-2.76-4.fc43.x86_64 libcap-ng-0.9.6-1.fc43.x86_64 libcom_err-1.47.3-2.fc43.x86_64 libcurl-8.15.0-12.fc43.x86_64 libeconf-0.7.9-2.fc43.x86_64 libevent-2.1.13-1.fc43.x86_64 libfdisk-2.41.6-1.fc43.x86_64 libffi-3.5.2-1.fc43.x86_64 libfsverity-1.6-3.fc43.x86_64 libgcc-15.3.1-1.fc43.x86_64 libgcrypt-1.11.1-4.fc43.x86_64 libgomp-15.3.1-1.fc43.x86_64 libgpg-error-1.55-2.fc43.x86_64 libidn2-2.3.8-2.fc43.x86_64 libksba-1.6.7-4.fc43.x86_64 liblastlog2-2.41.6-1.fc43.x86_64 libmount-2.41.6-1.fc43.x86_64 libnghttp2-1.66.0-3.fc43.x86_64 libpfm-4.14.1-2.fc43.x86_64 libpkgconf-2.3.0-3.fc43.x86_64 libpsl-0.21.5-6.fc43.x86_64 libselinux-3.9-5.fc43.x86_64 libsemanage-3.9-4.fc43.x86_64 libsepol-3.9-2.fc43.x86_64 libsmartcols-2.41.6-1.fc43.x86_64 libssh-0.11.5-1.fc43.x86_64 libssh-config-0.11.5-1.fc43.noarch libstdc++-15.3.1-1.fc43.x86_64 libtasn1-4.21.0-1.fc43.x86_64 libtool-ltdl-2.5.4-8.fc43.x86_64 libunistring-1.1-10.fc43.x86_64 libusb1-1.0.30-1.fc43.x86_64 libuuid-2.41.6-1.fc43.x86_64 libverto-0.3.2-11.fc43.x86_64 libxcrypt-4.5.2-1.fc43.x86_64 libxml2-2.12.10-5.fc43.x86_64 libzstd-1.5.7-2.fc43.x86_64 lua-libs-5.4.8-4.fc43.x86_64 lua-srpm-macros-1-16.fc43.noarch lz4-libs-1.10.0-3.fc43.x86_64 mpfr-4.2.2-2.fc43.x86_64 ncurses-base-6.5-7.20250614.fc43.noarch ncurses-libs-6.5-7.20250614.fc43.x86_64 nettle-3.10.1-2.fc43.x86_64 npth-1.8-3.fc43.x86_64 ocaml-srpm-macros-11-2.fc43.noarch openblas-srpm-macros-2-20.fc43.noarch openldap-2.6.15-1.fc43.x86_64 openssl-libs-3.5.9-1.fc43.x86_64 p11-kit-0.26.5-1.fc43.x86_64 p11-kit-trust-0.26.5-1.fc43.x86_64 package-notes-srpm-macros-0.20-1.fc43.noarch pam-libs-1.7.1-5.fc43.x86_64 patch-2.8-2.fc43.x86_64 pcre2-10.47-1.fc43.x86_64 pcre2-syntax-10.47-1.fc43.noarch perl-srpm-macros-1-60.fc43.noarch pkgconf-2.3.0-3.fc43.x86_64 pkgconf-m4-2.3.0-3.fc43.noarch pkgconf-pkg-config-2.3.0-3.fc43.x86_64 popt-1.19-9.fc43.x86_64 publicsuffix-list-dafsa-20260116-1.fc43.noarch pyproject-srpm-macros-1.24.0-1.fc43.noarch python-srpm-macros-3.14-5.fc43.noarch qt5-srpm-macros-5.15.18-1.fc43.noarch qt6-srpm-macros-6.10.3-1.fc43.noarch readline-8.3-2.fc43.x86_64 redhat-rpm-config-343-14.fc43.noarch rpm-6.0.2-1.fc43.x86_64 rpm-build-6.0.2-1.fc43.x86_64 rpm-build-libs-6.0.2-1.fc43.x86_64 rpm-libs-6.0.2-1.fc43.x86_64 rpm-sequoia-1.10.3-1.fc43.x86_64 rpm-sign-libs-6.0.2-1.fc43.x86_64 rust-srpm-macros-28.5-1.fc43.noarch sed-4.9-5.fc43.x86_64 setup-2.15.0-26.fc43.noarch shadow-utils-4.18.0-3.fc43.x86_64 sqlite-libs-3.50.2-3.fc43.x86_64 systemd-libs-258.11-1.fc43.x86_64 systemd-standalone-sysusers-258.11-1.fc43.x86_64 tar-1.35-6.fc43.x86_64 tpm2-tss-4.1.3-8.fc43.x86_64 tree-sitter-srpm-macros-0.4.2-1.fc43.noarch unzip-6.0-67.fc43.x86_64 util-linux-2.41.6-1.fc43.x86_64 util-linux-core-2.41.6-1.fc43.x86_64 which-2.23-3.fc43.x86_64 xxhash-libs-0.8.4-2.fc43.x86_64 xz-5.8.1-4.fc43.x86_64 xz-libs-5.8.1-4.fc43.x86_64 zig-srpm-macros-1-5.fc43.noarch zip-3.0-44.fc43.x86_64 zlib-ng-compat-2.3.3-2.fc43.x86_64 zstd-1.5.7-2.fc43.x86_64 Start: buildsrpm Start: rpmbuild -bs Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc43.src.rpm Finish: rpmbuild -bs INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-43-x86_64-1794040424.263307/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-e025pw8w/python-pyradplan/python-pyradplan.spec) Config(child) 0 minutes 20 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.fc43.src.rpm) Config(fedora-43-x86_64) Start(bootstrap): chroot init INFO: mounting tmpfs at /var/lib/mock/fedora-43-x86_64-bootstrap-1794040424.263307/root. INFO: reusing tmpfs at /var/lib/mock/fedora-43-x86_64-bootstrap-1794040424.263307/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-43-x86_64-1794040424.263307/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.fc43.x86_64 rpm-sequoia-1.10.3-1.fc43.x86_64 dnf5-5.2.18.0-5.fc43.x86_64 dnf5-plugins-5.2.18.0-5.fc43.x86_64 Finish: chroot init Start: build phase for python-pyradplan-0.8.0-1.fc43.src.rpm Start: build setup for python-pyradplan-0.8.0-1.fc43.src.rpm Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc43.src.rpm Updating and loading repositories: Copr repository 100% | 11.2 KiB/s | 1.5 KiB | 00m00s fedora 100% | 51.1 KiB/s | 23.5 KiB | 00m00s updates 100% | 69.7 KiB/s | 18.6 KiB | 00m00s Repositories loaded. Package Arch Version Repository Size Installing: pyproject-rpm-macros noarch 1.24.0-1.fc43 updates 169.0 KiB python3-devel x86_64 3.14.8-1.fc43 updates 2.0 MiB python3-pytest noarch 8.3.5-9.fc43 fedora 21.6 MiB Installing dependencies: expat x86_64 2.9.0-1.fc43 updates 337.6 KiB mpdecimal x86_64 4.0.1-2.fc43 fedora 217.2 KiB python-pip-wheel noarch 25.1.1-19.fc43 updates 1.2 MiB python-rpm-macros noarch 3.14-5.fc43 fedora 23.2 KiB python3 x86_64 3.14.8-1.fc43 updates 28.7 KiB python3-iniconfig noarch 2.1.0-3.fc43 fedora 42.4 KiB python3-libs x86_64 3.14.8-1.fc43 updates 43.5 MiB python3-packaging noarch 25.0-7.fc43 fedora 607.4 KiB python3-pluggy noarch 1.6.0-4.fc43 fedora 211.0 KiB python3-rpm-generators noarch 14-13.fc43 fedora 81.7 KiB python3-rpm-macros noarch 3.14-5.fc43 fedora 6.5 KiB tzdata noarch 2026e-1.fc43 updates 1.6 MiB Transaction Summary: Installing: 15 packages Total size of inbound packages is 15 MiB. Need to download 15 MiB. After this operation, 72 MiB extra will be used (install 72 MiB, remove 0 B). [ 1/15] python3-devel-0:3.14.8-1.fc43.x 100% | 35.8 MiB/s | 439.4 KiB | 00m00s [ 2/15] pyproject-rpm-macros-0:1.24.0-1 100% | 4.4 MiB/s | 58.0 KiB | 00m00s [ 3/15] python3-iniconfig-0:2.1.0-3.fc4 100% | 4.5 MiB/s | 22.9 KiB | 00m00s [ 4/15] python3-packaging-0:25.0-7.fc43 100% | 26.3 MiB/s | 161.5 KiB | 00m00s [ 5/15] python3-pluggy-0:1.6.0-4.fc43.n 100% | 30.0 MiB/s | 61.5 KiB | 00m00s [ 6/15] python3-pytest-0:8.3.5-9.fc43.n 100% | 96.4 MiB/s | 2.2 MiB | 00m00s [ 7/15] python-rpm-macros-0:3.14-5.fc43 100% | 4.2 MiB/s | 17.3 KiB | 00m00s [ 8/15] python3-rpm-macros-0:3.14-5.fc4 100% | 2.3 MiB/s | 11.8 KiB | 00m00s [ 9/15] mpdecimal-0:4.0.1-2.fc43.x86_64 100% | 19.0 MiB/s | 97.1 KiB | 00m00s [10/15] expat-0:2.9.0-1.fc43.x86_64 100% | 25.6 MiB/s | 131.1 KiB | 00m00s [11/15] tzdata-0:2026e-1.fc43.noarch 100% | 87.0 MiB/s | 713.0 KiB | 00m00s [12/15] python-pip-wheel-0:25.1.1-19.fc 100% | 92.7 MiB/s | 1.2 MiB | 00m00s [13/15] python3-0:3.14.8-1.fc43.x86_64 100% | 4.1 MiB/s | 29.4 KiB | 00m00s [14/15] python3-rpm-generators-0:14-13. 100% | 5.6 MiB/s | 28.5 KiB | 00m00s [15/15] python3-libs-0:3.14.8-1.fc43.x8 100% | 220.3 MiB/s | 9.9 MiB | 00m00s -------------------------------------------------------------------------------- [15/15] Total 100% | 212.2 MiB/s | 15.1 MiB | 00m00s Running transaction [ 1/17] Verify package files 100% | 288.0 B/s | 15.0 B | 00m00s [ 2/17] Prepare transaction 100% | 517.0 B/s | 15.0 B | 00m00s [ 3/17] Installing python-rpm-macros-0: 100% | 23.4 MiB/s | 23.9 KiB | 00m00s [ 4/17] Installing python3-rpm-macros-0 100% | 0.0 B/s | 6.8 KiB | 00m00s [ 5/17] Installing pyproject-rpm-macros 100% | 41.9 MiB/s | 171.5 KiB | 00m00s [ 6/17] Installing tzdata-0:2026e-1.fc4 100% | 70.8 MiB/s | 1.9 MiB | 00m00s [ 7/17] Installing python-pip-wheel-0:2 100% | 623.0 MiB/s | 1.2 MiB | 00m00s [ 8/17] Installing expat-0:2.9.0-1.fc43 100% | 23.7 MiB/s | 339.6 KiB | 00m00s [ 9/17] Installing mpdecimal-0:4.0.1-2. 100% | 42.7 MiB/s | 218.8 KiB | 00m00s [10/17] Installing python3-libs-0:3.14. 100% | 340.6 MiB/s | 43.9 MiB | 00m00s [11/17] Installing python3-0:3.14.8-1.f 100% | 2.3 MiB/s | 30.4 KiB | 00m00s [12/17] Installing python3-packaging-0: 100% | 201.8 MiB/s | 619.9 KiB | 00m00s [13/17] Installing python3-rpm-generato 100% | 0.0 B/s | 82.9 KiB | 00m00s [14/17] Installing python3-iniconfig-0: 100% | 45.4 MiB/s | 46.5 KiB | 00m00s [15/17] Installing python3-pluggy-0:1.6 100% | 70.8 MiB/s | 217.5 KiB | 00m00s [16/17] Installing python3-pytest-0:8.3 100% | 382.4 MiB/s | 21.8 MiB | 00m00s [17/17] Installing python3-devel-0:3.14 100% | 55.7 MiB/s | 2.0 MiB | 00m00s Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc43.src.rpm Updating and loading repositories: Copr repository 100% | 9.2 KiB/s | 1.5 KiB | 00m00s fedora 100% | 50.4 KiB/s | 23.5 KiB | 00m00s updates 100% | 58.0 KiB/s | 18.6 KiB | 00m00s Repositories loaded. Nothing to do. Package "pyproject-rpm-macros-1.24.0-1.fc43.noarch" is already installed. Package "python3-devel-3.14.8-1.fc43.x86_64" is already installed. Package "python3-pytest-8.3.5-9.fc43.noarch" is already installed. Finish: build setup for python-pyradplan-0.8.0-1.fc43.src.rpm Start: rpmbuild python-pyradplan-0.8.0-1.fc43.src.rpm Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%mkbuilddir): /bin/sh -e /var/tmp/rpm-tmp.Kot0LG Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.Sh0hyr + 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.Q7Vllv + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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=43 + 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.fc43.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-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.fc43.x86_64-pyproject-buildrequires + rm -rfv '*.dist-info/' + RPM_EC=0 ++ jobs -p + exit 0 Wrote: /builddir/build/SRPMS/python-pyradplan-0.8.0-1.fc43.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: Copr repository 100% | 6.8 KiB/s | 1.5 KiB | 00m00s fedora 100% | 57.4 KiB/s | 23.5 KiB | 00m00s updates 100% | 74.7 KiB/s | 18.6 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc43.noarch" is already installed. Package "python3-devel-3.14.8-1.fc43.x86_64" is already installed. Package "python3-pytest-8.3.5-9.fc43.noarch" is already installed. Package "python3-packaging-25.0-7.fc43.noarch" is already installed. Package Arch Version Repository Size Installing: python3-pip noarch 25.1.1-19.fc43 updates 12.5 MiB python3-setuptools noarch 78.1.1-15.fc43 fedora 9.0 MiB python3-setuptools_scm noarch 8.3.1-8.fc43 fedora 354.5 KiB Transaction Summary: Installing: 3 packages Total size of inbound packages is 5 MiB. Need to download 5 MiB. After this operation, 22 MiB extra will be used (install 22 MiB, remove 0 B). [1/3] python3-setuptools_scm-0:8.3.1-8. 100% | 9.1 MiB/s | 121.7 KiB | 00m00s [2/3] python3-pip-0:25.1.1-19.fc43.noar 100% | 167.3 MiB/s | 2.8 MiB | 00m00s [3/3] python3-setuptools-0:78.1.1-15.fc 100% | 68.5 MiB/s | 2.1 MiB | 00m00s -------------------------------------------------------------------------------- [3/3] Total 100% | 156.8 MiB/s | 5.0 MiB | 00m00s Running transaction [1/5] Verify package files 100% | 187.0 B/s | 3.0 B | 00m00s [2/5] Prepare transaction 100% | 157.0 B/s | 3.0 B | 00m00s [3/5] Installing python3-setuptools-0:7 100% | 249.2 MiB/s | 9.2 MiB | 00m00s [4/5] Installing python3-setuptools_scm 100% | 73.1 MiB/s | 374.4 KiB | 00m00s [5/5] Installing python3-pip-0:25.1.1-1 100% | 175.2 MiB/s | 12.8 MiB | 00m00s Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.Epe8DN + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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=43 + 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.fc43.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 78.1.1) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 8.3.1) /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:759: 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' /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:759: 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.fc43.x86_64-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.fc43.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: Copr repository 100% | 11.8 KiB/s | 1.5 KiB | 00m00s fedora 100% | 56.6 KiB/s | 23.5 KiB | 00m00s updates 100% | 72.4 KiB/s | 18.6 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc43.noarch" is already installed. Package "python3-devel-3.14.8-1.fc43.x86_64" is already installed. Package "python3-pytest-8.3.5-9.fc43.noarch" is already installed. Package "python3-packaging-25.0-7.fc43.noarch" is already installed. Package "python3-pip-25.1.1-19.fc43.noarch" is already installed. Package "python3-setuptools-78.1.1-15.fc43.noarch" is already installed. Package "python3-setuptools_scm-8.3.1-8.fc43.noarch" is already installed. Package Arch Version Repository Size Installing: python3-array-api-compat noarch 1.15.0-1.fc43 copr_base 506.6 KiB python3-array-api-extra noarch 0.11.5-1.fc43 copr_base 1.4 MiB python3-array-api-strict noarch 2.0.1-7.fc43 fedora 694.1 KiB python3-h5py x86_64 3.13.0-6.fc43 fedora 4.1 MiB python3-huggingface-hub noarch 1.24.0-1.fc43 copr_base 6.5 MiB python3-ipax noarch 0.13.0-1.fc43 copr_base 3.0 MiB python3-jinja2 noarch 3.1.6-6.fc43 fedora 3.1 MiB python3-matplotlib x86_64 3.10.9-1.fc43 updates 31.7 MiB python3-numpy x86_64 1:2.3.5-1.fc43 updates 41.4 MiB python3-numpydantic noarch 2.0.0-1.fc43 copr_base 621.5 KiB python3-pint noarch 0.25.2-1.fc43 updates 3.4 MiB python3-pydantic noarch 2.12.5-4.fc43 updates 5.1 MiB python3-pydantic-settings noarch 2.15.0-1.fc43 updates 557.0 KiB python3-pydicom noarch 3.0.2-1.fc43 updates 13.9 MiB python3-pymatreader noarch 1.3.1-1.fc43 copr_base 65.9 KiB python3-regex x86_64 2026.9.10-1.fc43 updates 2.1 MiB python3-safetensors x86_64 0.7.0-1.fc43 updates 945.3 KiB python3-scipy x86_64 1.16.2-1.fc43 fedora 66.5 MiB python3-simpleitk x86_64 2.5.5-12.fc43 copr_base 15.6 MiB python3-tqdm noarch 4.67.2-2.fc43 updates 574.9 KiB Installing dependencies: CharLS x86_64 2.4.3-2.fc43 updates 336.1 KiB InsightToolkit5 x86_64 5.4.7-24.fc43 copr_base 28.7 MiB abattis-cantarell-vf-fonts noarch 0.301-15.fc43 fedora 192.7 KiB abseil-cpp x86_64 20250814.2-2.fc43 updates 2.5 MiB armadillo12 x86_64 12.8.1-1.fc43 copr_base 81.9 KiB arpack x86_64 3.9.1-7.fc43 fedora 641.8 KiB blosc x86_64 1.21.6-7.fc43 fedora 126.2 KiB boost-program-options x86_64 1.83.0-17.fc43 fedora 280.8 KiB cairo x86_64 1.18.6-1.fc43 updates 1.8 MiB cfitsio x86_64 4.6.3-1.fc43 updates 1.9 MiB dcmtk x86_64 3.7.0^20260922git8d68392-1.fc43 copr_base 42.6 MiB default-fonts-core-sans noarch 4.2-5.fc43 fedora 11.9 KiB dejavu-sans-fonts noarch 2.37-26.fc43 fedora 5.5 MiB double-conversion x86_64 3.4.0-1.fc43 updates 97.9 KiB expatpp x86_64 0-32.20121019gitd8c1bf8.fc43 fedora 37.9 KiB fftw-libs-double x86_64 3.3.10-16.fc43 fedora 3.4 MiB fftw-libs-single x86_64 3.3.10-16.fc43 fedora 3.6 MiB flexiblas x86_64 3.5.0-1.fc43 updates 38.0 KiB flexiblas-netlib x86_64 3.5.0-1.fc43 updates 16.5 MiB flexiblas-netlib64 x86_64 3.5.0-1.fc43 updates 16.7 MiB flexiblas-openblas-openmp x86_64 3.5.0-1.fc43 updates 39.2 KiB flexiblas-openblas-openmp64 x86_64 3.5.0-1.fc43 updates 39.2 KiB fmt x86_64 11.2.0-3.fc43 fedora 266.8 KiB fontconfig x86_64 2.17.0-3.fc43 fedora 765.9 KiB fonts-filesystem noarch 1:2.0.5-23.fc43 fedora 0.0 B freetype x86_64 2.13.3-4.fc43 updates 850.1 KiB freexl x86_64 2.0.0-15.fc43 fedora 89.3 KiB fribidi x86_64 1.0.16-3.fc43 fedora 190.3 KiB gdal-libs x86_64 3.11.5-1.fc43 updates 31.2 MiB gdcm x86_64 3.0.24-14.fc43 fedora 8.1 MiB geos x86_64 3.14.1-1.fc43 updates 4.1 MiB giflib x86_64 5.2.2-9.fc43 updates 116.1 KiB glib2 x86_64 2.86.5-1.fc43 updates 15.0 MiB google-noto-fonts-common noarch 20251101-2.fc43 updates 17.7 KiB google-noto-sans-vf-fonts noarch 20251101-2.fc43 updates 1.4 MiB gpgme x86_64 1.24.3-6.fc43 fedora 587.9 KiB gpgmepp x86_64 1.24.3-6.fc43 fedora 429.2 KiB graphite2 x86_64 1.3.14-19.fc43 fedora 191.8 KiB harfbuzz x86_64 11.5.1-2.fc43 updates 2.8 MiB hdf-libs x86_64 4.3.0-4.fc43 fedora 687.2 KiB hdf5 x86_64 1.14.6-6.fc43 fedora 6.4 MiB imath x86_64 3.1.12-4.fc43 fedora 379.7 KiB jbigkit-libs x86_64 2.1-32.fc43 fedora 113.5 KiB jsoncpp x86_64 1.9.6-2.fc43 fedora 257.6 KiB lcms2 x86_64 2.16-6.fc43 fedora 433.7 KiB libX11 x86_64 1.8.13-1.fc43 updates 1.3 MiB libX11-common noarch 1.8.13-1.fc43 updates 1.1 MiB libXau x86_64 1.0.12-3.fc43 fedora 72.9 KiB libXext x86_64 1.3.6-4.fc43 fedora 90.0 KiB libXrender x86_64 0.9.12-3.fc43 fedora 46.0 KiB libaec x86_64 1.1.4-3.fc43 fedora 90.3 KiB libarrow x86_64 20.0.0-10.fc43 updates 26.6 MiB libarrow-acero-libs x86_64 20.0.0-10.fc43 updates 1.4 MiB libarrow-dataset-libs x86_64 20.0.0-10.fc43 updates 1.5 MiB libarrow-doc noarch 20.0.0-10.fc43 updates 117.1 KiB libdc1394 x86_64 2.2.7-8.fc43 fedora 350.9 KiB libdeflate x86_64 1.26-1.fc43 updates 123.9 KiB libgeotiff x86_64 1.7.4-3.fc43 fedora 290.3 KiB libgfortran x86_64 15.3.1-1.fc43 updates 3.3 MiB libgta x86_64 1.2.1-16.fc43 fedora 66.1 KiB libharu x86_64 2.4.5-1.fc43 fedora 1.7 MiB libicu x86_64 77.1-1.fc43 fedora 36.4 MiB libimagequant x86_64 4.0.3-8.fc43 fedora 690.9 KiB libjpeg-turbo x86_64 3.1.3-1.fc43 updates 806.3 KiB libkml x86_64 1.3.0-56.fc43 fedora 1.2 MiB liblerc x86_64 4.0.0-9.fc43 fedora 624.1 KiB liblzf x86_64 3.6-33.fc43 fedora 49.5 KiB libminc x86_64 2.4.03-27.fc43 fedora 693.6 KiB libogg x86_64 2:1.3.6-2.fc43 updates 45.6 KiB liborc2 x86_64 2.1.4-1.fc43 updates 1.8 MiB libpng x86_64 2:1.6.58-1.fc43 updates 245.7 KiB libpq x86_64 18.0-3.fc43 fedora 1.0 MiB libqhull_r x86_64 1:8.0.2-7.fc43 fedora 483.3 KiB libquadmath x86_64 15.3.1-1.fc43 updates 317.9 KiB libraqm x86_64 0.10.1-3.fc43 fedora 28.6 KiB libraw1394 x86_64 2.1.2-24.fc43 fedora 158.8 KiB librttopo x86_64 1.1.0-17.fc43 fedora 504.6 KiB libspatialite x86_64 5.1.0-11.fc43 fedora 15.3 MiB libtheora x86_64 1:1.1.1-40.fc43 fedora 477.3 KiB libtiff x86_64 4.7.2-3.fc43 updates 636.5 KiB libtirpc x86_64 1.3.7-1.rc1.fc43 updates 200.3 KiB libwebp x86_64 1.6.0-2.fc43 fedora 956.6 KiB libxcb x86_64 1.17.0-6.fc43 fedora 1.1 MiB libyaml x86_64 0.2.5-17.fc43 fedora 134.6 KiB libzip x86_64 1.11.4-2.fc43 fedora 135.8 KiB lzo x86_64 2.10-15.fc43 fedora 178.9 KiB mariadb-connector-c x86_64 3.4.9-2.fc43 updates 493.4 KiB mariadb-connector-c-config noarch 3.4.9-2.fc43 updates 26.4 KiB minizip-ng-compat x86_64 4.0.10-2.fc43 fedora 162.5 KiB muParser x86_64 2.3.5-3.fc43 fedora 551.2 KiB netcdf x86_64 4.9.2-15.fc43 fedora 2.3 MiB nspr x86_64 4.39.0-7.fc43 updates 315.1 KiB nss x86_64 3.131.0-1.fc43 updates 1.9 MiB nss-softokn x86_64 3.131.0-1.fc43 updates 2.0 MiB nss-softokn-freebl x86_64 3.131.0-1.fc43 updates 1.1 MiB nss-sysinit x86_64 3.131.0-1.fc43 updates 17.9 KiB nss-util x86_64 3.131.0-1.fc43 updates 204.8 KiB openblas x86_64 0.3.29-2.fc43 fedora 111.7 KiB openblas-openmp x86_64 0.3.29-2.fc43 fedora 43.7 MiB openblas-openmp64 x86_64 0.3.29-2.fc43 fedora 43.8 MiB openexr-libs x86_64 3.2.4-6.fc43 fedora 6.5 MiB openjpeg x86_64 2.5.4-1.fc43 fedora 456.3 KiB parquet-libs x86_64 20.0.0-10.fc43 updates 3.3 MiB pixman x86_64 0.46.2-2.fc43 fedora 710.3 KiB poppler x86_64 25.07.0-5.fc43 updates 3.8 MiB poppler-data noarch 0.4.11-10.fc43 fedora 12.3 MiB proj x86_64 9.6.2-2.fc43 fedora 4.5 MiB proj-data noarch 9.6.2-2.fc43 fedora 9.3 MiB protobuf x86_64 3.19.6-18.fc43 fedora 3.3 MiB pugixml x86_64 1.16-1.fc43 updates 278.5 KiB python3-annotated-types noarch 0.7.0-8.fc43 fedora 85.1 KiB python3-anyio noarch 4.13.0-2.fc43 updates 1.5 MiB python3-cached_property noarch 2.0.1-6.fc43 fedora 35.2 KiB python3-cairo x86_64 1.28.0-4.fc43 fedora 492.9 KiB python3-certifi noarch 2025.07.09-3.fc43 fedora 7.4 KiB python3-charset-normalizer noarch 3.4.3-3.fc43 fedora 355.7 KiB python3-click noarch 1:8.1.7-12.fc43 updates 1.2 MiB python3-contourpy x86_64 1.4.0-1.fc43 updates 857.1 KiB python3-cycler noarch 0.11.0-19.fc43 fedora 37.8 KiB python3-dateutil noarch 1:2.9.0.post0-6.fc43 fedora 877.5 KiB python3-dotenv noarch 1.2.2-1.fc43 updates 149.4 KiB python3-filelock noarch 3.15.4-10.fc43 fedora 97.0 KiB python3-flexcache noarch 0.3-10.fc43 fedora 57.0 KiB python3-flexparser noarch 0.4-6.fc43 fedora 263.5 KiB python3-fonttools x86_64 4.61.0-1.fc43 updates 19.2 MiB python3-fsspec noarch 2026.6.0-1.fc43 updates 1.9 MiB python3-h11 noarch 0.16.0-5.fc43 fedora 279.9 KiB python3-httpcore noarch 1.0.9-5.fc43 fedora 853.9 KiB python3-httpx noarch 0.28.1-9.fc43 fedora 992.1 KiB python3-idna noarch 3.18-1.fc43 updates 522.3 KiB python3-kiwisolver x86_64 1.5.1-1.fc43 updates 153.8 KiB python3-markupsafe x86_64 3.0.2-6.fc43 fedora 61.5 KiB python3-matplotlib-data-fonts x86_64 3.10.9-1.fc43 updates 7.9 MiB python3-numpy-f2py x86_64 1:2.3.5-1.fc43 updates 2.1 MiB python3-olefile noarch 0.47-12.fc43 updates 346.5 KiB python3-pillow x86_64 11.3.0-10.fc43 updates 4.2 MiB python3-platformdirs noarch 4.4.0-1.fc43 updates 182.4 KiB python3-pooch noarch 1.9.0-1.fc43 updates 656.8 KiB python3-pydantic-core x86_64 2.41.5-11.fc43 updates 5.3 MiB python3-pyparsing noarch 3.1.2-14.fc43 fedora 1.0 MiB python3-pyyaml x86_64 6.0.2-7.fc43 fedora 793.4 KiB python3-requests noarch 2.33.1-1.fc43 updates 477.3 KiB python3-six noarch 1.17.0-7.fc43 fedora 118.0 KiB python3-typing-extensions noarch 4.16.0-4.fc43 updates 552.0 KiB python3-typing-inspection noarch 0.4.4-1.fc43 updates 93.4 KiB python3-urllib3 noarch 2.8.0-3.fc43 updates 1.2 MiB python3-xmltodict noarch 0.14.2-4.fc43 fedora 56.0 KiB re2 x86_64 2:20251105-1.fc43 updates 583.4 KiB rply x86_64 1.1.4-11.fc43 updates 115.5 KiB simpleitk x86_64 2.5.5-12.fc43 copr_base 285.9 MiB snappy x86_64 1.2.2-2.fc43 fedora 71.8 KiB thrift x86_64 0.20.0-8.fc43 fedora 5.5 MiB unixODBC x86_64 2.3.14-2.fc43 updates 1.0 MiB uriparser x86_64 1.0.2-1.fc43 updates 184.4 KiB utf8proc x86_64 2.10.0-2.fc43 fedora 372.0 KiB viskores x86_64 1.2.0-3.fc43 copr_base 133.7 MiB vtk x86_64 9.7.0-7.fc43 copr_base 241.5 MiB vxl x86_64 3.5.0-16.fc43 fedora 53.1 MiB xerces-c x86_64 3.3.0-8.fc43 fedora 3.8 MiB xml-common noarch 0.6.3-67.fc43 fedora 78.4 KiB Transaction Summary: Installing: 180 packages Total size of inbound packages is 277 MiB. Need to download 277 MiB. After this operation, 1 GiB extra will be used (install 1 GiB, remove 0 B). [ 1/180] python3-array-api-strict-0:2. 100% | 11.5 MiB/s | 164.4 KiB | 00m00s [ 2/180] python3-h5py-0:3.13.0-6.fc43. 100% | 32.5 MiB/s | 1.1 MiB | 00m00s [ 3/180] python3-array-api-extra-0:0.1 100% | 925.7 KiB/s | 272.2 KiB | 00m00s [ 4/180] python3-jinja2-0:3.1.6-6.fc43 100% | 167.9 MiB/s | 515.8 KiB | 00m00s [ 5/180] python3-ipax-0:0.13.0-1.fc43. 100% | 2.2 MiB/s | 574.3 KiB | 00m00s [ 6/180] python3-scipy-0:1.16.2-1.fc43 100% | 226.9 MiB/s | 16.3 MiB | 00m00s [ 7/180] python3-array-api-compat-0:1. 100% | 320.0 KiB/s | 123.2 KiB | 00m00s [ 8/180] python3-pydantic-0:2.12.5-4.f 100% | 82.7 MiB/s | 1.0 MiB | 00m00s [ 9/180] python3-pydantic-settings-0:2 100% | 56.6 MiB/s | 173.7 KiB | 00m00s [ 10/180] python3-numpydantic-0:2.0.0-1 100% | 685.7 KiB/s | 186.5 KiB | 00m00s [ 11/180] python3-simpleitk-0:2.5.5-12. 100% | 7.4 MiB/s | 2.0 MiB | 00m00s [ 12/180] python3-huggingface-hub-0:1.2 100% | 5.2 MiB/s | 1.3 MiB | 00m00s [ 13/180] python3-pint-0:0.25.2-1.fc43. 100% | 80.5 MiB/s | 742.1 KiB | 00m00s [ 14/180] python3-pydicom-0:3.0.2-1.fc4 100% | 95.4 MiB/s | 3.1 MiB | 00m00s [ 15/180] python3-numpy-1:2.3.5-1.fc43. 100% | 149.5 MiB/s | 8.2 MiB | 00m00s [ 16/180] python3-regex-0:2026.9.10-1.f 100% | 81.8 MiB/s | 418.7 KiB | 00m00s [ 17/180] python3-safetensors-0:0.7.0-1 100% | 55.5 MiB/s | 397.9 KiB | 00m00s [ 18/180] python3-tqdm-0:4.67.2-2.fc43. 100% | 43.1 MiB/s | 176.3 KiB | 00m00s [ 19/180] hdf5-0:1.14.6-6.fc43.x86_64 100% | 104.9 MiB/s | 2.0 MiB | 00m00s [ 20/180] liblzf-0:3.6-33.fc43.x86_64 100% | 13.6 MiB/s | 27.8 KiB | 00m00s [ 21/180] python3-cached_property-0:2.0 100% | 10.0 MiB/s | 20.5 KiB | 00m00s [ 22/180] python3-six-0:1.17.0-7.fc43.n 100% | 20.4 MiB/s | 41.8 KiB | 00m00s [ 23/180] python3-markupsafe-0:3.0.2-6. 100% | 10.3 MiB/s | 31.7 KiB | 00m00s [ 24/180] python3-matplotlib-0:3.10.9-1 100% | 36.2 MiB/s | 7.9 MiB | 00m00s [ 25/180] python3-annotated-types-0:0.7 100% | 15.4 MiB/s | 31.6 KiB | 00m00s [ 26/180] python3-pydantic-core-0:2.41. 100% | 102.3 MiB/s | 1.7 MiB | 00m00s [ 27/180] python3-typing-inspection-0:0 100% | 11.0 MiB/s | 33.8 KiB | 00m00s [ 28/180] python3-filelock-0:3.15.4-10. 100% | 10.9 MiB/s | 44.8 KiB | 00m00s [ 29/180] python3-httpx-0:0.28.1-9.fc43 100% | 41.7 MiB/s | 213.7 KiB | 00m00s [ 30/180] python3-pyyaml-0:6.0.2-7.fc43 100% | 38.5 MiB/s | 236.4 KiB | 00m00s [ 31/180] dejavu-sans-fonts-0:2.37-26.f 100% | 189.3 MiB/s | 1.3 MiB | 00m00s [ 32/180] libqhull_r-1:8.0.2-7.fc43.x86 100% | 49.3 MiB/s | 201.9 KiB | 00m00s [ 33/180] python3-cycler-0:0.11.0-19.fc 100% | 10.7 MiB/s | 21.9 KiB | 00m00s [ 34/180] python3-dateutil-1:2.9.0.post 100% | 56.0 MiB/s | 344.3 KiB | 00m00s [ 35/180] python3-pyparsing-0:3.1.2-14. 100% | 93.4 MiB/s | 286.9 KiB | 00m00s [ 36/180] python3-matplotlib-data-fonts 100% | 234.1 MiB/s | 2.3 MiB | 00m00s [ 37/180] python3-numpy-f2py-1:2.3.5-1. 100% | 83.1 MiB/s | 510.8 KiB | 00m00s [ 38/180] python3-flexcache-0:0.3-10.fc 100% | 13.3 MiB/s | 27.2 KiB | 00m00s [ 39/180] python3-flexparser-0:0.4-6.fc 100% | 26.9 MiB/s | 55.1 KiB | 00m00s [ 40/180] python3-xmltodict-0:0.14.2-4. 100% | 3.7 MiB/s | 26.6 KiB | 00m00s [ 41/180] libaec-0:1.1.4-3.fc43.x86_64 100% | 18.4 MiB/s | 37.6 KiB | 00m00s [ 42/180] python3-pymatreader-0:1.3.1-1 100% | 129.4 KiB/s | 27.6 KiB | 00m00s [ 43/180] vxl-0:3.5.0-16.fc43.x86_64 100% | 216.5 MiB/s | 14.3 MiB | 00m00s [ 44/180] python3-certifi-0:2025.07.09- 100% | 7.3 MiB/s | 15.0 KiB | 00m00s [ 45/180] python3-httpcore-0:1.0.9-5.fc 100% | 38.4 MiB/s | 157.5 KiB | 00m00s [ 46/180] libyaml-0:0.2.5-17.fc43.x86_6 100% | 58.7 MiB/s | 60.1 KiB | 00m00s [ 47/180] fonts-filesystem-1:2.0.5-23.f 100% | 4.2 MiB/s | 8.7 KiB | 00m00s [ 48/180] InsightToolkit5-0:5.4.7-24.fc 100% | 11.2 MiB/s | 4.8 MiB | 00m00s [ 49/180] dcmtk-0:3.7.0^20260922git8d68 100% | 16.3 MiB/s | 8.1 MiB | 00m00s [ 50/180] fftw-libs-double-0:3.3.10-16. 100% | 142.8 MiB/s | 1.1 MiB | 00m00s [ 51/180] fftw-libs-single-0:3.3.10-16. 100% | 134.2 MiB/s | 1.2 MiB | 00m00s [ 52/180] gdcm-0:3.0.24-14.fc43.x86_64 100% | 168.1 MiB/s | 1.5 MiB | 00m00s [ 53/180] libminc-0:2.4.03-27.fc43.x86_ 100% | 67.9 MiB/s | 278.0 KiB | 00m00s [ 54/180] expatpp-0:0-32.20121019gitd8c 100% | 10.6 MiB/s | 21.8 KiB | 00m00s [ 55/180] libdc1394-0:2.2.7-8.fc43.x86_ 100% | 25.9 MiB/s | 132.8 KiB | 00m00s [ 56/180] libgeotiff-0:1.7.4-3.fc43.x86 100% | 31.5 MiB/s | 96.6 KiB | 00m00s [ 57/180] minizip-ng-compat-0:4.0.10-2. 100% | 16.4 MiB/s | 67.1 KiB | 00m00s [ 58/180] python3-h11-0:0.16.0-5.fc43.n 100% | 19.8 MiB/s | 81.0 KiB | 00m00s [ 59/180] simpleitk-0:2.5.5-12.fc43.x86 100% | 34.6 MiB/s | 42.4 MiB | 00m01s [ 60/180] fmt-0:11.2.0-3.fc43.x86_64 100% | 32.6 MiB/s | 100.2 KiB | 00m00s [ 61/180] jsoncpp-0:1.9.6-2.fc43.x86_64 100% | 24.7 MiB/s | 101.1 KiB | 00m00s [ 62/180] libharu-0:2.4.5-1.fc43.x86_64 100% | 112.7 MiB/s | 577.0 KiB | 00m00s [ 63/180] libtheora-1:1.1.1-40.fc43.x86 100% | 55.4 MiB/s | 170.3 KiB | 00m00s [ 64/180] netcdf-0:4.9.2-15.fc43.x86_64 100% | 114.5 MiB/s | 820.6 KiB | 00m00s [ 65/180] proj-0:9.6.2-2.fc43.x86_64 100% | 133.0 MiB/s | 1.6 MiB | 00m00s [ 66/180] openjpeg-0:2.5.4-1.fc43.x86_6 100% | 93.9 MiB/s | 192.2 KiB | 00m00s [ 67/180] libraw1394-0:2.1.2-24.fc43.x8 100% | 20.9 MiB/s | 64.1 KiB | 00m00s [ 68/180] blosc-0:1.21.6-7.fc43.x86_64 100% | 28.4 MiB/s | 58.1 KiB | 00m00s [ 69/180] libzip-0:1.11.4-2.fc43.x86_64 100% | 17.1 MiB/s | 70.0 KiB | 00m00s [ 70/180] proj-data-0:9.6.2-2.fc43.noar 100% | 36.6 MiB/s | 1.3 MiB | 00m00s [ 71/180] snappy-0:1.2.2-2.fc43.x86_64 100% | 12.9 MiB/s | 39.6 KiB | 00m00s [ 72/180] python3-typing-extensions-0:4 100% | 37.2 MiB/s | 114.1 KiB | 00m00s [ 73/180] python3-dotenv-0:1.2.2-1.fc43 100% | 28.0 MiB/s | 57.4 KiB | 00m00s [ 74/180] viskores-0:1.2.0-3.fc43.x86_6 100% | 30.0 MiB/s | 16.5 MiB | 00m01s [ 75/180] python3-platformdirs-0:4.4.0- 100% | 3.0 MiB/s | 49.1 KiB | 00m00s [ 76/180] flexiblas-0:3.5.0-1.fc43.x86_ 100% | 11.3 MiB/s | 23.1 KiB | 00m00s [ 77/180] flexiblas-openblas-openmp-0:3 100% | 16.9 MiB/s | 17.3 KiB | 00m00s [ 78/180] openblas-openmp-0:0.3.29-2.fc 100% | 214.4 MiB/s | 5.4 MiB | 00m00s [ 79/180] freetype-0:2.13.3-4.fc43.x86_ 100% | 40.2 MiB/s | 411.7 KiB | 00m00s [ 80/180] python3-cairo-0:1.28.0-4.fc43 100% | 41.1 MiB/s | 126.2 KiB | 00m00s [ 81/180] python3-contourpy-0:1.4.0-1.f 100% | 139.9 MiB/s | 286.5 KiB | 00m00s [ 82/180] python3-fonttools-0:4.61.0-1. 100% | 244.7 MiB/s | 3.2 MiB | 00m00s [ 83/180] python3-kiwisolver-0:1.5.1-1. 100% | 33.7 MiB/s | 69.0 KiB | 00m00s [ 84/180] python3-pillow-0:11.3.0-10.fc 100% | 56.8 MiB/s | 1.0 MiB | 00m00s [ 85/180] lcms2-0:2.16-6.fc43.x86_64 100% | 59.5 MiB/s | 182.8 KiB | 00m00s [ 86/180] libimagequant-0:4.0.3-8.fc43. 100% | 61.3 MiB/s | 313.8 KiB | 00m00s [ 87/180] libraqm-0:0.10.1-3.fc43.x86_6 100% | 10.9 MiB/s | 22.4 KiB | 00m00s [ 88/180] libwebp-0:1.6.0-2.fc43.x86_64 100% | 52.8 MiB/s | 324.2 KiB | 00m00s [ 89/180] libxcb-0:1.17.0-6.fc43.x86_64 100% | 116.1 MiB/s | 237.7 KiB | 00m00s [ 90/180] fribidi-0:1.0.16-3.fc43.x86_6 100% | 52.1 MiB/s | 53.3 KiB | 00m00s [ 91/180] libXau-0:1.0.12-3.fc43.x86_64 100% | 10.9 MiB/s | 33.4 KiB | 00m00s [ 92/180] harfbuzz-0:11.5.1-2.fc43.x86_ 100% | 215.6 MiB/s | 1.1 MiB | 00m00s [ 93/180] graphite2-0:1.3.14-19.fc43.x8 100% | 46.7 MiB/s | 95.6 KiB | 00m00s [ 94/180] libpng-2:1.6.58-1.fc43.x86_64 100% | 40.9 MiB/s | 125.8 KiB | 00m00s [ 95/180] libgfortran-0:15.3.1-1.fc43.x 100% | 158.5 MiB/s | 973.6 KiB | 00m00s [ 96/180] flexiblas-netlib-0:3.5.0-1.fc 100% | 34.1 MiB/s | 4.5 MiB | 00m00s [ 97/180] libquadmath-0:15.3.1-1.fc43.x 100% | 41.7 MiB/s | 213.7 KiB | 00m00s [ 98/180] libjpeg-turbo-0:3.1.3-1.fc43. 100% | 77.1 MiB/s | 236.8 KiB | 00m00s [ 99/180] libtiff-0:4.7.2-3.fc43.x86_64 100% | 55.1 MiB/s | 225.7 KiB | 00m00s [100/180] jbigkit-libs-0:2.1-32.fc43.x8 100% | 26.0 MiB/s | 53.2 KiB | 00m00s [101/180] liblerc-0:4.0.0-9.fc43.x86_64 100% | 70.0 MiB/s | 215.1 KiB | 00m00s [102/180] rply-0:1.1.4-11.fc43.x86_64 100% | 8.9 MiB/s | 45.4 KiB | 00m00s [103/180] python3-pooch-0:1.9.0-1.fc43. 100% | 47.5 MiB/s | 145.9 KiB | 00m00s [104/180] python3-idna-0:3.18-1.fc43.no 100% | 34.0 MiB/s | 104.3 KiB | 00m00s [105/180] cairo-0:1.18.6-1.fc43.x86_64 100% | 178.2 MiB/s | 729.7 KiB | 00m00s [106/180] python3-anyio-0:4.13.0-2.fc43 100% | 30.8 MiB/s | 315.8 KiB | 00m00s [107/180] libXext-0:1.3.6-4.fc43.x86_64 100% | 12.7 MiB/s | 39.1 KiB | 00m00s [108/180] fontconfig-0:2.17.0-3.fc43.x8 100% | 44.3 MiB/s | 272.2 KiB | 00m00s [109/180] lzo-0:2.10-15.fc43.x86_64 100% | 33.9 MiB/s | 69.4 KiB | 00m00s [110/180] libXrender-0:0.9.12-3.fc43.x8 100% | 8.7 MiB/s | 26.9 KiB | 00m00s [111/180] default-fonts-core-sans-0:4.2 100% | 9.7 MiB/s | 29.9 KiB | 00m00s [112/180] pixman-0:0.46.2-2.fc43.x86_64 100% | 71.4 MiB/s | 292.5 KiB | 00m00s [113/180] xml-common-0:0.6.3-67.fc43.no 100% | 7.6 MiB/s | 31.0 KiB | 00m00s [114/180] openblas-0:0.3.29-2.fc43.x86_ 100% | 10.3 MiB/s | 42.3 KiB | 00m00s [115/180] abattis-cantarell-vf-fonts-0: 100% | 14.7 MiB/s | 120.1 KiB | 00m00s [116/180] libogg-2:1.3.6-2.fc43.x86_64 100% | 16.3 MiB/s | 33.5 KiB | 00m00s [117/180] libX11-0:1.8.13-1.fc43.x86_64 100% | 128.0 MiB/s | 655.2 KiB | 00m00s [118/180] libX11-common-0:1.8.13-1.fc43 100% | 28.6 MiB/s | 175.6 KiB | 00m00s [119/180] CharLS-0:2.4.3-2.fc43.x86_64 100% | 29.3 MiB/s | 120.0 KiB | 00m00s [120/180] google-noto-fonts-common-0:20 100% | 8.5 MiB/s | 17.3 KiB | 00m00s [121/180] google-noto-sans-vf-fonts-0:2 100% | 54.6 MiB/s | 614.5 KiB | 00m00s [122/180] freexl-0:2.0.0-15.fc43.x86_64 100% | 5.0 MiB/s | 45.8 KiB | 00m00s [123/180] imath-0:3.1.12-4.fc43.x86_64 100% | 16.5 MiB/s | 101.4 KiB | 00m00s [124/180] libgta-0:1.2.1-16.fc43.x86_64 100% | 11.7 MiB/s | 35.9 KiB | 00m00s [125/180] libkml-0:1.3.0-56.fc43.x86_64 100% | 69.8 MiB/s | 357.3 KiB | 00m00s [126/180] libpq-0:18.0-3.fc43.x86_64 100% | 53.4 MiB/s | 273.6 KiB | 00m00s [127/180] libspatialite-0:5.1.0-11.fc43 100% | 88.3 MiB/s | 3.1 MiB | 00m00s [128/180] muParser-0:2.3.5-3.fc43.x86_6 100% | 34.8 MiB/s | 178.4 KiB | 00m00s [129/180] gdal-libs-0:3.11.5-1.fc43.x86 100% | 107.2 MiB/s | 10.3 MiB | 00m00s [130/180] openexr-libs-0:3.2.4-6.fc43.x 100% | 58.8 MiB/s | 1.1 MiB | 00m00s [131/180] vtk-0:9.7.0-7.fc43.x86_64 100% | 37.1 MiB/s | 40.7 MiB | 00m01s [132/180] xerces-c-0:3.3.0-8.fc43.x86_6 100% | 24.8 MiB/s | 1.0 MiB | 00m00s [133/180] librttopo-0:1.1.0-17.fc43.x86 100% | 5.2 MiB/s | 206.9 KiB | 00m00s [134/180] pugixml-0:1.16-1.fc43.x86_64 100% | 21.5 MiB/s | 109.9 KiB | 00m00s [135/180] python3-click-1:8.1.7-12.fc43 100% | 49.6 MiB/s | 254.2 KiB | 00m00s [136/180] python3-fsspec-0:2026.6.0-1.f 100% | 77.2 MiB/s | 474.5 KiB | 00m00s [137/180] double-conversion-0:3.4.0-1.f 100% | 12.7 MiB/s | 51.9 KiB | 00m00s [138/180] python3-requests-0:2.33.1-1.f 100% | 39.2 MiB/s | 160.6 KiB | 00m00s [139/180] python3-charset-normalizer-0: 100% | 28.6 MiB/s | 117.3 KiB | 00m00s [140/180] python3-olefile-0:0.47-12.fc4 100% | 24.4 MiB/s | 74.9 KiB | 00m00s [141/180] cfitsio-0:4.6.3-1.fc43.x86_64 100% | 60.5 MiB/s | 619.7 KiB | 00m00s [142/180] glib2-0:2.86.5-1.fc43.x86_64 100% | 171.3 MiB/s | 3.1 MiB | 00m00s [143/180] giflib-0:5.2.2-9.fc43.x86_64 100% | 7.3 MiB/s | 52.2 KiB | 00m00s [144/180] utf8proc-0:2.10.0-2.fc43.x86_ 100% | 16.0 MiB/s | 81.8 KiB | 00m00s [145/180] libarrow-doc-0:20.0.0-10.fc43 100% | 9.4 MiB/s | 28.8 KiB | 00m00s [146/180] parquet-libs-0:20.0.0-10.fc43 100% | 66.7 MiB/s | 1.0 MiB | 00m00s [147/180] libarrow-dataset-libs-0:20.0. 100% | 55.5 MiB/s | 511.1 KiB | 00m00s [148/180] libarrow-0:20.0.0-10.fc43.x86 100% | 113.6 MiB/s | 6.2 MiB | 00m00s [149/180] thrift-0:0.20.0-8.fc43.x86_64 100% | 75.1 MiB/s | 1.8 MiB | 00m00s [150/180] libarrow-acero-libs-0:20.0.0- 100% | 63.0 MiB/s | 516.0 KiB | 00m00s [151/180] libdeflate-0:1.26-1.fc43.x86_ 100% | 13.3 MiB/s | 68.3 KiB | 00m00s [152/180] mariadb-connector-c-config-0: 100% | 5.3 MiB/s | 21.6 KiB | 00m00s [153/180] mariadb-connector-c-0:3.4.9-2 100% | 40.3 MiB/s | 206.4 KiB | 00m00s [154/180] gpgmepp-0:1.24.3-6.fc43.x86_6 100% | 34.9 MiB/s | 142.9 KiB | 00m00s [155/180] poppler-0:25.07.0-5.fc43.x86_ 100% | 145.0 MiB/s | 1.3 MiB | 00m00s [156/180] poppler-data-0:0.4.11-10.fc43 100% | 163.8 MiB/s | 2.0 MiB | 00m00s [157/180] gpgme-0:1.24.3-6.fc43.x86_64 100% | 26.7 MiB/s | 218.5 KiB | 00m00s [158/180] unixODBC-0:2.3.14-2.fc43.x86_ 100% | 81.0 MiB/s | 414.5 KiB | 00m00s [159/180] uriparser-0:1.0.2-1.fc43.x86_ 100% | 14.0 MiB/s | 71.8 KiB | 00m00s [160/180] python3-urllib3-0:2.8.0-3.fc4 100% | 75.7 MiB/s | 309.9 KiB | 00m00s [161/180] nspr-0:4.39.0-7.fc43.x86_64 100% | 33.8 MiB/s | 138.4 KiB | 00m00s [162/180] nss-softokn-0:3.131.0-1.fc43. 100% | 86.1 MiB/s | 440.7 KiB | 00m00s [163/180] nss-0:3.131.0-1.fc43.x86_64 100% | 70.8 MiB/s | 725.0 KiB | 00m00s [164/180] nss-util-0:3.131.0-1.fc43.x86 100% | 17.1 MiB/s | 87.3 KiB | 00m00s [165/180] geos-0:3.14.1-1.fc43.x86_64 100% | 9.8 MiB/s | 1.3 MiB | 00m00s [166/180] nss-sysinit-0:3.131.0-1.fc43. 100% | 6.4 MiB/s | 19.6 KiB | 00m00s [167/180] nss-softokn-freebl-0:3.131.0- 100% | 76.7 MiB/s | 392.7 KiB | 00m00s [168/180] boost-program-options-0:1.83. 100% | 10.8 MiB/s | 110.7 KiB | 00m00s [169/180] liborc2-0:2.1.4-1.fc43.x86_64 100% | 44.9 MiB/s | 551.3 KiB | 00m00s [170/180] protobuf-0:3.19.6-18.fc43.x86 100% | 71.9 MiB/s | 1.0 MiB | 00m00s [171/180] re2-2:20251105-1.fc43.x86_64 100% | 37.6 MiB/s | 231.3 KiB | 00m00s [172/180] hdf-libs-0:4.3.0-4.fc43.x86_6 100% | 35.6 MiB/s | 291.3 KiB | 00m00s [173/180] abseil-cpp-0:20250814.2-2.fc4 100% | 57.8 MiB/s | 768.8 KiB | 00m00s [174/180] libtirpc-0:1.3.7-1.rc1.fc43.x 100% | 11.6 MiB/s | 94.9 KiB | 00m00s [175/180] arpack-0:3.9.1-7.fc43.x86_64 100% | 40.9 MiB/s | 209.6 KiB | 00m00s [176/180] libicu-0:77.1-1.fc43.x86_64 100% | 178.4 MiB/s | 10.7 MiB | 00m00s [177/180] flexiblas-netlib64-0:3.5.0-1. 100% | 113.9 MiB/s | 4.3 MiB | 00m00s [178/180] flexiblas-openblas-openmp64-0 100% | 4.2 MiB/s | 17.2 KiB | 00m00s [179/180] openblas-openmp64-0:0.3.29-2. 100% | 326.7 MiB/s | 5.2 MiB | 00m00s [180/180] armadillo12-0:12.8.1-1.fc43.x 100% | 141.0 KiB/s | 28.9 KiB | 00m00s -------------------------------------------------------------------------------- [180/180] Total 100% | 98.9 MiB/s | 277.0 MiB | 00m03s Running transaction [ 1/182] Verify package files 100% | 177.0 B/s | 180.0 B | 00m01s [ 2/182] Prepare transaction 100% | 2.1 KiB/s | 180.0 B | 00m00s [ 3/182] Installing libpng-2:1.6.58-1. 100% | 241.1 MiB/s | 246.9 KiB | 00m00s [ 4/182] Installing libjpeg-turbo-0:3. 100% | 394.5 MiB/s | 808.0 KiB | 00m00s [ 5/182] Installing libgfortran-0:15.3 100% | 417.9 MiB/s | 3.3 MiB | 00m00s [ 6/182] Installing python3-typing-ext 100% | 541.3 MiB/s | 554.3 KiB | 00m00s [ 7/182] Installing nspr-0:4.39.0-7.fc 100% | 309.5 MiB/s | 317.0 KiB | 00m00s [ 8/182] Installing nss-util-0:3.131.0 100% | 200.9 MiB/s | 205.7 KiB | 00m00s [ 9/182] Installing libarrow-doc-0:20. 100% | 0.0 B/s | 117.9 KiB | 00m00s [ 10/182] Installing python3-idna-0:3.1 100% | 37.0 MiB/s | 530.2 KiB | 00m00s [ 11/182] Installing openjpeg-0:2.5.4-1 100% | 223.8 MiB/s | 458.2 KiB | 00m00s [ 12/182] Installing fonts-filesystem-1 100% | 0.0 B/s | 788.0 B | 00m00s [ 13/182] Installing libaec-0:1.1.4-3.f 100% | 90.6 MiB/s | 92.8 KiB | 00m00s [ 14/182] Installing hdf5-0:1.14.6-6.fc 100% | 220.1 MiB/s | 6.4 MiB | 00m00s [ 15/182] Installing geos-0:3.14.1-1.fc 100% | 206.1 MiB/s | 4.1 MiB | 00m00s [ 16/182] Installing libwebp-0:1.6.0-2. 100% | 312.7 MiB/s | 960.7 KiB | 00m00s [ 17/182] Installing snappy-0:1.2.2-2.f 100% | 71.8 MiB/s | 73.5 KiB | 00m00s [ 18/182] Installing minizip-ng-compat- 100% | 159.5 MiB/s | 163.3 KiB | 00m00s [ 19/182] Installing freexl-0:2.0.0-15. 100% | 88.3 MiB/s | 90.5 KiB | 00m00s [ 20/182] Installing blosc-0:1.21.6-7.f 100% | 126.0 MiB/s | 129.0 KiB | 00m00s [ 21/182] Installing python3-typing-ins 100% | 95.2 MiB/s | 97.5 KiB | 00m00s [ 22/182] Installing libdeflate-0:1.26- 100% | 122.4 MiB/s | 125.3 KiB | 00m00s [ 23/182] Installing imath-0:3.1.12-4.f 100% | 186.5 MiB/s | 381.9 KiB | 00m00s [ 24/182] Installing libogg-2:1.3.6-2.f 100% | 0.0 B/s | 47.1 KiB | 00m00s [ 25/182] Installing openblas-0:0.3.29- 100% | 0.0 B/s | 113.5 KiB | 00m00s [ 26/182] Installing liblerc-0:4.0.0-9. 100% | 305.5 MiB/s | 625.6 KiB | 00m00s [ 27/182] Installing libquadmath-0:15.3 100% | 311.7 MiB/s | 319.2 KiB | 00m00s [ 28/182] Installing lcms2-0:2.16-6.fc4 100% | 212.6 MiB/s | 435.3 KiB | 00m00s [ 29/182] Installing python3-platformdi 100% | 184.4 MiB/s | 188.8 KiB | 00m00s [ 30/182] Installing python3-certifi-0: 100% | 10.9 MiB/s | 11.2 KiB | 00m00s [ 31/182] Installing libqhull_r-1:8.0.2 100% | 472.8 MiB/s | 484.1 KiB | 00m00s [ 32/182] Installing python3-six-0:1.17 100% | 117.5 MiB/s | 120.3 KiB | 00m00s [ 33/182] Installing python3-array-api- 100% | 172.3 MiB/s | 529.3 KiB | 00m00s [ 34/182] Installing python3-array-api- 100% | 236.9 MiB/s | 1.4 MiB | 00m00s [ 35/182] Installing python3-dateutil-1 100% | 290.1 MiB/s | 891.1 KiB | 00m00s [ 36/182] Installing openblas-openmp-0: 100% | 642.5 MiB/s | 43.7 MiB | 00m00s [ 37/182] Installing flexiblas-netlib-0 100% | 336.9 MiB/s | 16.5 MiB | 00m00s [ 38/182] Installing flexiblas-0:3.5.0- 100% | 0.0 B/s | 39.2 KiB | 00m00s [ 39/182] Installing flexiblas-openblas 100% | 13.0 MiB/s | 40.1 KiB | 00m00s [ 40/182] Installing python3-numpy-1:2. 100% | 365.6 MiB/s | 41.7 MiB | 00m00s [ 41/182] Installing python3-numpy-f2py 100% | 98.7 MiB/s | 2.2 MiB | 00m00s [ 42/182] Installing python3-contourpy- 100% | 212.4 MiB/s | 870.1 KiB | 00m00s [ 43/182] Installing openblas-openmp64- 100% | 654.1 MiB/s | 43.8 MiB | 00m00s [ 44/182] Installing flexiblas-openblas 100% | 0.0 B/s | 40.1 KiB | 00m00s [ 45/182] Installing flexiblas-netlib64 100% | 347.8 MiB/s | 16.7 MiB | 00m00s [ 46/182] Installing arpack-0:3.9.1-7.f 100% | 314.4 MiB/s | 643.9 KiB | 00m00s [ 47/182] Installing armadillo12-0:12.8 100% | 81.3 MiB/s | 83.2 KiB | 00m00s [ 48/182] Installing libtheora-1:1.1.1- 100% | 234.2 MiB/s | 479.7 KiB | 00m00s [ 49/182] Installing openexr-libs-0:3.2 100% | 503.6 MiB/s | 6.5 MiB | 00m00s [ 50/182] Installing librttopo-0:1.1.0- 100% | 247.3 MiB/s | 506.4 KiB | 00m00s [ 51/182] Installing dejavu-sans-fonts- 100% | 459.1 MiB/s | 5.5 MiB | 00m00s [ 52/182] Installing abattis-cantarell- 100% | 189.9 MiB/s | 194.4 KiB | 00m00s [ 53/182] Installing python3-anyio-0:4. 100% | 297.2 MiB/s | 1.5 MiB | 00m00s [ 54/182] Installing python3-urllib3-0: 100% | 294.8 MiB/s | 1.2 MiB | 00m00s [ 55/182] Installing nss-softokn-freebl 100% | 356.8 MiB/s | 1.1 MiB | 00m00s [ 56/182] Installing nss-softokn-0:3.13 100% | 403.8 MiB/s | 2.0 MiB | 00m00s [ 57/182] Installing nss-sysinit-0:3.13 100% | 1.6 MiB/s | 19.1 KiB | 00m00s [ 58/182] Installing nss-0:3.131.0-1.fc 100% | 159.3 MiB/s | 1.9 MiB | 00m00s [ 59/182] Installing python3-pydantic-c 100% | 382.2 MiB/s | 5.4 MiB | 00m00s [ 60/182] Installing python3-flexcache- 100% | 59.2 MiB/s | 60.6 KiB | 00m00s [ 61/182] Installing python3-flexparser 100% | 260.8 MiB/s | 267.1 KiB | 00m00s [ 62/182] Installing libharu-0:2.4.5-1. 100% | 282.5 MiB/s | 1.7 MiB | 00m00s [ 63/182] Installing libtirpc-0:1.3.7-1 100% | 197.6 MiB/s | 202.3 KiB | 00m00s [ 64/182] Installing hdf-libs-0:4.3.0-4 100% | 224.1 MiB/s | 688.3 KiB | 00m00s [ 65/182] Installing abseil-cpp-0:20250 100% | 251.5 MiB/s | 2.5 MiB | 00m00s [ 66/182] Installing libicu-0:77.1-1.fc 100% | 404.3 MiB/s | 36.4 MiB | 00m00s [ 67/182] Installing re2-2:20251105-1.f 100% | 285.5 MiB/s | 584.7 KiB | 00m00s [ 68/182] Installing protobuf-0:3.19.6- 100% | 408.7 MiB/s | 3.3 MiB | 00m00s [ 69/182] Installing liborc2-0:2.1.4-1. 100% | 359.8 MiB/s | 1.8 MiB | 00m00s [ 70/182] Installing boost-program-opti 100% | 275.2 MiB/s | 281.8 KiB | 00m00s [ 71/182] Installing uriparser-0:1.0.2- 100% | 13.0 MiB/s | 186.6 KiB | 00m00s [ 72/182] Installing libkml-0:1.3.0-56. 100% | 294.6 MiB/s | 1.2 MiB | 00m00s [ 73/182] Installing unixODBC-0:2.3.14- 100% | 63.5 MiB/s | 1.0 MiB | 00m00s [ 74/182] Installing gpgme-0:1.24.3-6.f 100% | 44.4 MiB/s | 590.4 KiB | 00m00s [ 75/182] Installing gpgmepp-0:1.24.3-6 100% | 210.1 MiB/s | 430.4 KiB | 00m00s [ 76/182] Installing poppler-data-0:0.4 100% | 399.7 MiB/s | 12.4 MiB | 00m00s [ 77/182] Installing mariadb-connector- 100% | 0.0 B/s | 27.2 KiB | 00m00s [ 78/182] Installing mariadb-connector- 100% | 243.7 MiB/s | 499.1 KiB | 00m00s [ 79/182] Installing thrift-0:0.20.0-8. 100% | 210.1 MiB/s | 5.5 MiB | 00m00s [ 80/182] Installing utf8proc-0:2.10.0- 100% | 364.7 MiB/s | 373.4 KiB | 00m00s [ 81/182] Installing libarrow-0:20.0.0- 100% | 501.8 MiB/s | 26.6 MiB | 00m00s [ 82/182] Installing parquet-libs-0:20. 100% | 412.3 MiB/s | 3.3 MiB | 00m00s [ 83/182] Installing libarrow-acero-lib 100% | 349.5 MiB/s | 1.4 MiB | 00m00s [ 84/182] Installing libarrow-dataset-l 100% | 367.6 MiB/s | 1.5 MiB | 00m00s [ 85/182] Installing giflib-0:5.2.2-9.f 100% | 115.0 MiB/s | 117.8 KiB | 00m00s [ 86/182] Installing cfitsio-0:4.6.3-1. 100% | 379.4 MiB/s | 1.9 MiB | 00m00s [ 87/182] Installing glib2-0:2.86.5-1.f 100% | 319.2 MiB/s | 15.0 MiB | 00m00s [ 88/182] Installing python3-olefile-0: 100% | 341.6 MiB/s | 349.8 KiB | 00m00s [ 89/182] Installing python3-charset-no 100% | 27.5 MiB/s | 365.8 KiB | 00m00s [ 90/182] Installing python3-requests-0 100% | 239.0 MiB/s | 489.5 KiB | 00m00s [ 91/182] Installing python3-pooch-0:1. 100% | 82.1 MiB/s | 672.8 KiB | 00m00s [ 92/182] Installing python3-scipy-0:1. 100% | 382.5 MiB/s | 66.9 MiB | 00m00s [ 93/182] Installing double-conversion- 100% | 97.3 MiB/s | 99.6 KiB | 00m00s [ 94/182] Installing python3-fsspec-0:2 100% | 273.3 MiB/s | 1.9 MiB | 00m00s [ 95/182] Installing python3-click-1:8. 100% | 390.3 MiB/s | 1.2 MiB | 00m00s [ 96/182] Installing pugixml-0:1.16-1.f 100% | 273.4 MiB/s | 279.9 KiB | 00m00s [ 97/182] Installing xerces-c-0:3.3.0-8 100% | 471.2 MiB/s | 3.8 MiB | 00m00s [ 98/182] Installing muParser-0:2.3.5-3 100% | 269.9 MiB/s | 552.7 KiB | 00m00s [ 99/182] Installing libpq-0:18.0-3.fc4 100% | 334.7 MiB/s | 1.0 MiB | 00m00s [100/182] Installing libgta-0:1.2.1-16. 100% | 65.9 MiB/s | 67.5 KiB | 00m00s [101/182] Installing google-noto-fonts- 100% | 0.0 B/s | 18.5 KiB | 00m00s [102/182] Installing google-noto-sans-v 100% | 347.8 MiB/s | 1.4 MiB | 00m00s [103/182] Installing default-fonts-core 100% | 17.8 MiB/s | 18.2 KiB | 00m00s [104/182] Installing CharLS-0:2.4.3-2.f 100% | 329.9 MiB/s | 337.8 KiB | 00m00s [105/182] Installing gdcm-0:3.0.24-14.f 100% | 476.6 MiB/s | 8.1 MiB | 00m00s [106/182] Installing libX11-common-0:1. 100% | 98.9 MiB/s | 1.2 MiB | 00m00s [107/182] Installing xml-common-0:0.6.3 100% | 79.2 MiB/s | 81.1 KiB | 00m00s [108/182] Installing pixman-0:0.46.2-2. 100% | 347.4 MiB/s | 711.4 KiB | 00m00s [109/182] Installing lzo-0:2.10-15.fc43 100% | 176.3 MiB/s | 180.5 KiB | 00m00s [110/182] Installing rply-0:1.1.4-11.fc 100% | 8.9 MiB/s | 118.4 KiB | 00m00s [111/182] Installing jbigkit-libs-0:2.1 100% | 112.7 MiB/s | 115.4 KiB | 00m00s [112/182] Installing libtiff-0:4.7.2-3. 100% | 207.9 MiB/s | 638.8 KiB | 00m00s [113/182] Installing dcmtk-0:3.7.0^2026 100% | 418.9 MiB/s | 42.7 MiB | 00m00s [114/182] Installing graphite2-0:1.3.14 100% | 14.6 MiB/s | 193.9 KiB | 00m00s [115/182] Installing freetype-0:2.13.3- 100% | 277.3 MiB/s | 851.8 KiB | 00m00s [116/182] Installing harfbuzz-0:11.5.1- 100% | 353.5 MiB/s | 2.8 MiB | 00m00s [117/182] Installing fontconfig-0:2.17. 100% | 758.0 KiB/s | 785.3 KiB | 00m01s [118/182] Installing poppler-0:25.07.0- 100% | 381.4 MiB/s | 3.8 MiB | 00m00s [119/182] Installing libXau-0:1.0.12-3. 100% | 72.7 MiB/s | 74.5 KiB | 00m00s [120/182] Installing libxcb-0:1.17.0-6. 100% | 270.0 MiB/s | 1.1 MiB | 00m00s [121/182] Installing libX11-0:1.8.13-1. 100% | 320.4 MiB/s | 1.3 MiB | 00m00s [122/182] Installing libXext-0:1.3.6-4. 100% | 89.1 MiB/s | 91.2 KiB | 00m00s [123/182] Installing libXrender-0:0.9.1 100% | 46.2 MiB/s | 47.3 KiB | 00m00s [124/182] Installing cairo-0:1.18.6-1.f 100% | 355.3 MiB/s | 1.8 MiB | 00m00s [125/182] Installing python3-cairo-0:1. 100% | 242.4 MiB/s | 496.4 KiB | 00m00s [126/182] Installing fribidi-0:1.0.16-3 100% | 14.5 MiB/s | 192.8 KiB | 00m00s [127/182] Installing libraqm-0:0.10.1-3 100% | 0.0 B/s | 29.7 KiB | 00m00s [128/182] Installing libimagequant-0:4. 100% | 225.4 MiB/s | 692.5 KiB | 00m00s [129/182] Installing python3-pillow-0:1 100% | 331.2 MiB/s | 4.3 MiB | 00m00s [130/182] Installing python3-kiwisolver 100% | 38.6 MiB/s | 157.9 KiB | 00m00s [131/182] Installing python3-fonttools- 100% | 358.6 MiB/s | 19.4 MiB | 00m00s [132/182] Installing python3-dotenv-0:1 100% | 76.2 MiB/s | 156.0 KiB | 00m00s [133/182] Installing proj-data-0:9.6.2- 100% | 514.5 MiB/s | 9.3 MiB | 00m00s [134/182] Installing proj-0:9.6.2-2.fc4 100% | 167.9 MiB/s | 4.5 MiB | 00m00s [135/182] Installing libgeotiff-0:1.7.4 100% | 22.1 MiB/s | 293.8 KiB | 00m00s [136/182] Installing libspatialite-0:5. 100% | 509.8 MiB/s | 15.3 MiB | 00m00s [137/182] Installing libzip-0:1.11.4-2. 100% | 133.7 MiB/s | 137.0 KiB | 00m00s [138/182] Installing netcdf-0:4.9.2-15. 100% | 123.5 MiB/s | 2.3 MiB | 00m00s [139/182] Installing libminc-0:2.4.03-2 100% | 226.6 MiB/s | 696.1 KiB | 00m00s [140/182] Installing gdal-libs-0:3.11.5 100% | 385.2 MiB/s | 31.2 MiB | 00m00s [141/182] Installing libraw1394-0:2.1.2 100% | 12.2 MiB/s | 162.2 KiB | 00m00s [142/182] Installing libdc1394-0:2.2.7- 100% | 344.5 MiB/s | 352.8 KiB | 00m00s [143/182] Installing jsoncpp-0:1.9.6-2. 100% | 253.1 MiB/s | 259.2 KiB | 00m00s [144/182] Installing fmt-0:11.2.0-3.fc4 100% | 262.0 MiB/s | 268.3 KiB | 00m00s [145/182] Installing viskores-0:1.2.0-3 100% | 639.6 MiB/s | 133.7 MiB | 00m00s [146/182] Installing vtk-0:9.7.0-7.fc43 100% | 542.9 MiB/s | 241.6 MiB | 00m00s [147/182] Installing python3-h11-0:0.16 100% | 140.6 MiB/s | 287.9 KiB | 00m00s [148/182] Installing python3-httpcore-0 100% | 213.5 MiB/s | 874.4 KiB | 00m00s [149/182] Installing python3-httpx-0:0. 100% | 328.0 MiB/s | 1.0 MiB | 00m00s [150/182] Installing expatpp-0:0-32.201 100% | 19.2 MiB/s | 39.3 KiB | 00m00s [151/182] Installing vxl-0:3.5.0-16.fc4 100% | 354.6 MiB/s | 53.2 MiB | 00m00s [152/182] Installing fftw-libs-single-0 100% | 400.0 MiB/s | 3.6 MiB | 00m00s [153/182] Installing fftw-libs-double-0 100% | 378.7 MiB/s | 3.4 MiB | 00m00s [154/182] Installing InsightToolkit5-0: 100% | 503.3 MiB/s | 28.7 MiB | 00m00s [155/182] Installing simpleitk-0:2.5.5- 100% | 624.3 MiB/s | 285.9 MiB | 00m00s [156/182] Installing libyaml-0:0.2.5-17 100% | 132.8 MiB/s | 136.0 KiB | 00m00s [157/182] Installing python3-pyyaml-0:6 100% | 262.8 MiB/s | 807.4 KiB | 00m00s [158/182] Installing python3-xmltodict- 100% | 57.1 MiB/s | 58.5 KiB | 00m00s [159/182] Installing python3-matplotlib 100% | 416.5 MiB/s | 7.9 MiB | 00m00s [160/182] Installing python3-pyparsing- 100% | 343.1 MiB/s | 1.0 MiB | 00m00s [161/182] Installing python3-cycler-0:0 100% | 39.3 MiB/s | 40.3 KiB | 00m00s [162/182] Installing python3-filelock-0 100% | 101.4 MiB/s | 103.9 KiB | 00m00s [163/182] Installing python3-annotated- 100% | 86.2 MiB/s | 88.2 KiB | 00m00s [164/182] Installing python3-pydantic-0 100% | 366.7 MiB/s | 5.1 MiB | 00m00s [165/182] Installing python3-markupsafe 100% | 64.2 MiB/s | 65.8 KiB | 00m00s [166/182] Installing python3-cached_pro 100% | 37.3 MiB/s | 38.2 KiB | 00m00s [167/182] Installing liblzf-0:3.6-33.fc 100% | 4.2 MiB/s | 51.9 KiB | 00m00s [168/182] Installing python3-h5py-0:3.1 100% | 347.8 MiB/s | 4.2 MiB | 00m00s [169/182] Installing python3-tqdm-0:4.6 100% | 38.9 MiB/s | 597.7 KiB | 00m00s [170/182] Installing python3-huggingfac 100% | 206.3 MiB/s | 6.6 MiB | 00m00s [171/182] Installing python3-pymatreade 100% | 68.6 MiB/s | 70.2 KiB | 00m00s [172/182] Installing python3-jinja2-0:3 100% | 386.5 MiB/s | 3.1 MiB | 00m00s [173/182] Installing python3-numpydanti 100% | 158.7 MiB/s | 650.0 KiB | 00m00s [174/182] Installing python3-pydantic-s 100% | 111.9 MiB/s | 573.0 KiB | 00m00s [175/182] Installing python3-matplotlib 100% | 425.9 MiB/s | 31.9 MiB | 00m00s [176/182] Installing python3-simpleitk- 100% | 579.8 MiB/s | 15.7 MiB | 00m00s [177/182] Installing python3-pint-0:0.2 100% | 144.4 MiB/s | 3.5 MiB | 00m00s [178/182] Installing python3-array-api- 100% | 175.2 MiB/s | 717.6 KiB | 00m00s [179/182] Installing python3-ipax-0:0.1 100% | 333.5 MiB/s | 3.0 MiB | 00m00s [180/182] Installing python3-safetensor 100% | 309.3 MiB/s | 950.1 KiB | 00m00s [181/182] Installing python3-regex-0:20 100% | 300.1 MiB/s | 2.1 MiB | 00m00s [182/182] Installing python3-pydicom-0: 100% | 88.9 MiB/s | 14.0 MiB | 00m00s Warning: skipped OpenPGP checks for 13 packages from repository: copr_base Complete! Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.nNhkpR + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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=43 + 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.fc43.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 78.1.1) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 8.3.1) /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:759: 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' /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:759: 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.3.5) 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.13.0) 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.9) 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.67.2) 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.fc43.x86_64-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.fc43.buildreqs.nosrc.rpm INFO: Going to install missing dynamic buildrequires Updating and loading repositories: Copr repository 100% | 10.9 KiB/s | 1.5 KiB | 00m00s fedora 100% | 50.5 KiB/s | 23.5 KiB | 00m00s updates 100% | 114.2 KiB/s | 18.6 KiB | 00m00s Repositories loaded. Package "pyproject-rpm-macros-1.24.0-1.fc43.noarch" is already installed. Package "python3-devel-3.14.8-1.fc43.x86_64" is already installed. Package "python3-pytest-8.3.5-9.fc43.noarch" is already installed. Package "python3-array-api-compat-1.15.0-1.fc43.noarch" is already installed. Package "python3-array-api-extra-0.11.5-1.fc43.noarch" is already installed. Package "python3-array-api-strict-2.0.1-7.fc43.noarch" is already installed. Package "python3-h5py-3.13.0-6.fc43.x86_64" is already installed. Package "python3-huggingface-hub-1.24.0-1.fc43.noarch" is already installed. Package "python3-ipax-0.13.0-1.fc43.noarch" is already installed. Package "python3-jinja2-3.1.6-6.fc43.noarch" is already installed. Package "python3-matplotlib-3.10.9-1.fc43.x86_64" is already installed. Package "python3-numpy-1:2.3.5-1.fc43.x86_64" is already installed. Package "python3-numpydantic-2.0.0-1.fc43.noarch" is already installed. Package "python3-packaging-25.0-7.fc43.noarch" is already installed. Package "python3-pint-0.25.2-1.fc43.noarch" is already installed. Package "python3-pip-25.1.1-19.fc43.noarch" is already installed. Package "python3-pydicom-3.0.2-1.fc43.noarch" is already installed. Package "python3-pymatreader-1.3.1-1.fc43.noarch" is already installed. Package "python3-regex-2026.9.10-1.fc43.x86_64" is already installed. Package "python3-safetensors-0.7.0-1.fc43.x86_64" is already installed. Package "python3-scipy-1.16.2-1.fc43.x86_64" is already installed. Package "python3-setuptools-78.1.1-15.fc43.noarch" is already installed. Package "python3-setuptools_scm-8.3.1-8.fc43.noarch" is already installed. Package "python3-simpleitk-2.5.5-12.fc43.x86_64" is already installed. Package "python3-tqdm-4.67.2-2.fc43.noarch" is already installed. Nothing to do. Building target platforms: x86_64 Building for target x86_64 setting SOURCE_DATE_EPOCH=1793923200 Executing(%generate_buildrequires): /bin/sh -e /var/tmp/rpm-tmp.crX1aq + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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=43 + 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.fc43.x86_64-pyproject-buildrequires --dep-overrides-file /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-pyproject-dep-overrides Handling setuptools>=64 from build-system.requires Requirement satisfied: setuptools>=64 (installed: setuptools 78.1.1) Handling setuptools-scm>=8 from build-system.requires Requirement satisfied: setuptools-scm>=8 (installed: setuptools-scm 8.3.1) /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:759: 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' /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:759: 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.3.5) 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.13.0) 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.9) 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.67.2) 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.fc43.x86_64-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.nsiq18 + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyradplan-0.8.0 Preparing metadata (pyproject.toml): started Running command Preparing metadata (pyproject.toml) /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:759: 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-6atd1u7o/pyRadPlan.egg-info writing /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/PKG-INFO writing dependency_links to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/dependency_links.txt writing entry points to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/entry_points.txt writing requirements to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/requires.txt writing top-level names to /builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/top_level.txt writing manifest file '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/pyRadPlan.egg-info/SOURCES.txt' reading manifest file '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/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-6atd1u7o/pyRadPlan.egg-info/SOURCES.txt' creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-modern-metadata-6atd1u7o/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) /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:759: 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-x86_64/wheel running install running install_lib creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/pyRadPlan creating build/bdist.linux-x86_64/wheel/pyRadPlan/data creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/ai_models copying build/lib/pyRadPlan/data/ai_models/model_config.template.json -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/ai_models creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/protons_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/photons_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/oxygen_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/helium_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/carbon_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/VHEE_Generic.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines copying build/lib/pyRadPlan/data/machines/VHEE_Focused.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/machines creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/phantoms copying build/lib/pyRadPlan/data/phantoms/TG119.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/phantoms creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/physics creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/physics/stopping copying build/lib/pyRadPlan/data/physics/stopping/SPtable.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/physics/stopping creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/rbe copying build/lib/pyRadPlan/data/rbe/RBEtable_LEMI_Scholz06_AX01_BX005.mat -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/rbe creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/topas creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/topas/input creating build/bdist.linux-x86_64/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-x86_64/wheel/./pyRadPlan/data/topas/input/beam_setup creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/topas/input/material_converter copying build/lib/pyRadPlan/data/topas/input/material_converter/TOPAS_schneider_converter.txt.in -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/material_converter creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_subscorer_LET.txt.in -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToWater.txt.in -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/scorer copying build/lib/pyRadPlan/data/topas/input/scorer/TOPAS_scorer_doseToMedium.txt.in -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/scorer creating build/bdist.linux-x86_64/wheel/pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/pyRadPlan_run_template.txt -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/patient_template.txt -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/template copying build/lib/pyRadPlan/data/topas/input/template/beamSetup_template.txt -> build/bdist.linux-x86_64/wheel/./pyRadPlan/data/topas/input/template creating build/bdist.linux-x86_64/wheel/pyRadPlan/ai creating build/bdist.linux-x86_64/wheel/pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_cst_agents.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_models.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_plan_agents.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_settings.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents copying build/lib/pyRadPlan/ai/agents/_usage.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/agents creating build/bdist.linux-x86_64/wheel/pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_load_model.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_preprocessor.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_registry.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_resolve.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/modelhub/_settings.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai/modelhub copying build/lib/pyRadPlan/ai/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ai creating build/bdist.linux-x86_64/wheel/pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_dvh.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_dvh_plot.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_qi.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/analysis copying build/lib/pyRadPlan/analysis/_units.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/analysis creating build/bdist.linux-x86_64/wheel/pyRadPlan/biology creating build/bdist.linux-x86_64/wheel/pyRadPlan/biology/models creating build/bdist.linux-x86_64/wheel/pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/const_rbe.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/kernel_based_lq_model.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/let_based_lq_models.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/lq_models.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/tabulated_rbe_models.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/_models/zstar_based_lq_model.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models/_models copying build/lib/pyRadPlan/biology/models/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_engine.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_evaluator.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_influence.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_kernel_sets.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_options.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_resolution.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models copying build/lib/pyRadPlan/biology/models/_tissue_lookup.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/models creating build/bdist.linux-x86_64/wheel/pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_conversion.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_presets.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_provenance.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_reference.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/tissues/_sources.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology/tissues copying build/lib/pyRadPlan/biology/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/biology creating build/bdist.linux-x86_64/wheel/pyRadPlan/core creating build/bdist.linux-x86_64/wheel/pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_backends.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_image_interpolation.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_interpolation.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_interpolation1d.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/_reductions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/compat.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/helpers.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/jittable.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/xp_utils/typing.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core/xp_utils copying build/lib/pyRadPlan/core/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_base_data.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_configurable.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_exceptions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_grids.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_paths.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_progress.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/_units.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/datamodel.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/np2sitk.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core copying build/lib/pyRadPlan/core/resample.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/core creating build/bdist.linux-x86_64/wheel/pyRadPlan/cst copying build/lib/pyRadPlan/cst/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/cst copying build/lib/pyRadPlan/cst/_cst.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/cst copying build/lib/pyRadPlan/cst/_voi.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/cst creating build/bdist.linux-x86_64/wheel/pyRadPlan/ct copying build/lib/pyRadPlan/ct/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ct copying build/lib/pyRadPlan/ct/_ct.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ct copying build/lib/pyRadPlan/ct/_hlut.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/ct creating build/bdist.linux-x86_64/wheel/pyRadPlan/dij copying build/lib/pyRadPlan/dij/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dij copying build/lib/pyRadPlan/dij/_compose_beam_dijs.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dij copying build/lib/pyRadPlan/dij/_dij.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dij creating build/bdist.linux-x86_64/wheel/pyRadPlan/dose creating build/bdist.linux-x86_64/wheel/pyRadPlan/dose/engines creating build/bdist.linux-x86_64/wheel/pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/kernels/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/kernels/_calc_geo_dists_kernel.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines/kernels copying build/lib/pyRadPlan/dose/engines/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_montecarlo.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_pencilbeam.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_base_pencilbeam_particle.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_fredmc.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_hongpb.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_particle_cutoff.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_sparse_output.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_svdpb.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/engines/_topasmc.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose/engines copying build/lib/pyRadPlan/dose/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose copying build/lib/pyRadPlan/dose/_calc_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/dose creating build/bdist.linux-x86_64/wheel/pyRadPlan/geometry copying build/lib/pyRadPlan/geometry/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/geometry copying build/lib/pyRadPlan/geometry/lps.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/geometry creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/assets creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/pyradplan_logo_skull_square.svg -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/pyradplan_logo_full_landscape.svg -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/dkfz_logo_white.svg -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/logos/dkfz_logo_blue.svg -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/assets/logos copying build/lib/pyRadPlan/gui/assets/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/assets creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_base_data.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_edit.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_file.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_help.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_settings.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus copying build/lib/pyRadPlan/gui/menus/_view.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/menus creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/ai copying build/lib/pyRadPlan/gui/widgets/ai/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/ai copying build/lib/pyRadPlan/gui/widgets/ai/_ai_task_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/ai creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_dvh.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_gamma.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_qi.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/analysis copying build/lib/pyRadPlan/gui/widgets/analysis/_qi_point_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/analysis creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/_optimization_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/optimization copying build/lib/pyRadPlan/gui/widgets/optimization/_status_window.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/optimization creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_optimization_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_plan_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/plan copying build/lib/pyRadPlan/gui/widgets/plan/_tissue_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/plan creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_labels.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_orientation_marker.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/_save_result_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/quantity_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/viewer_options_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/visualization_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result copying build/lib/pyRadPlan/gui/widgets/result/vois_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/result creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_binary_import_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_dicom_import_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_image_import_dialog.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/workflow/_workflow_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets/workflow copying build/lib/pyRadPlan/gui/widgets/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_analysis_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_config_form.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_display_names.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_info_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_log_console.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_logo_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_plot_theme.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_quantity_selector.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_result_widget.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_tissue_params.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets copying build/lib/pyRadPlan/gui/widgets/_ui_mode.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/widgets creating build/bdist.linux-x86_64/wheel/pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_analysis_win.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_main_win.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_result_win.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/windows/_splash_win.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui/windows copying build/lib/pyRadPlan/gui/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui copying build/lib/pyRadPlan/gui/apps.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui copying build/lib/pyRadPlan/gui/workspace.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/gui creating build/bdist.linux-x86_64/wheel/pyRadPlan/io copying build/lib/pyRadPlan/io/.gitkeep -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/base copying build/lib/pyRadPlan/io/base/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/base creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_common.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_cst.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_ct.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_export_seg.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_handler.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_helpers.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_cst.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_ct.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_import_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom copying build/lib/pyRadPlan/io/dicom/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/dicom creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_handler.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/matlab copying build/lib/pyRadPlan/io/matlab/_matfile.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/matlab creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_handler.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/npz copying build/lib/pyRadPlan/io/npz/_serialize.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/npz creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_handler.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/pickle copying build/lib/pyRadPlan/io/pickle/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/pickle creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/sitk_based creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_exporter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_importer.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/base copying build/lib/pyRadPlan/io/sitk_based/base/_serialize.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/base creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/sitk_based/meta_image copying build/lib/pyRadPlan/io/sitk_based/meta_image/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/meta_image creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/sitk_based/nifti copying build/lib/pyRadPlan/io/sitk_based/nifti/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/nifti creating build/bdist.linux-x86_64/wheel/pyRadPlan/io/sitk_based/nrrd copying build/lib/pyRadPlan/io/sitk_based/nrrd/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based/nrrd copying build/lib/pyRadPlan/io/sitk_based/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based copying build/lib/pyRadPlan/io/sitk_based/_binary_import.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io/sitk_based copying build/lib/pyRadPlan/io/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_helpers.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io copying build/lib/pyRadPlan/io/_load_save.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/io creating build/bdist.linux-x86_64/wheel/pyRadPlan/machines creating build/bdist.linux-x86_64/wheel/pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_beam_modifier.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_external_beam.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base copying build/lib/pyRadPlan/machines/base/_internal_beam.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/base creating build/bdist.linux-x86_64/wheel/pyRadPlan/machines/particles creating build/bdist.linux-x86_64/wheel/pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_ions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/kernel/_vhee.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles/kernel copying build/lib/pyRadPlan/machines/particles/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_cutoff.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_emittance.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_energy.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_focus.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_beam_fragment_spectrum.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_ions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles copying build/lib/pyRadPlan/machines/particles/_vhee.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/particles creating build/bdist.linux-x86_64/wheel/pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_calculate_machine_scale.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_linac.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/photons/_svd_kernel.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines/photons copying build/lib/pyRadPlan/machines/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines copying build/lib/pyRadPlan/machines/_load.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines copying build/lib/pyRadPlan/machines/_validate.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/machines creating build/bdist.linux-x86_64/wheel/pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/.gitkeep -> build/bdist.linux-x86_64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_engine.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_matlab.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/matRad copying build/lib/pyRadPlan/matRad/_octave.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/matRad creating build/bdist.linux-x86_64/wheel/pyRadPlan/optimization creating build/bdist.linux-x86_64/wheel/pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_eud.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_max_dvh.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_mean.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_min_dvh.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_objective.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_dev.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_mimicking.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_over.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_squared_under.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_std.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives copying build/lib/pyRadPlan/optimization/objectives/_variance.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/objectives creating build/bdist.linux-x86_64/wheel/pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_nonlin_fluence.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_optiprob.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/problems copying build/lib/pyRadPlan/optimization/problems/_simple_least_squares.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/problems creating build/bdist.linux-x86_64/wheel/pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_composite_worst_case.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_expected_quantity.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_expected_value.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_none.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_objective_worst_case.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_smooth_max.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_terms.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_utils.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness copying build/lib/pyRadPlan/optimization/robustness/_voxel_worst_case.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/robustness creating build/bdist.linux-x86_64/wheel/pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_base_solvers.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_ipax_solver.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_ipopt.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/solvers/_scipy_solver.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization/solvers copying build/lib/pyRadPlan/optimization/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization copying build/lib/pyRadPlan/optimization/_fluence_optimization.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/optimization creating build/bdist.linux-x86_64/wheel/pyRadPlan/plan copying build/lib/pyRadPlan/plan/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/plan copying build/lib/pyRadPlan/plan/_plans.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/plan creating build/bdist.linux-x86_64/wheel/pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_alpha_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_effect.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_let.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_let_x_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_rbe_x_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_resolver.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities copying build/lib/pyRadPlan/quantities/_sqrt_beta_dose.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/quantities creating build/bdist.linux-x86_64/wheel/pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_kernels.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_kernels_numba.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/raytracer copying build/lib/pyRadPlan/raytracer/_siddon.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/raytracer creating build/bdist.linux-x86_64/wheel/pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_dimensions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_distributions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_explicit.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_gridded.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_importance.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_legacy.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_nominal.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_random.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_set.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios copying build/lib/pyRadPlan/scenarios/_worst_case.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/scenarios creating build/bdist.linux-x86_64/wheel/pyRadPlan/stf creating build/bdist.linux-x86_64/wheel/pyRadPlan/stf/hlutLibrary copying build/lib/pyRadPlan/stf/hlutLibrary/matRad_default.hlut -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/hlutLibrary creating build/bdist.linux-x86_64/wheel/pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_base.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_externalbeam.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_factory.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_ions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_photons.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/generators/_vhee.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf/generators copying build/lib/pyRadPlan/stf/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_beam.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_beamlet.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_exceptions.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_generate_stf.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_presets.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_rangeshifter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_ray.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf copying build/lib/pyRadPlan/stf/_steeringinformation.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/stf creating build/bdist.linux-x86_64/wheel/pyRadPlan/util copying build/lib/pyRadPlan/util/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/_jupyter.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/helpers.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/keyboard_listener.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/logging_utils.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util copying build/lib/pyRadPlan/util/openmp.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/util creating build/bdist.linux-x86_64/wheel/pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/_plot_multiple_slices.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/visualization/_plot_slice.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan/visualization copying build/lib/pyRadPlan/__init__.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan copying build/lib/pyRadPlan/_lazy.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan copying build/lib/pyRadPlan/_settings.py -> build/bdist.linux-x86_64/wheel/./pyRadPlan running install_egg_info Copying pyRadPlan.egg-info to build/bdist.linux-x86_64/wheel/./pyRadPlan-0.8.0-py3.14.egg-info running install_scripts creating build/bdist.linux-x86_64/wheel/pyradplan-0.8.0.dist-info/WHEEL creating '/builddir/build/BUILD/python-pyradplan-0.8.0-build/.pyproject-builddir/pip-wheel-2lc8wx5t/.tmp-aobx5hy0/pyradplan-0.8.0-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/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-x86_64/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=32327555 sha256=94b5f21105c16a95ea17ed6b4e568dbf5b738c17e03b217665043a1bdcf39dd9 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.zOeOed + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 ++ xargs basename --multiple ++ ls /builddir/build/BUILD/python-pyradplan-0.8.0-build/pyproject-wheeldir/pyradplan-0.8.0-py3-none-any.whl ++ 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 25.1.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.fc43.x86_64-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.fc43.x86_64-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.fc43.x86_64-pyproject-dep-overrides ']' ++ wc -l /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-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.fc43.x86_64-pyproject-files --output-modules /builddir/build/BUILD/python-pyradplan-0.8.0-build/python-pyradplan-0.8.0-1.fc43.x86_64-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.fc43.x86_64-pyproject-record --prefix /usr pyRadPlan + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-ldconfig + /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-determinism --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__/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/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/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/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__/_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/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__/_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__/_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/__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/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/__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/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__/__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__/_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/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__/_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/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__/_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__/_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__/_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/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__/__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__/_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/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/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__/_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/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/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__/_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__/_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/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__/_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/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/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/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__/_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/__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__/_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/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__/_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/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/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__/_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/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/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/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__/_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__/_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__/_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__/_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__/_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__/_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/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/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__/__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/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/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/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/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__/_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/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_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__/_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_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__/_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__/_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/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/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__/_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__/_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/__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/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/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__/_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/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/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/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/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_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/__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__/_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/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/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/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/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/__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/__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/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/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/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/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/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/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/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/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/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/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/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/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__/__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/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/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__/_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/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/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__/_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/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__/_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__/_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_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__/_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__/_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__/_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/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__/_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__/_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__/_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/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/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/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/__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/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/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/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/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/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__/_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__/_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/__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__/_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__/_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/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/__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__/__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__/_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__/_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/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__/_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/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/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__/_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/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/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__/_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__/_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/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/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__/_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__/__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__/__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/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/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/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/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/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__/_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__/_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__/_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__/_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__/_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/__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/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/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/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/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/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/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__/_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/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/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__/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__/_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/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__/_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/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__/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__/_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__/_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__/__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__/_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__/_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__/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__/_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__/_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__/_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/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/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/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/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/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__/_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/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/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/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__/_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/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__/_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/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/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__/_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/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__/_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__/_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/__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__/_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__/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__/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/__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/_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/_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/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/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_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/__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/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/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/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/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__/_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__/_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/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__/_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__/_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__/__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 Executing(%check): /bin/sh -e /var/tmp/rpm-tmp.dDG380 + 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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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.fc43.x86_64-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.fc43.x86_64-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 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -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.8, pytest-8.3.5, 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 0x7f51adc042f0> 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 0x7f51adc04c20> 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 0x7f51a3234160> 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 0x7f51adc042f0> 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 0x7f51adc11a90> 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 0x7f51a1748180> 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 0x7f51a17488a0> 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 0x7f51a2716d50> 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 0x7f51a3237240> @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 0x7f51a32357b0> @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 0x7f51a32b9b50> @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 0x7f51a1616250> @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 0x7f51a1636030> @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 0x7f51a1635c70> @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 0x7f51a132e970> @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 0x7f51a1903bd0> @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 0x7f51a1a7c7a0> 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 0x7f51a1773620> 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 0x7f51a17af700> 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 0x7f51ae51d940> 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 0x7f51ae51d470> 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 0x7f51a196bee0> 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 0x7f51ae570ad0> 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 0x7f51a0bb73d0> 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 0x7f518672b8a0> 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 0x7f51a0228600> 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.23858 , 10.549352 , 11.840602 , 10.603649 , 11.967773 , 5.453381 , 12.007432 , 10.000741 , ... 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.521752 , 7.7439146, 11.06683 , 10.885351 , 11.675577 , 15.509579 , 7.965419 , 9.880358 , 1... 10.343923 , 9.865117 , 6.355603 , 12.273873 , 12.153698 , 10.404239 ], 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.666314 , 9.0304165, 7.779864 , 6.5125656, 1... 11.938342 , 11.60448 , 10.413535 , 8.711117 , 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.840266 , 12.32343 , 8.011889 , 12.554123 , 8.772326 , 10.576969 , 7.7545686, 7.588301 , 1... 12.832273 , 9.58289 , 8.894093 , 12.701789 , 8.755134 , 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.23858 , 10.549352 , 11.840602 , 10.603649 , 11.967773 , 5.453381 , 12.007432 , 10.000741 , ... 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([ 2., 92., 2., 2., 2., 2., 2., 2., 92., 2., 2., 2., 92., 2., 2., 2., 2., 2., 2., 2...., 92., 92., 2., 92., 92., 2., 2., 2., 2., 92., 2., 2., 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 , 4.7914815, 4.7914815, 4.7914815, 4.7914815, 0.2 , 0.2 , 4.7914815... , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.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_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 0x7f51adc89e10> 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 0x7f51adc8a900> 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/core/xp_utils/test_reductions.py::test_nan_and_initial[numpy] test/core/xp_utils/test_reductions.py::test_nan_initial[numpy] /builddir/build/BUILD/python-pyradplan-0.8.0-build/BUILDROOT/usr/lib/python3.14/site-packages/pyRadPlan/core/xp_utils/_reductions.py:56: RuntimeWarning: invalid value encountered in maximum xp.maximum.at(result, groups, values) 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:1518: 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, 11561 warnings, 28 errors in 123.17s (0:02:03) = error: Bad exit status from /var/tmp/rpm-tmp.dDG380 (%check) Bad exit status from /var/tmp/rpm-tmp.dDG380 (%check) RPM build errors: Finish: rpmbuild python-pyradplan-0.8.0-1.fc43.src.rpm Finish: build phase for python-pyradplan-0.8.0-1.fc43.src.rpm INFO: chroot_scan: 1 files copied to /var/lib/copr-rpmbuild/results/chroot_scan INFO: /var/lib/mock/fedora-43-x86_64-1794040424.263307/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.fc43.src.rpm) Config(fedora-43-x86_64) 2 minutes 38 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 8ceb47addbd14b01871c75db1b4f69a2 -D /var/lib/mock/fedora-43-x86_64-1794040424.263307/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 x86_64 /builddir/build/originals/python-pyradplan.spec' Copr build error: Build failed