Skip to content
Open
Show file tree
Hide file tree
Changes from 209 commits
Commits
Show all changes
252 commits
Select commit Hold shift + click to select a range
69b1e22
feat: retreive mouse position and current LOD scale
briossant Nov 10, 2025
488c184
feat: add support for voxel annotation rendering and specification
briossant Nov 10, 2025
fa6ecd5
feat: introduce VoxDummyChunkSource for procedural voxel annotation demo
briossant Nov 10, 2025
a52bad1
feat: no errors but no checkboard tho
briossant Nov 10, 2025
dcf7e12
feat: finaly the checkboard is showing, but it is a bit bugged out, i…
briossant Nov 10, 2025
935509b
doc: rework voxel annotation specs
briossant Nov 10, 2025
d0ce4ca
feat: working on the pixel tool, there are interaction but a bug seem…
briossant Nov 10, 2025
767006c
feat: pixel tool is now working as intended
briossant Nov 10, 2025
d94ee5a
feat: fix pixel tool not working when the scale is not equal to the g…
briossant Nov 10, 2025
b81186c
refactor: rename DummyMultiscaleVolumeChunkSource to VoxMultiscaleVol…
briossant Nov 10, 2025
a121d4b
feat: brush size, eraser mode and little trivial optimization
briossant Nov 10, 2025
cbff7a4
feat: continuous drawing and shape selection for the brush
briossant Nov 10, 2025
bbe859f
doc: add TODO list
briossant Nov 10, 2025
7eba8ec
feat: small improvement on the drawing render delay
briossant Nov 10, 2025
119450f
feat: persist voxel edits to backend and improve drawing responsiveness
briossant Nov 10, 2025
76975cf
feat: redesign toolbox with structured layout, tool selection, and ex…
briossant Nov 10, 2025
514ecd8
feat: implement new local voxel storage with IndexedDB, map initializ…
briossant Nov 10, 2025
85f6d69
doc: brainstorming LOD
briossant Nov 10, 2025
451c69b
feat: support region-based voxel initialization with corners, update …
briossant Nov 10, 2025
a8f9454
feat: expand TODOs with plans for segmentation compression, multi-use…
briossant Nov 10, 2025
f6e3547
feat: implement voxel label creation, persistence via IndexedDB, and …
briossant Nov 10, 2025
8ec4e90
feat: implement RPC-based voxel label persistence
briossant Nov 10, 2025
732132e
refactor: ran 'npm run format:fix'
briossant Nov 10, 2025
2c50dcb
feat: add support for remote voxel sources via HTTP(S) - (note: the l…
briossant Nov 10, 2025
32d7b72
feat: replace `setLabelIds` with `addLabel` for label management
briossant Nov 10, 2025
904591e
doc: add guidelines for junie and write project overview file
briossant Nov 10, 2025
eb4c0e3
feat: map creation and selection, the min scale is currently not save…
briossant Nov 10, 2025
8cfd644
feat: cleanup map init/selection implementation, the remote still nee…
briossant Nov 10, 2025
792c8fa
refactor: remove `VoxelPixelLegacyTool`, update references, and enabl…
briossant Nov 10, 2025
a718320
feat: add LOD locking for voxel rendering and extend brush size range
briossant Nov 10, 2025
3bab282
feat: move local and remote VoxSource to separate files, updated the …
briossant Nov 10, 2025
5e88dcf
feat: move local and remote VoxSource to separate files, updated the …
briossant Nov 10, 2025
5796116
feat: introduce chunk reload and downsample propagation APIs
briossant Nov 10, 2025
33d051a
feat: chunk reloading from the backend -> currently do not work due t…
briossant Nov 10, 2025
cad4a80
feat: add Zarr export functionality and dirty-tree upscaling (not wor…
briossant Nov 10, 2025
8cc92dc
feat: dirty tree upscaling is kinda working, at least enough to concl…
briossant Nov 10, 2025
ba6ae20
feat: restrict brush size and disable dirty tree upscaling
briossant Nov 10, 2025
a01be95
feat: introduce VoxelEditController for centralized edit handling and…
briossant Nov 10, 2025
944998a
refactor: improve chunk invalidation and reload workflows
briossant Nov 10, 2025
769f6ca
feat: add flood fill tool and export UI improvements
briossant Nov 10, 2025
1de7c59
feat: implement downscale job queue and improve chunk reload handling
briossant Nov 10, 2025
a030b50
feat: enhance flood fill stability and optimize Zarr export
briossant Nov 10, 2025
f47b41b
feat: rework map settings UI and add import/export improvements
briossant Nov 10, 2025
ea0832b
doc: update TODOs
briossant Nov 10, 2025
6c8ac37
feat: add Zarr import support and integrate remote chunk fallback
briossant Nov 10, 2025
9c2cfed
feat: add error handling for flood fill and display draw error messages
briossant Nov 10, 2025
f980626
Add `weekly-progress.md` to document the voxel annotation project's p…
briossant Nov 10, 2025
3810f61
feat: introduce `LabelsManager` for label management and cleanup `Vox…
briossant Nov 10, 2025
d16fb23
refactor: remove `RemoteVoxSource` and refactor related components fo…
briossant Nov 10, 2025
3dd2e99
feat: add Stateless S3 Authenticator (SSA) integration with KVStore
briossant Nov 10, 2025
1838e52
feat: upgrade SSA flow to OIDC-based authentication with PKCE support
briossant Nov 10, 2025
6890dbe
feat: enhance SSA KVStore integration and improve authentication logic
briossant Nov 10, 2025
e749b7a
feat: add backend integration for SSA KVStore
briossant Nov 10, 2025
f100dfa
refactor: consolidate SSA URL utilities and improve PKCE verifier gen…
briossant Nov 10, 2025
cbeb5ca
feat: add IndexedDB-backed KVStore implementation
briossant Nov 10, 2025
b51bf6b
feat: move the downscaling queue to the EditController backend and re…
briossant Nov 10, 2025
5c66105
feat: replace IndexedDB implementation with OPFS-backed KVStore
briossant Nov 10, 2025
5c35cdd
feat: add OPFS-backed KVStore module registration
briossant Nov 10, 2025
78056f7
chore: remove unused voxel annotation modules and associated logic
briossant Nov 10, 2025
d838eec
feat: enhance VoxUserLayer with configurable multiscale source option…
briossant Nov 10, 2025
dc74576
fix: rework getVoxelPositionFromMouse to give the right coords
briossant Nov 10, 2025
ac03537
refactor: simplify getVoxelPositionFromMouse logic by removing redund…
briossant Nov 10, 2025
73834c6
feat: optimize voxel drawing and transform caching
briossant Nov 10, 2025
118711c
feat: modularize `VolumeChunk` and chunk format handling
briossant Nov 10, 2025
402256c
feat: implement multiscale voxel editing and raw chunk encoding pipeline
briossant Nov 10, 2025
b24666e
feat: improve chunk handling and integrate SSA write/delete support (…
briossant Nov 10, 2025
35c58a1
feat: enhance retry logic, s3 support, and voxel annotation
briossant Nov 10, 2025
235af99
feat: add targeted chunk invalidation and improve voxel annotation pr…
briossant Nov 10, 2025
fd15293
feat: remove legacy local://voxel-annotations code and improve chunk …
briossant Nov 10, 2025
d59de80
feat: update voxel editing to support bigint values and improve label…
briossant Nov 10, 2025
3ef5f98
feat: refactor voxel annotation handling to support bigint and improv…
briossant Nov 10, 2025
ff0c70b
feat: convert voxel values to BigInt for improved precision in annota…
briossant Nov 10, 2025
9ceb2ad
feat: refactor voxel annotation to support multiscale resolutions and…
briossant Nov 10, 2025
c8b079b
feat: improve uncompressed chunk editing and fix TODOs
briossant Nov 10, 2025
06abea9
feat: add undo/redo support for voxel editing and enhance change trac…
briossant Nov 10, 2025
c51788d
fix: add mask for label generation to ensure it respect the DataType
briossant Nov 10, 2025
6c5cbf1
feat: enhance disk brush tool with arbitrary plane support
briossant Nov 10, 2025
45fb2c9
fix: ensure voxel coordinates align between CPU and GPU
briossant Nov 10, 2025
bb4698a
fix: adjust default `voxFloodMaxVoxels` and refine flood fill plane l…
briossant Nov 10, 2025
d2afe3f
chore: cleanup dev files and format + lint code
briossant Nov 10, 2025
cba1c9f
fix: properly align flood fill seed
briossant Nov 10, 2025
176f96a
refactor: start switching vox tools to the new tool system
briossant Nov 10, 2025
8c7fadb
refactor: fully migrate voxel tools to new tool system
briossant Nov 10, 2025
a1d56f1
feat: add dynamic cursor support for brush and flood fill tools
briossant Nov 10, 2025
c845d0d
feat: improve voxel layer rendering and UI enhancements
briossant Nov 10, 2025
fdef2c0
refactor: Merging vox layer into seg and img layers
briossant Nov 10, 2025
b46224e
feat: took care of every remaining ts errors
briossant Nov 10, 2025
a8feb09
feat: add writable subsource support and enable voxel editing
briossant Nov 10, 2025
595bba0
feat: add in-memory voxel editing capabilities
briossant Nov 10, 2025
ba01de6
feat: add support for compressed chunks in applyEdits() and zarr write()
briossant Nov 10, 2025
b2cc38d
feat: add dynamic cursor for voxel picker tool
briossant Nov 10, 2025
1a20724
refactor: replace the SingleScaleVolumeChunkSource with a proper Mult…
briossant Nov 10, 2025
557ce29
fix: finally found the bug of the drawing preview -> getChunk of InMe…
briossant Nov 10, 2025
c7edca0
refactor: rewrite the InMemoryVolumeChunkSource to no longer create a…
briossant Nov 10, 2025
0f38e50
feat: add chunk invalidation for the preview sources
briossant Nov 10, 2025
d89174a
fix: undo stack was corrupted
briossant Nov 10, 2025
85e7f2d
chore: lint + format
briossant Nov 10, 2025
83316aa
feat: save writable state to json state
briossant Nov 10, 2025
b7dec47
refactor: replace label system with paint value mechanism and simplif…
briossant Nov 10, 2025
c1cbb8b
feat: add state serialization and restoration for voxel editing context
briossant Nov 10, 2025
3acf73f
fix: planeNormal used to aligned floddfill and brush was wrong if the…
briossant Nov 10, 2025
48761ed
refactor: format + lint + cleanup
briossant Nov 10, 2025
8e11ffd
feat: ensure the draw tab is only visible if there is a writable source.
briossant Nov 10, 2025
e119731
fix: the brush cursor was disappearing because browsers have a limita…
briossant Nov 10, 2025
bef93e3
fix: ensure brush cursor is shown on tool activation
briossant Nov 10, 2025
b306e07
refactor(voxel-annotations): remove obsolete color controls and limit…
briossant Nov 10, 2025
3b7650e
fix(voxel-annotations): do not display the brush cursor in the 3d view
briossant Nov 10, 2025
3a7ebbc
refactor(voxel-annotations): rework chunk reloading pipeline -> wait …
briossant Nov 10, 2025
8eca17e
refactor(voxel-annotations): previous commit introduced serious flick…
briossant Nov 10, 2025
9c1cfd0
chore(voxel-annotations): Adjust flood fill to avoid small artifacts.
briossant Nov 10, 2025
2513c55
feat(voxel-annotations): add support for the seg picker tool to cycle…
briossant Nov 11, 2025
fb029f6
feat(datasource): add POC for dataset creation feature : ui + main pi…
briossant Nov 12, 2025
c6592b0
fix(datasource): correct the dataset creation POC to actually produce…
briossant Nov 12, 2025
0ab5bd5
feat(datasource): started generalizing dataset creation feature
briossant Nov 12, 2025
77b1317
chore: run format
briossant Nov 12, 2025
f67b9b8
refactor(datasource): simplify dataset creation UI and remove unused …
briossant Nov 13, 2025
898d8f5
fix(datasource): ensure datasource gets reloaded upon creation
briossant Nov 13, 2025
d4c171a
fix(voxel-annotation): support every data type (expect float32)
briossant Nov 13, 2025
cdd14be
feat(datasource): implement support for gzip and blosc codecs in enco…
briossant Nov 14, 2025
bc84ca0
chore: format code + update TODOs
briossant Nov 14, 2025
b5d90b8
refactor(datasource): following @chrisj comment: generalize KvStore i…
briossant Nov 14, 2025
9078c41
feat(voxel-annotation): support elliptical brush outlines (cursor)
briossant Nov 17, 2025
c2f9016
chore(voxel-annotation): fix diagnosis of the preview color issue and…
briossant Nov 17, 2025
1a4d3fd
fix(voxel-annotation): ensure paint value is clamped in the datatype…
briossant Nov 17, 2025
a32360c
fix(voxel-annotation): Correct buffer type for new compressed segment…
briossant Nov 17, 2025
1ac34bd
fix(datasource): resolve incorrect blosc encoding
briossant Nov 17, 2025
d84f0b0
feat(dataset-creation): generalize to ranks and fix copying of units …
briossant Nov 17, 2025
0e0a105
chore: format + update TODOs
briossant Nov 17, 2025
22f083e
refactor(dataset-creation): enhance metadata copying
briossant Nov 18, 2025
d484dd2
test(sliceview/volume/backend.ts): add tests for applyEdits ; added d…
briossant Nov 19, 2025
61483e9
test(voxel-annotation): add tests for `_calculateParentUpdate` ; add …
briossant Nov 20, 2025
701b139
test(voxel-annotation): add tests for `_getParentChunkInfo`
briossant Nov 20, 2025
f5993ce
test(voxel-annotation): add integration tests for downsampling in `Vo…
briossant Nov 20, 2025
7e8b6d4
test(voxel-annotation): add `flushPending` tests
briossant Nov 20, 2025
b537ed8
test(voxel-annotation): add undo/redo tests
briossant Nov 21, 2025
844b1a1
feat(voxel-annotation): add constraint validation on voxel annotation…
briossant Nov 21, 2025
16bb033
test(voxel-annotation): add unit tests for getVoxelPositionFromMouse,…
briossant Nov 21, 2025
6ff5830
test(voxel-annotation): add unit tests for applyLocalEdits
briossant Nov 21, 2025
d68342a
test(voxel-annotation): add unit tests for floodFillPlane2D and paint…
briossant Nov 24, 2025
1a58e55
feat(voxel-annotation): add user confirmation prompt for write action…
briossant Nov 25, 2025
2452a4e
chore: dev utilities
briossant Nov 25, 2025
bdbc575
test(voxel-annotation): finally able to run browser_test and create o…
briossant Nov 26, 2025
f7510f4
test(voxel-annotation): expand browser tests with additional scenario…
briossant Nov 26, 2025
40f588b
test(voxel-annotation): migrate unit tests to browser tests for layer…
briossant Nov 27, 2025
76d55f2
cleanup: Remove OPFS and SSA-S3 KV store implementations and related …
briossant Nov 26, 2025
9871115
refactor(voxel-annotation): use the already implemented multiscale lo…
briossant Nov 26, 2025
d3f77a2
cleanup: Remove dataset creation feature.
briossant Nov 26, 2025
5624813
cleanup: remove dev files (docker for testsuite and dev scripts) and …
briossant Nov 27, 2025
22394eb
chore: add missing license headers across multiple files in the codebase
briossant Nov 27, 2025
91a71e4
refactor(voxel-annotation): remove unused styles, improve toolbox str…
briossant Nov 27, 2025
df9092a
refactor(voxel-annotation): replace `planeNormal` with `basis` in flo…
briossant Nov 27, 2025
b0d8421
cleanup(voxel-annotation): remove redundant or clarify comments
briossant Nov 27, 2025
9612dda
chore: merge master
briossant Nov 27, 2025
9f41d3b
refactor(voxel-annotation): rename `writable` to `writingEnabled` acr…
briossant Nov 27, 2025
46fb66d
fix(voxel-annotation): rename writable to writingEnabled in getActive…
briossant Dec 1, 2025
b3256b6
fix(voxel-annotation): fix paintValue json serialization
briossant Dec 1, 2025
1d6689b
feat(voxel-annotation): update TODOs with some found bugs and quality…
briossant Dec 1, 2025
b434958
fix(voxel-annotation): prevent redundant chunk reloads in downsamplin…
briossant Dec 2, 2025
b1bcaec
feat(voxel-annotation): render the brush cursor when changing the bru…
briossant Dec 3, 2025
d023f9f
refactor(voxel-annotation): fix missing keybind display for voxel ann…
briossant Dec 4, 2025
d1eb0d5
refactor(voxel-annotation): renamed edit_controller.ts and edit_backe…
briossant Dec 5, 2025
4d8b3bd
feat(voxel-annotation): add selective erase mode and refactor edit me…
briossant Dec 5, 2025
86a2009
fix(voxel-annotation): correctly retrieve value from voxEraseSelected…
briossant Dec 9, 2025
00de4cf
feat(voxel-annotation): remove double-opacity artifact from the optim…
briossant Dec 9, 2025
0bd9fd9
feat(voxel-annotation): added eraser preview with the help of a senti…
briossant Dec 10, 2025
ff5b752
feat(voxel-annotation): add a bottom bar when a voxel tool is active,…
briossant Dec 8, 2025
52dd642
fix(voxel-annotation): ensure proper cleanup of optimistic render lay…
briossant Dec 12, 2025
4acff9e
fix(voxel-annotation): enforce the activation of single writable sour…
briossant Dec 12, 2025
17ea651
fix(voxel-annotation): ensure brush outline/cursor always aligns with…
briossant Dec 15, 2025
243715d
refactor(voxel-annotation): extract `getBasisFromNormal`
briossant Dec 15, 2025
f33e54a
feat(voxel-annotation): implement a gap filling painting postprocessi…
briossant Dec 15, 2025
e920a98
fix(voxel-annotation): made the settings in the bottom bar of the pai…
briossant Dec 16, 2025
fa11f98
refactor(voxel-annotation): move erase mode to contole+shift+mousedow…
briossant Dec 16, 2025
72b326c
refactor(voxel-annotation): refactor erase action binding to ensure i…
briossant Dec 16, 2025
9bf17db
feat(voxel-annotation): made painting tool cursor show erase mode whe…
briossant Dec 16, 2025
b9df814
fix(voxel-annotation): prevent activation of voxel tools when no writ…
briossant Dec 17, 2025
64a8323
refactor(kvstore): remove unused proxy write logic
briossant Jan 7, 2026
ac372bf
refactor(voxel-annotation):
briossant Jan 7, 2026
de7bb60
refactor(voxel-annotation): temporarily add different ways to render …
briossant Jan 8, 2026
efacdaa
feat(voxel-annotation): discard the drawing action done before user c…
briossant Jan 8, 2026
9209334
test(voxel-annotation): remove obsolete frontend voxel annotation tes…
briossant Jan 9, 2026
b923709
chore(voxel-annotation): format
briossant Jan 9, 2026
7c86fb0
fix(voxel-annotation): fix `TypeError: Cannot convert undefined to a …
briossant Jan 12, 2026
9eb0278
feat(voxel-annotation): update tool cursors SVGs: added a crosshair a…
briossant Jan 12, 2026
6b01299
feat(voxel-annotation): adjust cursors aesthetic
briossant Jan 12, 2026
ab17db4
feat(voxel-annotation): adjust the brush radius calculation minimum t…
briossant Jan 12, 2026
e02b424
feat(voxel-annotation): add stamina bar
briossant Jan 13, 2026
66f52f2
feat(voxel-annotation): refine stamina computations and ui
briossant Jan 13, 2026
550b323
fix(voxel-annotation): ensure cursor overlay is only drawn when a wri…
briossant Jan 13, 2026
622410a
test(voxel-annotation): adapt backend.spec.ts to the latest updates
briossant Jan 14, 2026
4ad6e83
feat(voxel-annotation): introduce brush caching for performance optim…
briossant Jan 14, 2026
d52b800
feat(voxel-annotation): make pushIf a sync function when filterValue …
briossant Jan 14, 2026
7796df1
feat(voxel-annotation): optimize brush operations by removing memory …
briossant Jan 14, 2026
a6ea83c
feat(voxel-annotation): benchmarked the entire drawing pipeline to pr…
briossant Jan 21, 2026
55f57b4
feat(voxel-annotation): update stamina bar logic to dynamically adjus…
briossant Jan 22, 2026
ae68146
refactor(voxel-annotation):
briossant Jan 26, 2026
16df51f
test(voxel-annotation): fix backend.spec.ts
briossant Jan 27, 2026
9b392db
feat(voxel-annotation): remove the temporary brush shapes (kept SPHER…
briossant Jan 27, 2026
818131c
fix(voxel-annotation): make the brush cursor red again when `xtrl+shi…
briossant Jan 27, 2026
98eb68a
feat(voxel-annotation): add `ctrl+middleclick` shortcut for flood fil…
briossant Jan 28, 2026
bcedbb6
feat(voxel-annotation): add fast flood fill preview time limited (cur…
briossant Jan 28, 2026
019c40e
feat(voxel-annotation): add concurrency to downsampling jobs
briossant Jan 29, 2026
54cfd7b
feat(voxel-annotation): group paintBrushWithShape calls into a single…
briossant Jan 29, 2026
76dce78
fix(voxel-annotation): adjust the chunk reloading in the downsampling…
briossant Jan 29, 2026
8c6753d
chroe(voxel-annotation): run format + revert chunk reload edits from …
briossant Jan 29, 2026
c1384ab
fix(voxel-annotation): handle cases with no downsampling (single reso…
briossant Jan 30, 2026
fae54db
docs(voxel-annotation): add user guide for voxel annotation features
briossant Feb 22, 2026
ec5ddbd
docs(voxel-annotation): update from @seankmartin review
briossant Apr 10, 2026
2a6f12a
docs(voxel-annotation): remove duplicate
briossant Apr 10, 2026
12e3f27
refactor(voxel-annotation): renamed seg picker to value picker
briossant Apr 10, 2026
b33d913
fix(voxel-annotation): fix comment typo and remove shader debug method
briossant Apr 25, 2026
f25e482
fix(voxel-annotation): rename snake_case vars to camelCase and fix in…
briossant Apr 26, 2026
181d161
refactor(voxel-annotation): rename _createVoxelRenderLayer to _create…
briossant Apr 27, 2026
4d2f061
refactor(voxel-annotation): convert stamina benchmark to proper bench…
briossant Apr 27, 2026
ac82620
refactor(voxel-annotation): define VOXEL_EMPTY_VALUE constant and doc…
briossant Apr 28, 2026
abb9e11
refactor(voxel-annotation): replace remaining 0n erase value with VOX…
briossant Apr 28, 2026
35c747e
refactor(voxel-annotation): throw on Float32 and extract cursor SVGs …
briossant Apr 28, 2026
dc7c070
refactor(voxel-annotation): move Draw tab before Annotations and remo…
briossant Apr 29, 2026
fa90d63
docs(voxel-annotation): clarify compressedSegmentationBlockSize decom…
briossant Apr 29, 2026
61b4407
fix(voxel-annotation): restore backward-compatible subsource serialis…
briossant Apr 30, 2026
70a2aa0
refactor(voxel-annotation): dispatch brush stroke once at mouseup ins…
briossant May 12, 2026
9e20ca6
refactor(voxel-annotation): re-implement @chrisj sphere optimisations…
briossant May 23, 2026
df28681
test(voxel-annotation): add back @chrisj tests for chunkGridPosition …
briossant May 24, 2026
29e7a12
fix(voxel-annotation): restore shift+wheel brush size keybind
briossant May 29, 2026
c438791
fix(voxel-annotation): give overlay preview its own render scale hist…
briossant Jun 8, 2026
e156417
fix(voxel-annotation): compute stroke basis only after getPoint recor…
briossant Jul 6, 2026
08e0c65
fix(voxel-annotation): apply edits on isolated chunks and invalidate …
briossant Jul 6, 2026
081ff62
fix(zarr): refuse to write detached or size-mismatched chunk buffers
briossant Jul 6, 2026
3d3f040
feat(voxel-annotation): clear optimistic overlay on fresh-chunk arriv…
briossant Jul 6, 2026
ee30e91
fix(voxel-annotation): revalidate HTTP reads on sources this session …
briossant Jul 6, 2026
50aa60d
test(voxel-annotation): browser tests for repaint, gzip, dense labels…
briossant Jul 6, 2026
5adcd05
fix(voxel-annotation): clear overlay only when the written data cover…
briossant Jul 15, 2026
9d7f173
fix(voxel-annotation): capture cascade coverage at chain start and lo…
briossant Jul 15, 2026
dc88631
fix(voxel-annotation): tag overlay chunks with their stroke seq and r…
briossant Jul 17, 2026
1303430
perf(chunk): replace reload-time queue drain with receipt-seq causali…
briossant Jul 17, 2026
6b8ee31
refactor(voxel-annotation): resolve overlay swaps by observation, rem…
briossant Jul 17, 2026
58523e0
fix(voxel-annotation): small review findings
briossant Jul 17, 2026
480608e
fix(voxel-annotation): clear overlays explicitly on undo/redo and pru…
briossant Jul 19, 2026
0655699
fix(voxel-annotation): self-correcting accessor loads and flush-first…
briossant Jul 19, 2026
a2874ca
fix(voxel-annotation): serialize LOD-0 writers through a single exclu…
briossant Jul 19, 2026
e1f0227
fix(voxel-annotation): swap undone overlays on arrival instead of cle…
briossant Jul 19, 2026
55b15bf
fix(voxel-annotation): reconcile stroke overlays against the backend'…
briossant Aug 8, 2026
f4be994
feat(voxel-annotation): make flood-fill morphological gating optional
briossant Aug 8, 2026
6e6e816
test(voxel-annotation): update applyEdits spec for the isolated-chunk…
briossant Aug 15, 2026
0b11543
refactor: address review nits from PR #858
briossant Aug 15, 2026
5a635b9
refactor(zarr): extract chunk key computation shared by download and …
briossant Aug 15, 2026
1e218c3
refactor(kvstore): cache-bust S3 reads with a random query param inst…
briossant Aug 15, 2026
88046fd
fix(zarr): do not advertise writing support for sharded or transposed…
briossant Aug 16, 2026
818af71
refactor(sliceview): drop the NaN chunk-position tripwire in drawChunk
briossant Aug 20, 2026
77b3837
fix(kvstore): reject dot-segment components in S3 object keys
briossant Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ tsconfig.tsbuildinfo
-/docs/python/api/index.rst
/docs/python/api/*.rst
/.vite
/.idea
/.local
/.env
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Neuroglancer
:caption: User Guide

user-guide/navigation
user-guide/voxel_annotation

.. toctree::
:hidden:
Expand Down
115 changes: 115 additions & 0 deletions docs/user-guide/voxel_annotation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
.. _voxel-annotation:

Voxel Annotation
================

Voxel annotation allows for direct painting and editing of volumetric data
within Neuroglancer. This feature is available for both :ref:`image-layer` and
:ref:`segmentation-layer`.

Enabling Voxel Editing
----------------------

To enable voxel editing, you must first have a writable volume source.

1. Open the **Source** tab of an Image or Segmentation layer.
2. Locate a volume source and click the **Write** checkbox next to it.

.. note::
Only one source can be writable at a time within a layer. Voxel annotation is currently supported only for 3D volumes.

The first time you attempt a drawing operation (like a brush stroke) after enabling writing, a confirmation dialog will appear. Note that this initial operation will be canceled; you can resume drawing once you have confirmed.

.. note::
For the segmentation layer, it is recommended to deactivate the Highlight on hover option under the Render tab.
Comment thread
seankmartin marked this conversation as resolved.
Outdated

Supported Storage and Formats
-----------------------------

Voxel editing is currently supported for the following configurations:

**Storage**:

- Amazon S3 or any S3 compatible storage.
Comment thread
seankmartin marked this conversation as resolved.

**Data Format**:
Comment thread
seankmartin marked this conversation as resolved.

- Zarr v2 and Zarr v3 (including OME-Zarr), with the following Compression/Encoding:
- None (Raw)
- Blosc
- Gzip

Tools
-----

Voxel editing provides several tools for different annotation tasks. You can
bind these tools from the **Draw** tab to use/activate them.

.. _voxel-brush-tool:

Brush Tool
~~~~~~~~~~

The Brush tool allows you to paint voxels by clicking and dragging.

- **Paint**: Hold :kbd:`Control` + :kbd:`Left Click` and drag.
- **Erase**: Hold :kbd:`Control` + :kbd:`Shift` + :kbd:`Left Click` and drag.
- **Quick Flood Fill**: Hold :kbd:`Control` + :kbd:`Right Click` to trigger a
flood fill at the current position. Hold :kbd:`Shift` as well to erase.

Settings:
- **Brush size**: Adjust the radius of the brush.
- **Brush shape**: Choose between **Disk** and **Sphere** shapes.

.. _voxel-flood-fill-tool:

Flood Fill Tool
~~~~~~~~~~~~~~~

The Flood Fill tool fills a connected region of voxels on the current 2D plane.

- **Fill**: Hold :kbd:`Control` + :kbd:`Left Click`.
- **Clear**: Hold :kbd:`Control` + :kbd:`Shift` + :kbd:`Left Click`.

Settings:
- **Max fill voxels**: Limits the maximum number of voxels to fill to
prevent accidental large-scale changes. If the limit is exceeded, the
operation will be canceled.

.. note::
The flood fill will automatically fill small gaps in the connected region, proportionally to the number of voxels in the region. This feature may sometimes leave unpainted voxels in tight corners of the region.

.. _voxel-seg-picker-tool:

Seg Picker
~~~~~~~~~~

The Seg Picker tool allows you to adopt the voxel value at the current mouse
Comment thread
seankmartin marked this conversation as resolved.
Outdated
position as your active Paint Value.

Common Controls
---------------

The **Draw** tab provides several common controls:

- **Erase only selected value**: When enabled, the erase action only affects
voxels that match the current **Paint Value**. This feature will slow down
painting performance when erasing.
- **Undo / Redo**: Revert or re-apply recent changes.
- **Paint Value**: Manually specify the segment ID or intensity value to paint.
- **New Random Value**: Generates a new random segment ID.
Comment thread
seankmartin marked this conversation as resolved.
Outdated

Stamina System
--------------

When you perform many edits quickly, a stamina bar will appear below your cursor. This bar represents the amount of remaining work before all of your edits are processed and saved. **If you reload the page while the stamina bar is visible, you will lose some edits**. If the bar gets emptied painting will be halted until the system is able to catch up, this prevents neuroglancer from crashing due to too many edits in a short period of time.

About multi-resolution datasets
-------------------------------

Any multi-resolution dataset that has many-to-1 mapping (i.e. one child cannot have multiple parents) can be used for voxel annotation.

Although voxel annotation supports multi-resolution, any drawing operation will be performed on the highest resolution level, no matter what the current view is. Once an operation is completed, a downsampling pipeline will be triggered to update the lower resolution levels.

.. note::
Because of the 3D nature of the datasets, the downsampling may cause visual artifacts: when zoomed out you may see annotations that then disappear when zoomed in, those "invisible" annotations will be found on nearby slices.
25 changes: 25 additions & 0 deletions src/async_computation/encode_blosc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @license
* Copyright 2025 Google Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { encodeBlosc } from "#src/async_computation/encode_blosc_request.js";
import { registerAsyncComputation } from "#src/async_computation/handler.js";

registerAsyncComputation(encodeBlosc, async (data, config) => {
const { default: Blosc } = await import("numcodecs/blosc");
const codec = Blosc.fromConfig({ id: "blosc", ...config });
const result = await codec.encode(data);
return { value: result, transfer: [result.buffer] };
});
22 changes: 22 additions & 0 deletions src/async_computation/encode_blosc_request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2025 Google Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { asyncComputation } from "#src/async_computation/index.js";

export const encodeBlosc =
asyncComputation<(data: Uint8Array, config: any) => Uint8Array>(
"encodeBlosc",
);
17 changes: 15 additions & 2 deletions src/chunk_manager/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
LayerChunkProgressInfo,
} from "#src/chunk_manager/base.js";
import {
CHUNK_SOURCE_INVALIDATE_CHUNKS_RPC_ID,
CHUNK_LAYER_STATISTICS_RPC_ID,
CHUNK_MANAGER_RPC_ID,
CHUNK_QUEUE_MANAGER_RPC_ID,
Expand Down Expand Up @@ -1110,8 +1111,10 @@ export class ChunkQueueManager extends SharedObjectCounterpart {
}
}

invalidateSourceCache(source: ChunkSource) {
for (const chunk of source.chunks.values()) {
invalidateCachedChunks(source: ChunkSource, keys: string[]) {
for (const key of keys) {
const chunk = source.chunks.get(key);
if (!chunk) continue;
switch (chunk.state) {
case ChunkState.DOWNLOADING:
cancelChunkDownload(chunk);
Expand All @@ -1123,6 +1126,10 @@ export class ChunkQueueManager extends SharedObjectCounterpart {
// Note: After calling this, chunk may no longer be valid.
this.updateChunkState(chunk, ChunkState.QUEUED);
}
}

invalidateSourceCache(source: ChunkSource) {
this.invalidateCachedChunks(source, [...source.chunks.keys()]);
this.rpc!.invoke("Chunk.update", { source: source.rpcId });
this.scheduleUpdate();
}
Expand Down Expand Up @@ -1378,6 +1385,12 @@ registerRPC(CHUNK_SOURCE_INVALIDATE_RPC_ID, function (x) {
source.chunkManager.queueManager.invalidateSourceCache(source);
});

registerRPC(CHUNK_SOURCE_INVALIDATE_CHUNKS_RPC_ID, function (x) {
const source = <ChunkSource>this.get(x.id);
source.chunkManager.queueManager.invalidateCachedChunks(source, x.keys);
source.chunkManager.queueManager.scheduleUpdate();
});

registerPromiseRPC(
REQUEST_CHUNK_STATISTICS_RPC_ID,
function (x: { queue: number }) {
Expand Down
2 changes: 2 additions & 0 deletions src/chunk_manager/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ export const PREFETCH_PRIORITY_MULTIPLIER = 1e13;
export const CHUNK_QUEUE_MANAGER_RPC_ID = "ChunkQueueManager";
export const CHUNK_MANAGER_RPC_ID = "ChunkManager";
export const CHUNK_SOURCE_INVALIDATE_RPC_ID = "ChunkSource.invalidate";
export const CHUNK_SOURCE_INVALIDATE_CHUNKS_RPC_ID =
"ChunkSource.invalidateChunks";

export const REQUEST_CHUNK_STATISTICS_RPC_ID =
"ChunkQueueManager.requestChunkStatistics";
Expand Down
21 changes: 21 additions & 0 deletions src/chunk_manager/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
LayerChunkProgressInfo,
} from "#src/chunk_manager/base.js";
import {
CHUNK_SOURCE_INVALIDATE_CHUNKS_RPC_ID,
CHUNK_LAYER_STATISTICS_RPC_ID,
CHUNK_MANAGER_RPC_ID,
CHUNK_QUEUE_MANAGER_RPC_ID,
Expand Down Expand Up @@ -463,6 +464,26 @@ export class ChunkSource extends SharedObject {
this.chunks.delete(key);
}

invalidateChunks(keys: string[]): void {
const validKeys: string[] = [];
for (const key of keys) {
const chunk = this.chunks.get(key);
if (chunk) {
validKeys.push(key);
this.deleteChunk(key);
}
}

if (validKeys.length > 0) {
this.rpc!.invoke(CHUNK_SOURCE_INVALIDATE_CHUNKS_RPC_ID, {
id: this.rpcId,
keys: validKeys,
});

this.chunkManager.chunkQueueManager.visibleChunksChanged.dispatch();
}
}

addChunk(key: string, chunk: Chunk) {
this.chunks.set(key, chunk);
}
Expand Down
1 change: 1 addition & 0 deletions src/chunk_worker.bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ import "#src/annotation/backend.js";
import "#src/datasource/enabled_backend_modules.js";
import "#src/kvstore/enabled_backend_modules.js";
import "#src/worker_rpc_context.js";
import "#src/voxel_annotation/backend.ts";
Comment thread
briossant marked this conversation as resolved.
Outdated
3 changes: 3 additions & 0 deletions src/datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ export interface DataSubsource {
singleMesh?: SingleMeshSource;
segmentPropertyMap?: SegmentPropertyMap;
segmentationGraph?: SegmentationGraphSource;
// specify whether the datasource & kvstore implementations supports writing, is also responsible for showing the enableWriting checkbox in the UI
isPotentiallyWritable?: boolean;
Comment thread
briossant marked this conversation as resolved.
Outdated
}

export interface CompleteUrlOptionsBase extends Partial<ProgressOptions> {
Expand Down Expand Up @@ -216,6 +218,7 @@ export interface DataSourceWithRedirectInfo extends DataSource {

export interface DataSubsourceSpecification {
enabled?: boolean;
writingEnabled?: boolean;
}

export interface DataSourceSpecification {
Expand Down
1 change: 1 addition & 0 deletions src/datasource/zarr/async_computation.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import "#src/async_computation/decode_blosc.js";
import "#src/async_computation/decode_zstd.js";
import "#src/async_computation/encode_blosc.js";
Loading