From 759def1658cf248fa5b71743e8db11cd466bcc68 Mon Sep 17 00:00:00 2001 From: Sean Martin Date: Thu, 19 Sep 2024 12:20:23 +0200 Subject: [PATCH] feat: allow seg gen to control the segments shown, have random colours, and the mesh render scale also keep the names for "mesh" generation to distinguish from "seg" generation so that the interface can stay the same, but use aliases where there is no difference in the function --- .../models/json_generator.py | 53 +++++-------------- .../state_generator.py | 21 ++++++-- 2 files changed, 29 insertions(+), 45 deletions(-) diff --git a/cryoet_data_portal_neuroglancer/models/json_generator.py b/cryoet_data_portal_neuroglancer/models/json_generator.py index 3bf9edc..4cb9865 100644 --- a/cryoet_data_portal_neuroglancer/models/json_generator.py +++ b/cryoet_data_portal_neuroglancer/models/json_generator.py @@ -186,17 +186,19 @@ def _get_shader(self): class SegmentationJSONGenerator(RenderingJSONGenerator): """Generates JSON Neuroglancer config for segmentation mask.""" - color: str + color: str | None = None is_visible: bool = True display_mesh: bool = True display_bounding_box: bool = False highlight_on_hover: bool = False + mesh_render_scale: float = 1.0 + visible_segments: tuple[int, ...] = (1,) def __post_init__(self): self._type = RenderingTypes.SEGMENTATION def generate_json(self) -> dict: - return { + state = { "type": self.layer_type, "name": f"{self.name}", "source": { @@ -210,48 +212,19 @@ def generate_json(self) -> dict: "tab": "rendering", "selectedAlpha": 1, "hoverHighlight": self.highlight_on_hover, - "segments": [ - 1, - ], - "segmentDefaultColor": self.color, + "segments": sorted((self.visible_segments)), "visible": self.is_visible, + "meshRenderScale": self.mesh_render_scale, } + # self.color === None means that the color will be random + # This is useful for multiple segmentations + if self.color is not None: + state["segmentDefaultColor"] = self.color + return state -@dataclass -class MeshJSONGenerator(RenderingJSONGenerator): - """Generates JSON Neuroglancer config for mesh that are alone (without any segmentation).""" - - color: str - is_visible: bool = True - display_mesh: bool = True - display_bounding_box: bool = False - highlight_on_hover: bool = False - - def __post_init__(self): - self._type = RenderingTypes.SEGMENTATION - - def generate_json(self) -> dict: - return { - "type": self.layer_type, - "name": f"{self.name}", - "source": { - **create_source(f"precomputed://{self.source}", self.scale, self.scale), - "subsources": { - "default": True, - "mesh": self.display_mesh, - }, - "enableDefaultSubsources": self.display_bounding_box, - }, - "tab": "rendering", - "selectedAlpha": 1, - "hoverHighlight": self.highlight_on_hover, - "segments": [ - 1, - ], - "segmentDefaultColor": self.color, - "visible": self.is_visible, - } +# Alias for SegmentationJSONGenerator - for future compatibility +MeshJSONGenerator = SegmentationJSONGenerator @dataclass diff --git a/cryoet_data_portal_neuroglancer/state_generator.py b/cryoet_data_portal_neuroglancer/state_generator.py index dd93a70..8400de1 100644 --- a/cryoet_data_portal_neuroglancer/state_generator.py +++ b/cryoet_data_portal_neuroglancer/state_generator.py @@ -87,12 +87,14 @@ def generate_segmentation_mask_layer( source: str, name: str | None = None, url: str | None = None, - color: str = "#FFFFFF", + color: str | None = "#FFFFFF", scale: float | tuple[float, float, float] = (1.0, 1.0, 1.0), is_visible: bool = True, display_bounding_box: bool = False, display_mesh: bool = True, highlight_on_hover: bool = False, + mesh_render_scale: float = 2.0, + visible_segments: tuple[int, ...] = (1,), ) -> dict[str, Any]: source, name, url, _, scale = _setup_creation(source, name, url, scale=scale) _validate_color(color) @@ -105,6 +107,8 @@ def generate_segmentation_mask_layer( display_bounding_box=display_bounding_box, display_mesh=display_mesh, highlight_on_hover=highlight_on_hover, + mesh_render_scale=mesh_render_scale, + visible_segments=visible_segments, ).to_json() @@ -118,6 +122,8 @@ def generate_mesh_layer( display_bounding_box: bool = False, display_mesh: bool = True, highlight_on_hover: bool = False, + mesh_render_scale: float = 2.0, + visible_segments: tuple[int, ...] = (1,), ) -> dict[str, Any]: source, name, url, _, scale = _setup_creation(source, name, url, scale=scale) _validate_color(color) @@ -130,6 +136,8 @@ def generate_mesh_layer( display_bounding_box=display_bounding_box, display_mesh=display_mesh, highlight_on_hover=highlight_on_hover, + mesh_render_scale=mesh_render_scale, + visible_segments=visible_segments, ).to_json() @@ -143,19 +151,22 @@ def generate_oriented_point_mesh_layer( display_bounding_box: bool = False, display_mesh: bool = True, highlight_on_hover: bool = False, + mesh_render_scale: float = 4.0, + visible_segments: tuple[int, ...] = (1,), ) -> dict[str, Any]: - source, name, url, _, scale = _setup_creation(source, name, url, scale=scale) - _validate_color(color) - return MeshJSONGenerator( + return generate_mesh_layer( source=source, name=name, + url=url, color=color, scale=scale, is_visible=is_visible, display_bounding_box=display_bounding_box, display_mesh=display_mesh, highlight_on_hover=highlight_on_hover, - ).to_json() + mesh_render_scale=mesh_render_scale, + visible_segments=visible_segments, + ) def generate_image_layer(