-
Notifications
You must be signed in to change notification settings - Fork 333
Feature/voxel annotation #858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Can you complete the CLA? |
| this.voxBrushShape.changed.add(this.specificationChanged.dispatch); | ||
| this.voxFloodMaxVoxels.changed.add(this.specificationChanged.dispatch); | ||
| this.paintValue.changed.add(this.specificationChanged.dispatch); | ||
| this.tabs.add("Draw", { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the hidden property to ensure this is only visible if there is a writable source.
src/layer/vox/controls.ts
Outdated
| }), | ||
| }, | ||
| { | ||
| label: "Paint Color", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is intended to show the color for segmentation layers, it shouldn't be editable, and also it doesn't always seem to stay in sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, this is pretty much useless, I will remove it
src/layer/vox/controls.ts
Outdated
| control.title = "Specify segment ID or intensity value to paint"; | ||
| control.addEventListener("change", () => { | ||
| try { | ||
| layer.setVoxelPaintValue(BigInt(control.value)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be limited to the valid range for the data type.
|
The brush hover outline (circle where the mouse pointer is) seems to go away in some cases when changing the zoom level. |
2d5359d to
9d15526
Compare
|
|
- Introduced a new dummy `MultiscaleVolumeChunkSource`. - Added `VoxelAnnotationRenderLayer` for voxel annotation rendering. - Implemented `VoxUserLayer` with dummy data source and rendering. - Added tools and logs for voxel layer interactions and debugging. - Documented voxel annotation specification and implementation details.
- Added a backend `VoxDummyChunkSource` that generates a checkerboard pattern for voxel annotations. - Implemented frontend `VoxDummyChunkSource` with RPC pairing to the backend. - Updated documentation with details on chunk source architecture and implementation.
…t seems there is some fighting.
…s to corruped the chunk after the usage of the tool. Added a front end buffer which is the only drawing storage for now. Added user settings to set the voxel_annotation layer scale and bounds. Added a second empty source to DummyMultiscaleVolumeChunkSource to prevent crashs when zoomed out too much
…lobal one (there where a missing convertion) ; add a primitive brush tool
…umeChunkSource and update related imports
…panded brush settings
…ation, and improved backend edit handling
…map options and UI settings
…r remote workflows, label creation, and new drawing tools
…n unnecessary amount of 0 filled chunks, this fixed the perfomance issue
…y voxel editing logic
… local coord space was not aligned with the global (e.g. x and z inverted for example, which is common).
…tion on cursor sizes (128 for chrome), to fix this, the brush cursor is now drawn on an overlay canvas. This explains why other web-based drawing tools have inertia (we now have) on the brush cursor.
…e the value to the valid range for the data type.
…for the entire downsample cascade before reloading chunks, this fixes the disappearing preview at low res.
9d15526 to
3a7ebbc
Compare
…ering on chunk reload, the reloading pipeline was reverted for the primaryRenderLayer and the new logic only kept for the optimistic one.
… through volumes (writable or not) in the goal of supporting a "writing over read-only sources" workflow
src/datasource/zarr/backend.ts
Outdated
| } | ||
|
|
||
| async writeChunk(chunk: VolumeChunk): Promise<void> { | ||
| const { kvStore, getChunkKey, decodeCodecs } = this.chunkKvStore as any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would avoid casting as any, it makes it hard to follow. kvStore in zarr is explictly a ReadableKvStore so I think you want to change that to a normal KvStore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, I will look into that. I originally did this as part of my non-destructive workflow (e.g. I wanted to modify as little as possible of preexisting neuroglancer code while prototyping), but this makes no more sense now.
…peline + hardcoded zarr metadata creation
… valid zarr metadata
…ding pipeline and complete Zarr v3 metadata creation
…nterface key type and update codecs to use it instead of the ReadableKvStore subclass
This Draft Pull Request introduces an interactive voxel annotation feature, allowing users to perform manual segmentation by painting directly onto volumetric layers. This implementation is based on the proposal in Issue #851 and incorporates the feedback from @jbms.
Key Changes & Architectural Overview
Following the discussion, this implementation has been significantly revised from the initial prototype:
voxlayer type, the voxel editing functionality is now integrated directly intoImageUserLayerandSegmentationUserLayervia aUserLayerWithVoxelEditingMixin. This mixin adds a new "Draw" tab in the UI.New Tool System: The Brush and Flood Fill tools are implemented as toggleable LayerTools, while the Picker tool is a one-shot tool. All integrate with Neuroglancer's new tool system. The drawing action is bound to Ctrl + Left Click.
Optimistic Preview for Compressed Chunks: To provide immediate visual feedback and solve the performance problem with compressed chunks, edits are now rendered through an optimistic preview layer.
InMemoryVolumeChunkSource.RenderLayer(e.g.,ImageRenderLayerorSegmentationRenderLayer). This ensures the preview perfectly matches the user's existing shader and display settings.Data-flow
sequenceDiagram participant User participant Tool as VoxelBrushTool participant ControllerFE as VoxelEditController (FE) participant EditSourceFE as OverlayChunkSource (FE) participant BaseSourceFE as VolumeChunkSource (FE) participant ControllerBE as VoxelEditController (BE) participant BaseSourceBE as VolumeChunkSource (BE) User->>Tool: Mouse Down/Drag Tool->>ControllerFE: paintBrushWithShape(mouse, ...) ControllerFE->>ControllerFE: Calculates affected voxels and chunks ControllerFE->>EditSourceFE: applyLocalEdits(chunkKeys, ...) activate EditSourceFE EditSourceFE->>EditSourceFE: Modifies its own in-memory chunk data note over EditSourceFE: This chunk's texture is re-uploaded to the GPU deactivate EditSourceFE ControllerFE->>ControllerBE: commitEdits(edits, ...) [RPC] activate ControllerBE ControllerBE->>ControllerBE: Debounces and batches edits ControllerBE->>BaseSourceBE: applyEdits(chunkKeys, ...) activate BaseSourceBE BaseSourceBE-->>ControllerBE: Returns VoxelChange (for undo stack) deactivate BaseSourceBE ControllerBE->>ControllerFE: callChunkReload(chunkKeys) [RPC] activate ControllerFE ControllerFE->>BaseSourceFE: invalidateChunks(chunkKeys) note over BaseSourceFE: BaseSourceFE re-fetches chunk with the now-permanent edit. ControllerFE->>EditSourceFE: clearOptimisticChunk(chunkKeys) deactivate ControllerFE ControllerBE->>ControllerBE: Pushes change to Undo Stack & enqueues for downsampling deactivate ControllerBE loop Downsampling & Reload Cascade ControllerBE->>ControllerBE: downsampleStep(chunkKeys) ControllerBE->>ControllerFE: callChunkReload(chunkKeys) [RPC] activate ControllerFE ControllerFE->>BaseSourceFE: invalidateChunks(chunkKeys) note over BaseSourceFE: BaseSourceFE re-fetches chunk with the now-permanent edit. ControllerFE->>EditSourceFE: clearOptimisticChunk(chunkKeys) deactivate ControllerFE endData sources & Kvstores
Currently, there is a very limited set of supported data sources and kvstores, which are:
This lack of support is the first limitation of the current implementation.
Open Questions & Future Work
This PR focuses on establishing the core architecture. Several larger topics from the original discussion are noted here as future work:
Checklist