diff --git a/examples/simple.ipynb b/examples/simple.ipynb index 2d4961ac3..9ca764283 100644 --- a/examples/simple.ipynb +++ b/examples/simple.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "fb57c3d3-f20d-4d88-9e7a-04b9309bc637", "metadata": {}, "outputs": [], @@ -34,52 +34,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "237823b7-e2c0-4e2f-9ee8-e3fc2b4453c4", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "22e188ba0769451ba369b4a5a2d5d313", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "997ba4e4d8b540ffa3f100c2fde27920", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# create a `Plot` instance\n", "plot = Plot()\n", @@ -112,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "de816c88-1c4a-4071-8a5e-c46c93671ef5", "metadata": {}, "outputs": [], @@ -122,7 +80,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "09350854-5058-4574-a01d-84d00e276c57", "metadata": {}, "outputs": [], @@ -132,7 +90,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "83b2db1b-2783-4e89-bcf3-66bb6e09e18a", "metadata": {}, "outputs": [], @@ -143,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "3e298c1c-7551-4401-ade0-b9af7d2bbe23", "metadata": {}, "outputs": [], @@ -161,42 +119,20 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "e6ba689c-ff4a-44ef-9663-f2c8755072c4", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('random-image': ImageGraphic @ 0x7fbb681a1360,)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "plot.graphics" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "5b18f4e3-e13b-46d5-af1f-285c5a7fdc12", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'random-image': ImageGraphic @ 0x7fbb681a1360" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "plot[\"random-image\"]" ] @@ -211,42 +147,20 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "2b5c1321-1fd4-44bc-9433-7439ad3e22cf", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'random-image': ImageGraphic @ 0x7fbb681a1360" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "image_graphic" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "b12bf75e-4e93-4930-9146-e96324fdf3f6", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "image_graphic is plot[\"random-image\"]" ] @@ -265,52 +179,10 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "aadd757f-6379-4f52-a709-46aa57c56216", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "543d56b0c4fa4eb18927358bd7d0d2fa", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ca2343e7c6294dddb4d71253c5dd0050", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# create another `Plot` instance\n", "plot_v = Plot()\n", @@ -348,52 +220,10 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "86e70b1e-4328-4035-b992-70dff16d2a69", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2fca1a70597f4f2c813245b472557980", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "655dee7f343d4ad1b9d1dca8bf499fa2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "plot_sync = Plot(controller=plot_v.controller)\n", "\n", @@ -430,25 +260,10 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "ef9743b3-5f81-4b79-9502-fa5fca08e56d", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "98e198424c434dfcaf932bdf67e8c1b2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(JupyterWgpuCanvas(frame_feedback={'index': 211, 'timestamp': 1673222194.8195093, 'localtime': 1…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "VBox([plot_v.show(), plot_sync.show()])" ] @@ -464,25 +279,10 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "11839d95-8ff7-444c-ae13-6b072c3112c5", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f97d3b3fd53040388be0f2527a832b41", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(JupyterWgpuCanvas(frame_feedback={'index': 236, 'timestamp': 1673222197.978218, 'localtime': 16…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "HBox([plot_v.show(), plot_sync.show()])" ] @@ -507,7 +307,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "0bcedf83-cbdd-4ec2-b8d5-172aa72a3e04", "metadata": {}, "outputs": [], @@ -582,21 +382,10 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "8b560151-c258-415c-a20d-3cccd421f44a", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1000, 512, 512)" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "movie.shape" ] @@ -619,39 +408,10 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "62166a9f-ab43-45cc-a6db-6d441387e9a5", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "716bb151456446c283aa842c008fc805", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6ef37682df3f409b8d2a7ac36974d7ce", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(JupyterWgpuCanvas(), IntSlider(value=0, max=999)))" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "plot_movie = Plot()\n", "\n", @@ -710,7 +470,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "8e8280da-b421-43a5-a1a6-2a196a408e9a", "metadata": {}, "outputs": [], @@ -741,52 +501,10 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "93a5d1e6-d019-4dd0-a0d1-25d1704ab7a7", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5a78ff5b74a64ba28afcd7844a5bd1de", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "59f97de592804347a60996be35bcab2c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Create a plot instance\n", "plot_l = Plot()\n", @@ -804,6 +522,48 @@ "plot_l.show()" ] }, + { + "cell_type": "markdown", + "id": "22dde600-0f56-4370-b017-c8f23a6c01aa", + "metadata": {}, + "source": [ + "### \"stretching\" the camera, useful for large timeseries data\n", + "\n", + "Set `maintain_aspect = False` on a camera, and then use the right mouse button and move the mouse to stretch and squeeze the view!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2695f023-f6ce-4e26-8f96-4fbed5510d1d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plot_l.camera.maintain_aspect = False" + ] + }, + { + "cell_type": "markdown", + "id": "1651e965-f750-47ac-bf53-c23dae84cc98", + "metadata": {}, + "source": [ + "### reset the plot area" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba50a6ed-0f1b-4795-91dd-a7c3e40b8e3c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plot_l.auto_scale(maintain_aspect=True)" + ] + }, { "cell_type": "markdown", "id": "dcd68796-c190-4c3f-8519-d73b98ff6367", @@ -814,7 +574,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "cb0d13ed-ef07-46ff-b19e-eeca4c831037", "metadata": {}, "outputs": [], @@ -842,7 +602,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "cfa001f6-c640-4f91-beb0-c19b030e503f", "metadata": {}, "outputs": [], @@ -856,32 +616,10 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "bb8a0f95-0063-4cd4-a117-e3d62c6e120d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "FeatureEvent @ 0x7fbacc955060\n", - "type: colors\n", - "pick_info: {'index': range(15, 50, 3), 'collection-index': None, 'world_object': , 'new_data': array([[0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.],\n", - " [0., 1., 1., 1.]], dtype=float32)}\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# more complex indexing of colors\n", "# from point 15 - 30, set every 3rd point as \"cyan\"\n", @@ -898,7 +636,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "d1a4314b-5723-43c7-94a0-b4cbb0e44d60", "metadata": {}, "outputs": [], @@ -909,7 +647,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "682db47b-8c7a-4934-9be4-2067e9fb12d5", "metadata": {}, "outputs": [], @@ -927,7 +665,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "fcba75b7-9a1e-4aae-9dec-715f7f7456c3", "metadata": {}, "outputs": [], @@ -937,7 +675,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "763b9943-53a4-4e2a-b47a-4e9e5c9d7be3", "metadata": {}, "outputs": [], @@ -955,7 +693,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "id": "64a20a16-75a5-4772-a849-630ade9be4ff", "metadata": {}, "outputs": [], @@ -965,7 +703,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "id": "fb093046-c94c-4085-86b4-8cd85cb638ff", "metadata": {}, "outputs": [], @@ -975,7 +713,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "id": "f05981c3-c768-4631-ae62-6a8407b20c4c", "metadata": {}, "outputs": [], @@ -993,60 +731,10 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "9c51229f-13a2-4653-bff3-15d43ddbca7b", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4beed0a67834408aa4549374af4b36d8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/kushalk/repos/fastplotlib/fastplotlib/layouts/_base.py:214: UserWarning: `center_scene()` not yet implemented for `PerspectiveCamera`\n", - " warn(\"`center_scene()` not yet implemented for `PerspectiveCamera`\")\n" - ] - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "52aa9698dbe2430099c3d88159bcb47b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# just set the camera as \"3d\", the rest is basically the same :D \n", "plot_l3d = Plot(camera='3d')\n", @@ -1067,6 +755,18 @@ "plot_l3d.show()" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "28eb7014-4773-4a34-8bfc-bd3a46429012", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plot_l3d.auto_scale(maintain_aspect=True)" + ] + }, { "cell_type": "markdown", "id": "a202b3d0-2a0b-450a-93d4-76d0a1129d1d", @@ -1081,7 +781,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "id": "2ecb2385-8fa4-4239-881c-b754c24aed9f", "metadata": {}, "outputs": [], @@ -1093,52 +793,10 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "id": "39252df5-9ae5-4132-b97b-2785c5fa92ea", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "58954cd128264eb38a4afc87f940194e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "RFBOutputContext()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
initial snapshot
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3eac2f2a71334813a958c144d22089d4", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "JupyterWgpuCanvas()" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# create a random distribution of 10,000 xyz coordinates\n", "n_points = 10_000\n", @@ -1185,7 +843,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "id": "8fa46ec0-8680-44f5-894c-559de3145932", "metadata": {}, "outputs": [], @@ -1196,7 +854,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "id": "e4dc71e4-5144-436f-a464-f2a29eee8f0b", "metadata": {}, "outputs": [], @@ -1207,7 +865,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "id": "5b637a29-cd5e-4011-ab81-3f91490d9ecd", "metadata": {}, "outputs": [], @@ -1218,7 +876,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "id": "a4084fce-78a2-48b3-9a0d-7b57c165c3c1", "metadata": {}, "outputs": [], @@ -1229,7 +887,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "id": "f486083e-7c58-4255-ae1a-3fe5d9bfaeed", "metadata": {}, "outputs": [], @@ -1250,25 +908,10 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "id": "f404a5ea-633b-43f5-87d1-237017bbca2a", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "36ce2e79024a4906aef9530ea238631d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(JupyterWgpuCanvas(frame_feedback={'index': 812, 'timestamp': 1673222184.132576, …" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "row1 = HBox([plot.show(), plot_v.show(), plot_sync.show()])\n", "row2 = HBox([plot_l.show(), plot_l3d.show(), plot_s.show()])\n", @@ -1301,7 +944,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.5" + "version": "3.11.3" } }, "nbformat": 4, diff --git a/fastplotlib/VERSION b/fastplotlib/VERSION index 229bb9495..6cb992894 100644 --- a/fastplotlib/VERSION +++ b/fastplotlib/VERSION @@ -1 +1 @@ -0.1.0.a9 +0.1.0.a10 \ No newline at end of file diff --git a/fastplotlib/graphics/features/_colors.py b/fastplotlib/graphics/features/_colors.py index a5147b95e..f8e7c8c3d 100644 --- a/fastplotlib/graphics/features/_colors.py +++ b/fastplotlib/graphics/features/_colors.py @@ -220,8 +220,8 @@ def __init__(self, parent, cmap: str): self.name = cmap def _set(self, cmap_name: str): - self._parent.world_object.material.map.texture.data[:] = make_colors(256, cmap_name) - self._parent.world_object.material.map.texture.update_range((0, 0, 0), size=(256, 1, 1)) + self._parent.world_object.material.map.data[:] = make_colors(256, cmap_name) + self._parent.world_object.material.map.update_range((0, 0, 0), size=(256, 1, 1)) self.name = cmap_name self._feature_changed(key=None, new_data=self.name) @@ -246,8 +246,8 @@ class HeatmapCmapFeature(ImageCmapFeature): """ def _set(self, cmap_name: str): - self._parent._material.map.texture.data[:] = make_colors(256, cmap_name) - self._parent._material.map.texture.update_range((0, 0, 0), size=(256, 1, 1)) + self._parent._material.map.data[:] = make_colors(256, cmap_name) + self._parent._material.map.update_range((0, 0, 0), size=(256, 1, 1)) self.name = cmap_name self._feature_changed(key=None, new_data=self.name) diff --git a/fastplotlib/graphics/features/_data.py b/fastplotlib/graphics/features/_data.py index 3d877bace..5063b4200 100644 --- a/fastplotlib/graphics/features/_data.py +++ b/fastplotlib/graphics/features/_data.py @@ -1,7 +1,7 @@ from typing import * import numpy as np -from pygfx import Buffer, Texture, TextureView +from pygfx import Buffer, Texture from ._base import GraphicFeatureIndexable, cleanup_slice, FeatureEvent, to_gpu_supported_dtype @@ -87,7 +87,7 @@ def _feature_changed(self, key, new_data): class ImageDataFeature(GraphicFeatureIndexable): """ - Access to the TextureView buffer shown in an ImageGraphic. + Access to the Texture buffer shown in an ImageGraphic. """ def __init__(self, parent, data: Any): @@ -102,7 +102,7 @@ def __init__(self, parent, data: Any): @property def buffer(self) -> Texture: """Texture buffer for the image data""" - return self._parent.world_object.geometry.grid.texture + return self._parent.world_object.geometry.grid def update_gpu(self): """Update the GPU with the buffer""" @@ -153,7 +153,7 @@ class HeatmapDataFeature(ImageDataFeature): @property def buffer(self) -> List[Texture]: """list of Texture buffer for the image data""" - return [img.geometry.grid.texture for img in self._parent.world_object.children] + return [img.geometry.grid for img in self._parent.world_object.children] def update_gpu(self): """Update the GPU with the buffer""" diff --git a/fastplotlib/graphics/image.py b/fastplotlib/graphics/image.py index cb4cf1587..835061328 100644 --- a/fastplotlib/graphics/image.py +++ b/fastplotlib/graphics/image.py @@ -4,7 +4,6 @@ import numpy as np import pygfx -from pygfx.utils import unpack_bitfield from ._base import Graphic, Interaction, PreviouslyModifiedData from .features import ImageCmapFeature, ImageDataFeature, HeatmapDataFeature, HeatmapCmapFeature @@ -87,18 +86,18 @@ def __init__( if (vmin is None) or (vmax is None): vmin, vmax = quick_min_max(data) - texture_view = pygfx.Texture(buffer_init, dim=2).get_view(filter=filter) + texture = pygfx.Texture(buffer_init, dim=2) - geometry = pygfx.Geometry(grid=texture_view) + geometry = pygfx.Geometry(grid=texture) # if data is RGB if data.ndim == 3: self.cmap = None - material = pygfx.ImageBasicMaterial(clim=(vmin, vmax)) + material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map_interpolation=filter) # if data is just 2D without color information, use colormap LUT else: self.cmap = ImageCmapFeature(self, cmap) - material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap()) + material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap(), map_interpolation=filter) world_object = pygfx.Image( geometry, @@ -151,21 +150,13 @@ class _ImageTile(pygfx.Image): """ Similar to pygfx.Image, only difference is that it contains a few properties to keep track of row chunk index, column chunk index - - """ def _wgpu_get_pick_info(self, pick_value): - tex = self.geometry.grid - if hasattr(tex, "texture"): - tex = tex.texture # tex was a view - # This should match with the shader - values = unpack_bitfield(pick_value, wobject_id=20, x=22, y=22) - x = values["x"] / 4194304 * tex.size[0] - 0.5 - y = values["y"] / 4194304 * tex.size[1] - 0.5 - ix, iy = int(x + 0.5), int(y + 0.5) + pick_info = super()._wgpu_get_pick_info(pick_value) + + # add row chunk and col chunk index to pick_info dict return { - "index": (ix, iy), - "pixel_coord": (x - ix, y - iy), + **pick_info, "row_chunk_index": self.row_chunk_index, "col_chunk_index": self.col_chunk_index } @@ -281,7 +272,7 @@ def __init__( vmin, vmax = quick_min_max(data) self.cmap = HeatmapCmapFeature(self, cmap) - self._material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap()) + self._material = pygfx.ImageBasicMaterial(clim=(vmin, vmax), map=self.cmap(), map_interpolation=filter) for start, stop, chunk in zip(start_ixs, stop_ixs, chunks): row_start, col_start = start @@ -290,8 +281,8 @@ def __init__( # x and y positions of the Tile in world space coordinates y_pos, x_pos = row_start, col_start - tex_view = pygfx.Texture(buffer_init[row_start:row_stop, col_start:col_stop], dim=2).get_view(filter=filter) - geometry = pygfx.Geometry(grid=tex_view) + texture = pygfx.Texture(buffer_init[row_start:row_stop, col_start:col_stop], dim=2) + geometry = pygfx.Geometry(grid=texture) # material = pygfx.ImageBasicMaterial(clim=(0, 1), map=self.cmap()) img = _ImageTile(geometry, self._material) diff --git a/fastplotlib/layouts/_base.py b/fastplotlib/layouts/_base.py index c98c010ea..70bd6dbaa 100644 --- a/fastplotlib/layouts/_base.py +++ b/fastplotlib/layouts/_base.py @@ -70,18 +70,11 @@ def __init__( self._camera = camera self._controller = controller - self.controller.add_default_event_handlers( + self.controller.add_camera(self.camera) + self.controller.register_events( self.viewport, - self.camera ) - # camera.far and camera.near clipping planes get - # wonky with setting controller.distance = 0 - if isinstance(self.camera, OrthographicCamera): - self.controller.distance = 0 - # also set a initial zoom - self.controller.zoom(0.8 / self.controller.zoom_value) - self.renderer.add_event_handler(self.set_viewport_rect, "resize") # list of hex id strings for all graphics managed by this PlotArea @@ -158,7 +151,6 @@ def set_viewport_rect(self, *args): def render(self): # does not flush - self.controller.update_camera(self.camera) self.viewport.render(self.scene, self.camera) for child in self.children: @@ -213,17 +205,7 @@ def _check_graphic_name_exists(self, name): if name in graphic_names: raise ValueError(f"graphics must have unique names, current graphic names are:\n {graphic_names}") - def _refresh_camera(self): - self.controller.update_camera(self.camera) - if sum(self.renderer.logical_size) > 0: - scene_lsize = self.viewport.rect[2], self.viewport.rect[3] - else: - scene_lsize = (1, 1) - - self.camera.set_view_size(*scene_lsize) - self.camera.update_projection_matrix() - - def center_graphic(self, graphic: Graphic, zoom: float = 1.3): + def center_graphic(self, graphic: Graphic, zoom: float = 1.35): """ Center the camera w.r.t. the passed graphic @@ -236,17 +218,14 @@ def center_graphic(self, graphic: Graphic, zoom: float = 1.3): zoom the camera after centering """ - if not isinstance(self.camera, OrthographicCamera): - warn("`center_graphic()` not yet implemented for `PerspectiveCamera`") - return - self._refresh_camera() + self.camera.show_object(graphic.world_object) - self.controller.show_object(self.camera, graphic.world_object) + # camera.show_object can cause the camera width and height to increase so apply a zoom to compensate + # probably because camera.show_object uses bounding sphere + self.camera.zoom = zoom - self.controller.zoom(zoom) - - def center_scene(self, zoom: float = 1.3): + def center_scene(self, zoom: float = 1.35): """ Auto-center the scene, does not scale. @@ -259,15 +238,11 @@ def center_scene(self, zoom: float = 1.3): if not len(self.scene.children) > 0: return - if not isinstance(self.camera, OrthographicCamera): - warn("`center_scene()` not yet implemented for `PerspectiveCamera`") - return - - self._refresh_camera() + self.camera.show_object(self.scene) - self.controller.show_object(self.camera, self.scene) - - self.controller.zoom(zoom) + # camera.show_object can cause the camera width and height to increase so apply a zoom to compensate + # probably because camera.show_object uses bounding sphere + self.camera.zoom = zoom def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8): """ @@ -303,9 +278,7 @@ def auto_scale(self, maintain_aspect: bool = False, zoom: float = 0.8): self.camera.width = width self.camera.height = height - # self.controller.distance = 0 - - self.controller.zoom(zoom / self.controller.zoom_value) + self.camera.zoom = zoom def remove_graphic(self, graphic: Graphic): """ diff --git a/fastplotlib/layouts/_defaults.py b/fastplotlib/layouts/_defaults.py index 3c5732613..314774751 100644 --- a/fastplotlib/layouts/_defaults.py +++ b/fastplotlib/layouts/_defaults.py @@ -8,9 +8,9 @@ controller_types = { '2d': pygfx.PanZoomController, - '3d': pygfx.OrbitOrthoController, + '3d': pygfx.OrbitController, pygfx.OrthographicCamera: pygfx.PanZoomController, - pygfx.PerspectiveCamera: pygfx.OrbitOrthoController, + pygfx.PerspectiveCamera: pygfx.OrbitController, } diff --git a/fastplotlib/layouts/_subplot.py b/fastplotlib/layouts/_subplot.py index 7bb1f0540..a5f57451e 100644 --- a/fastplotlib/layouts/_subplot.py +++ b/fastplotlib/layouts/_subplot.py @@ -6,7 +6,7 @@ from inspect import signature, getfullargspec from warnings import warn -from pygfx import Scene, OrthographicCamera, PanZoomController, OrbitOrthoController, \ +from pygfx import Scene, OrthographicCamera, PanZoomController, OrbitController, \ AxesHelper, GridHelper, WgpuRenderer from wgpu.gui.auto import WgpuCanvas @@ -22,7 +22,7 @@ def __init__( position: Tuple[int, int] = None, parent_dims: Tuple[int, int] = None, camera: str = '2d', - controller: Union[PanZoomController, OrbitOrthoController] = None, + controller: Union[PanZoomController, OrbitController] = None, canvas: WgpuCanvas = None, renderer: WgpuRenderer = None, name: str = None, diff --git a/fastplotlib/plot.py b/fastplotlib/plot.py index 74c35ef6e..89c73a5f2 100644 --- a/fastplotlib/plot.py +++ b/fastplotlib/plot.py @@ -10,7 +10,7 @@ def __init__( canvas: WgpuCanvas = None, renderer: pygfx.Renderer = None, camera: str = '2d', - controller: Union[pygfx.PanZoomController, pygfx.OrbitOrthoController] = None, + controller: Union[pygfx.PanZoomController, pygfx.OrbitController] = None, **kwargs ): """ diff --git a/fastplotlib/utils/functions.py b/fastplotlib/utils/functions.py index d919a88d6..1ba72b322 100644 --- a/fastplotlib/utils/functions.py +++ b/fastplotlib/utils/functions.py @@ -68,7 +68,7 @@ def make_colors(n_colors: int, cmap: str, alpha: float = 1.0) -> np.ndarray: def get_cmap_texture(name: str, alpha: float = 1.0) -> Texture: cmap = _get_cmap(name) - return Texture(cmap, dim=1).get_view() + return Texture(cmap, dim=1) def make_colors_dict(labels: iter, cmap: str, **kwargs) -> OrderedDict: