Wrap a NumPy array to use explicit indexing.
| 1680 | |
| 1681 | |
| 1682 | class NumpyIndexingAdapter(IndexingAdapter): |
| 1683 | """Wrap a NumPy array to use explicit indexing.""" |
| 1684 | |
| 1685 | __slots__ = ("array",) |
| 1686 | |
| 1687 | def __init__(self, array): |
| 1688 | # In NumpyIndexingAdapter we only allow to store bare np.ndarray |
| 1689 | if not isinstance(array, np.ndarray): |
| 1690 | raise TypeError( |
| 1691 | "NumpyIndexingAdapter only wraps np.ndarray. " |
| 1692 | f"Trying to wrap {type(array)}" |
| 1693 | ) |
| 1694 | self.array = array |
| 1695 | |
| 1696 | def transpose(self, order): |
| 1697 | return self.array.transpose(order) |
| 1698 | |
| 1699 | def _oindex_get(self, indexer: OuterIndexer): |
| 1700 | key = _outer_to_numpy_indexer(indexer, self.array.shape) |
| 1701 | return self.array[key] |
| 1702 | |
| 1703 | def _vindex_get(self, indexer: VectorizedIndexer): |
| 1704 | _assert_not_chunked_indexer(indexer.tuple) |
| 1705 | array = NumpyVIndexAdapter(self.array) |
| 1706 | return array[indexer.tuple] |
| 1707 | |
| 1708 | def __getitem__(self, indexer: ExplicitIndexer): |
| 1709 | self._check_and_raise_if_non_basic_indexer(indexer) |
| 1710 | |
| 1711 | array = self.array |
| 1712 | # We want 0d slices rather than scalars. This is achieved by |
| 1713 | # appending an ellipsis (see |
| 1714 | # https://numpy.org/doc/stable/reference/arrays.indexing.html#detailed-notes). |
| 1715 | key = indexer.tuple + (Ellipsis,) |
| 1716 | return array[key] |
| 1717 | |
| 1718 | def _safe_setitem(self, array, key: tuple[Any, ...], value: Any) -> None: |
| 1719 | try: |
| 1720 | array[key] = value |
| 1721 | except ValueError as exc: |
| 1722 | # More informative exception if read-only view |
| 1723 | if not array.flags.writeable and not array.flags.owndata: |
| 1724 | raise ValueError( |
| 1725 | "Assignment destination is a view. " |
| 1726 | "Do you want to .copy() array first?" |
| 1727 | ) from exc |
| 1728 | else: |
| 1729 | raise exc |
| 1730 | |
| 1731 | def _oindex_set(self, indexer: OuterIndexer, value: Any) -> None: |
| 1732 | key = _outer_to_numpy_indexer(indexer, self.array.shape) |
| 1733 | self._safe_setitem(self.array, key, value) |
| 1734 | |
| 1735 | def _vindex_set(self, indexer: VectorizedIndexer, value: Any) -> None: |
| 1736 | array = NumpyVIndexAdapter(self.array) |
| 1737 | self._safe_setitem(array, indexer.tuple, value) |
| 1738 | |
| 1739 | def __setitem__(self, indexer: ExplicitIndexer, value: Any) -> None: |
no outgoing calls
searching dependent graphs…