diff --git a/explore.ipynb b/explore.ipynb new file mode 100644 index 0000000..07d12ca --- /dev/null +++ b/explore.ipynb @@ -0,0 +1,199 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from funlib.persistence import Array\n", + "\n", + "import numpy as np\n", + "\n", + "import zarr" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "container = zarr.open(\"example.zarr\")\n", + "shape = (2, 3, 3)\n", + "\n", + "ds = container.create_dataset(\n", + " \"raw\",\n", + " chunks=(1, 3, 3),\n", + " dtype=\"f4\",\n", + " data=np.random.randn(*shape),\n", + " overwrite=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 0.44273075 -0.17070776 -0.7056614 ]\n", + " [ 0.99363405 -0.7815089 1.3557754 ]\n", + " [ 0.5848475 0.59523624 -1.4611949 ]]\n", + "\n", + " [[ 0.09116387 -1.4376557 0.5421799 ]\n", + " [ 1.1627685 1.9053004 1.2552763 ]\n", + " [ 0.2825793 -0.8584084 -1.4131508 ]]]\n" + ] + } + ], + "source": [ + "array = Array(ds, (0, 0), (1, 1))\n", + "print(array[array.roi])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 0.09116387 -1.4376557 0.5421799 ]\n", + " [ 1.1627685 1.9053004 1.2552763 ]\n", + " [ 0.2825793 -0.8584084 -1.4131508 ]]]\n" + ] + } + ], + "source": [ + "array_sliced = Array(ds, (0, 0), (1, 1), adapter=slice(1,2))\n", + "print(array_sliced[array_sliced.roi])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[10.091164 8.562345 10.54218 ]\n", + " [11.162768 11.9053 11.255277]\n", + " [10.282579 9.141592 8.586849]]]\n" + ] + } + ], + "source": [ + "array_sliced[array_sliced.roi] = array_sliced[array_sliced.roi] + 10\n", + "print(array_sliced[array_sliced.roi])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[[ 0.44273075 -0.17070776 -0.7056614 ]\n", + " [ 0.99363405 -0.7815089 1.3557754 ]\n", + " [ 0.5848475 0.59523624 -1.4611949 ]]\n", + "\n", + " [[10.091164 8.562345 10.54218 ]\n", + " [11.162768 11.9053 11.255277 ]\n", + " [10.282579 9.141592 8.586849 ]]]\n" + ] + } + ], + "source": [ + "print(ds[:])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bool\n", + "[[[False False False]\n", + " [False False False]\n", + " [False False False]]\n", + "\n", + " [[ True True True]\n", + " [ True True True]\n", + " [ True True True]]]\n" + ] + } + ], + "source": [ + "thresholded = Array(ds, (0, 0), (1, 1), adapter=lambda x: x > 5)\n", + "print(thresholded.dtype)\n", + "print(thresholded[thresholded.roi])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "ename": "RuntimeError", + "evalue": "This array is not writeable since you have applied a custom callable adapter that may or may not be invertable.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mthresholded\u001b[49m\u001b[43m[\u001b[49m\u001b[43mthresholded\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mroi\u001b[49m\u001b[43m]\u001b[49m \u001b[38;5;241m=\u001b[39m thresholded[thresholded\u001b[38;5;241m.\u001b[39mroi] \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m10\u001b[39m\n", + "File \u001b[0;32m~/Work/Packages/funlib.persistence/funlib/persistence/arrays/array.py:211\u001b[0m, in \u001b[0;36mArray.__setitem__\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 209\u001b[0m da\u001b[38;5;241m.\u001b[39mstore(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdata[roi_slices], \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_source_data, regions\u001b[38;5;241m=\u001b[39mroi_slices)\n\u001b[1;32m 210\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 211\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[1;32m 212\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThis array is not writeable since you have applied a custom callable \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 213\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124madapter that may or may not be invertable.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 214\u001b[0m )\n", + "\u001b[0;31mRuntimeError\u001b[0m: This array is not writeable since you have applied a custom callable adapter that may or may not be invertable." + ] + } + ], + "source": [ + "\n", + "thresholded[thresholded.roi] = thresholded[thresholded.roi] + 10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "funlib.persistence", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/funlib/persistence/arrays/array.py b/funlib/persistence/arrays/array.py index fe6de92..ba45bd7 100644 --- a/funlib/persistence/arrays/array.py +++ b/funlib/persistence/arrays/array.py @@ -128,7 +128,11 @@ def dtype(self): def is_writeable(self): return len(self.adapter) == 0 or all( [ - isinstance(adapter, slice) or isinstance(adapter, list[slice]) + isinstance(adapter, slice) + or ( + isinstance(adapter, Iterable) + and all([isinstance(a, slice) for a in adapter]) + ) for adapter in self.adapter ] ) @@ -161,7 +165,7 @@ def __getitem__(self, key) -> np.ndarray: % (roi, self.roi) ) - return self.data[self.__slices(roi)] + return self.data[self.__slices(roi)].compute() elif isinstance(key, Coordinate): coordinate = key @@ -173,7 +177,7 @@ def __getitem__(self, key) -> np.ndarray: return self.data[index].compute() else: - return self.data[key] + return self.data[key].compute() def __setitem__(self, key, value: np.ndarray): """Set the data of this array within the given ROI. @@ -203,6 +207,11 @@ def __setitem__(self, key, value: np.ndarray): self.data[roi_slices] = value da.store(self.data[roi_slices], self._source_data, regions=roi_slices) + else: + raise RuntimeError( + "This array is not writeable since you have applied a custom callable " + "adapter that may or may not be invertable." + ) def to_ndarray(self, roi, fill_value=0): """An alternative implementation of `__getitem__` that supports @@ -268,8 +277,6 @@ def _combine_slices( slice(slice_range.start, slice_range.stop, slice_range.step) ) - print(roi_slices, combined_slices) - return tuple(combined_slices) def __slices(self, roi, check_chunk_align=False): @@ -299,7 +306,7 @@ def __slices(self, roi, check_chunk_align=False): ] combined_slice = self._combine_slices(roi_slices, *adapter_slices) - + return combined_slice def __index(self, coordinate):