From 39ba9450d94e811712c2c7455cf7c67a8bc938e5 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Tue, 30 Jan 2024 13:50:07 -0500 Subject: [PATCH 1/3] build(remote-image): drop Python 3.7, add Python 3.12 --- packages/remote-image/pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/remote-image/pyproject.toml b/packages/remote-image/pyproject.toml index edb4bc66..c4b6dd1b 100644 --- a/packages/remote-image/pyproject.toml +++ b/packages/remote-image/pyproject.toml @@ -7,7 +7,7 @@ name = "itk-viewer-remote-image" dynamic = ["version"] description = '' readme = "README.md" -requires-python = ">=3.7" +requires-python = ">=3.8" license = "Apache-2.0" keywords = [] authors = [ @@ -17,11 +17,11 @@ authors = [ classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] @@ -59,7 +59,7 @@ cov = [ ] [[tool.hatch.envs.all.matrix]] -python = ["3.7", "3.8", "3.9", "3.10", "3.11"] +python = ["3.8", "3.9", "3.10", "3.11", "3.12"] [tool.hatch.envs.lint] detached = true From 1c78c1e96849b25fe212dcfbf2b7775a875e2639 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Mon, 5 Feb 2024 06:46:02 -0500 Subject: [PATCH 2/3] test: support starting agave renderer with local hypha Refactor to support using the hypha --start-functions feature. --- .gitignore | 3 +- package.json | 2 +- .../itk_viewer_agave_renderer/renderer.py | 15 ++------ packages/agave-renderer/pyproject.toml | 4 +- packages/element/.env.example | 2 +- .../itk_viewer_remote_image/remote_zarr.py | 7 +--- packages/remote-image/tests/get_store.py | 7 ++-- packages/remote-image/tests/service.py | 24 +++++++++--- test/agave-startup.py | 37 +++++++++++++++++++ test/ome-zarr-startup.py | 18 +++++++++ 10 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 test/agave-startup.py create mode 100644 test/ome-zarr-startup.py diff --git a/.gitignore b/.gitignore index 78ca3554..6a41e530 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,8 @@ types/ .npmrc .pnpm-store +.env # temp transpiled TS files that don't always get cleaned up vite.config.ts.timestamp-*.mjs -vite.config.ts.timestamp-*.mts \ No newline at end of file +vite.config.ts.timestamp-*.mts diff --git a/package.json b/package.json index ef944c47..13d485f3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "lint": "pnpm prettier --check . && pnpm eslint .", "lint:fix": "pnpm prettier --write . && pnpm eslint --fix .", "setup-micromamba": "setup-micromamba --micromamba-binary-path ./micromamba/micromamba --micromamba-root-path ./micromamba --init-shell none --create-environment true --environment-file environment.yml --log-level info --run-command \"clean -fya\"", - "start-hypha": "pnpm setup-micromamba && ./micromamba/micromamba run -r micromamba -n itk-viewer hypha --host=127.0.0.1 --port=37580", + "start-hypha": "pnpm setup-micromamba && ./micromamba/micromamba run -r micromamba -n itk-viewer hypha --host=127.0.0.1 --port=9000 --startup-functions ./test/agave-startup.py:hypha_startup ./test/ome-zarr-startup.py:hypha_startup", "test": "pnpm test:downloadData && concurrently -n \"hypha,cypress\" --success first -k \"pnpm start-hypha\" \"pnpm cy:component\"", "test:downloadData": "node test/downloadData.mjs", "cy:watch": "cypress open --component -b chrome", diff --git a/packages/agave-renderer/itk_viewer_agave_renderer/renderer.py b/packages/agave-renderer/itk_viewer_agave_renderer/renderer.py index 24c9614e..90630363 100644 --- a/packages/agave-renderer/itk_viewer_agave_renderer/renderer.py +++ b/packages/agave-renderer/itk_viewer_agave_renderer/renderer.py @@ -40,7 +40,7 @@ async def recv(self): frame = VideoFrame.from_image(img) - frame.pts = self.count + frame.pts = self.count self.count+=1 frame.time_base = fractions.Fraction(1, 1000) return frame @@ -118,7 +118,7 @@ async def draw_frame(self): img = r.memory_redraw() self.render_time = time.time() - start_time return img - + def get_render_time(self): return self.render_time @@ -187,21 +187,14 @@ async def on_ended(): async def connect( self, - hypha_server_url, + server, load_image_into_agave_fn, visibility="public", - identifier="agave-renderer-rtc", + identifier=f"{RENDERER_SERVICE_ID}-rtc", ): self.load_image = functools.partial(load_image_into_agave_fn, self) service_id = identifier - client_id = service_id + "-client" - server = await connect_to_server( - { - "client_id": client_id, - "server_url": hypha_server_url, - } - ) await server.register_service( { diff --git a/packages/agave-renderer/pyproject.toml b/packages/agave-renderer/pyproject.toml index 86accd15..349f4685 100644 --- a/packages/agave-renderer/pyproject.toml +++ b/packages/agave-renderer/pyproject.toml @@ -16,11 +16,11 @@ authors = [ classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] @@ -59,7 +59,7 @@ cov = [ ] [[tool.hatch.envs.all.matrix]] -python = ["3.7", "3.8", "3.9", "3.10", "3.11"] +python = ["3.8", "3.9", "3.10", "3.11", "3.12"] [tool.hatch.envs.lint] detached = true diff --git a/packages/element/.env.example b/packages/element/.env.example index 01c11464..eb0c64b9 100644 --- a/packages/element/.env.example +++ b/packages/element/.env.example @@ -1,4 +1,4 @@ VITE_HYPHA_URL=http://127.0.0.1:9000 VITE_HYPHA_RENDER_SERVICE_ID=agave-renderer-rtc VITE_HYPHA_REMOTE_ZARR_SERVICE_ID=remote-zarr -VITE_IMAGE=data/aneurism.ome.tif \ No newline at end of file +VITE_IMAGE=input/ome-ngff-prototypes/single_image/v0.4/zyx.ome.zarr \ No newline at end of file diff --git a/packages/remote-image/itk_viewer_remote_image/remote_zarr.py b/packages/remote-image/itk_viewer_remote_image/remote_zarr.py index 22748bfa..1e994e1d 100644 --- a/packages/remote-image/itk_viewer_remote_image/remote_zarr.py +++ b/packages/remote-image/itk_viewer_remote_image/remote_zarr.py @@ -4,7 +4,6 @@ from pathlib import Path -from imjoy_rpc.hypha import connect_to_server import zarr from ngff_zarr import ( detect_cli_io_backend, @@ -69,15 +68,11 @@ async def get_store(self, image_path): async def connect( self, - hypha_server_url, + server, map_path=lambda p: p, visibility="public", identifier="remote-zarr", ): - server = await connect_to_server( - {"name": "remote-zarr", "server_url": hypha_server_url} - ) - self.map_path = map_path await server.register_service( diff --git a/packages/remote-image/tests/get_store.py b/packages/remote-image/tests/get_store.py index 4b162e2d..3ed9e152 100644 --- a/packages/remote-image/tests/get_store.py +++ b/packages/remote-image/tests/get_store.py @@ -1,11 +1,12 @@ +import os import asyncio from imjoy_rpc.hypha import connect_to_server -HYPHA_SERVER_URL = "https://hypha.website" - +from dotenv import load_dotenv async def main(): - server = await connect_to_server({"server_url": HYPHA_SERVER_URL}) + hypha_server_url = os.environ.get("HYPHA_SERVER_URL", "https://hypha.website") + server = await connect_to_server({"server_url": hypha_server_url}) svc = await server.get_service("remote-zarr") diff --git a/packages/remote-image/tests/service.py b/packages/remote-image/tests/service.py index fdb2f367..f279f175 100644 --- a/packages/remote-image/tests/service.py +++ b/packages/remote-image/tests/service.py @@ -1,17 +1,29 @@ +import os import asyncio +from pathlib import Path -from itk_viewer_remote_image import RemoteZarr - -HYPHA_SERVER_URL = "https://hypha.website" +from imjoy_rpc.hypha import connect_to_server -remoteZarr = RemoteZarr() +from dotenv import load_dotenv +from itk_viewer_remote_image import RemoteZarr def map_path(image_path) -> str: - return f"../../../test/data/input/{image_path}" + script_dir = os.path.dirname(os.path.realpath(__file__)) + image_path_mapped = Path(script_dir) / '..' / '..' / '..' / 'test' / 'data' / 'input' / image_path + return str(image_path_mapped) + +async def hypha_startup(): + hypha_server_url = os.environ.get("HYPHA_SERVER_URL", "https://hypha.website") + server = await connect_to_server( + {"name": "remote-zarr-client", "server_url": hypha_server_url} + ) + + remote_zarr = RemoteZarr() + await remote_zarr.connect(server, map_path) if __name__ == "__main__": loop = asyncio.new_event_loop() - task = loop.create_task(remoteZarr.connect(HYPHA_SERVER_URL, map_path)) + task = loop.create_task(hypha_startup()) loop.run_forever() diff --git a/test/agave-startup.py b/test/agave-startup.py new file mode 100644 index 00000000..879736ce --- /dev/null +++ b/test/agave-startup.py @@ -0,0 +1,37 @@ +import os +import websockets + +from dotenv import load_dotenv + +from itk_viewer_agave_renderer import Renderer + +load_dotenv() + +async def check_websocket_server(): + try: + async with websockets.connect('ws://localhost:1235') as ws: + return True + except Exception as e: + print(f"Failed to connect: {e}") + return False + +async def load_image(renderer, image_path="", multiresolution_level=0, channels=[], region=[]): + agave_renderer = renderer.agave + + script_dir = os.path.dirname(os.path.realpath(__file__)) + image_path_mapped = os.path.join(script_dir, f"data/{image_path}") + + agave_renderer.load_data( + image_path_mapped, 0, multiresolution_level, 0, channels, region + ) + +async def hypha_startup(server): + renderer = Renderer() + + server_is_listening = await check_websocket_server() + if not server_is_listening: + print("Server is not listening, start with `agave --server`") + print("Skipping tests...") + return + + await renderer.connect(server, load_image) \ No newline at end of file diff --git a/test/ome-zarr-startup.py b/test/ome-zarr-startup.py new file mode 100644 index 00000000..c1cd6c06 --- /dev/null +++ b/test/ome-zarr-startup.py @@ -0,0 +1,18 @@ +import os +from pathlib import PosixPath + +from dotenv import load_dotenv + +from itk_viewer_remote_image import RemoteZarr + +load_dotenv() + +def map_path(image_path) -> str: + script_dir = os.path.dirname(os.path.realpath(__file__)) + image_path_mapped = PosixPath(script_dir) / "data" / image_path + return str(image_path_mapped.resolve()) + +async def hypha_startup(server): + remote_zarr = RemoteZarr() + + await remote_zarr.connect(server, map_path) \ No newline at end of file From a887226a03e028a3c977c03ba7ebd09838a5615e Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Thu, 7 Mar 2024 09:02:51 -0500 Subject: [PATCH 3/3] refactor(remote-image): use itkwasm_guassian Also ensure dimension_separator="/" is set. --- .../remote-image/itk_viewer_remote_image/remote_zarr.py | 7 ++++--- packages/remote-image/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/remote-image/itk_viewer_remote_image/remote_zarr.py b/packages/remote-image/itk_viewer_remote_image/remote_zarr.py index 1e994e1d..4b3ad432 100644 --- a/packages/remote-image/itk_viewer_remote_image/remote_zarr.py +++ b/packages/remote-image/itk_viewer_remote_image/remote_zarr.py @@ -46,9 +46,10 @@ def __init__(self): pass async def get_store(self, image_path): - print(f"get_store: {image_path}", flush=True) + print(f"image_path: {image_path}", flush=True) mapped_path = self.map_path(image_path) + print(f"mapped_path: {mapped_path}", flush=True) if mapped_path.find("://") == -1 and not Path(mapped_path).exists(): print(f"File not found: {mapped_path}\n", flush=True) @@ -56,11 +57,11 @@ async def get_store(self, image_path): backend = detect_cli_io_backend([mapped_path]) if backend is ConversionBackend.NGFF_ZARR: - return zarr.storage.DirectoryStore(mapped_path) + return zarr.storage.DirectoryStore(mapped_path, dimension_separator="/") # TODO: code below does not work yet image = cli_input_to_ngff_image(backend, [mapped_path]) - multiscales = to_multiscales(image, method=Methods.DASK_IMAGE_GAUSSIAN) + multiscales = to_multiscales(image, method=Methods.ITKWASM_GAUSSIAN) store, chunk_store = _make_multiscale_store() to_ngff_zarr(store, multiscales, chunk_store=chunk_store) diff --git a/packages/remote-image/pyproject.toml b/packages/remote-image/pyproject.toml index c4b6dd1b..0b762e33 100644 --- a/packages/remote-image/pyproject.toml +++ b/packages/remote-image/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Programming Language :: Python :: Implementation :: PyPy", ] dependencies = [ - "ngff-zarr[dask-image]", + "ngff-zarr", "zarr", "hypha", "numpy",