Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
401 commits
Select commit Hold shift + click to select a range
32442b4
fix: Keep visible segment ids on nodes refresh
afonsobspinto Apr 9, 2026
249d669
fix: correct moving to node position
seankmartin Apr 9, 2026
21f32e7
fix: also correct global position in picking
seankmartin Apr 9, 2026
ebf2fec
chore: remove comment as used in more than one place
seankmartin Apr 9, 2026
a3bb499
fix: apply transform and local to global permutation on mouse position
seankmartin Apr 10, 2026
800ca08
refactor: clean up the loop of setting position
seankmartin Apr 10, 2026
daab5e8
refactor: minor, but rename DEBUG to match more common ng pattern
seankmartin Apr 10, 2026
0a8cfab
fix: set position on move correctly and remove duplicate call
seankmartin Apr 10, 2026
41ed4af
revert: undo accidental change back of naming
seankmartin Apr 10, 2026
37ac4b2
feat: follow the pattern in annotation.ts to cache the chunkTransform
seankmartin Apr 10, 2026
f42e897
fix: use chunk transform for mouse
seankmartin Apr 10, 2026
0b5545e
perf: cache a float array for chunk pos
seankmartin Apr 10, 2026
6767d98
fix: don't set failed click to new array
seankmartin Apr 10, 2026
6aa9950
fix: map move node to correct spaces
seankmartin Apr 10, 2026
3f6cf3a
refactor: rename click pos to model space
seankmartin Apr 10, 2026
ba2a519
chore: add TODO to come back to
seankmartin Apr 10, 2026
fd53b78
perf: remove uneeded vec copy
seankmartin Apr 10, 2026
a803c19
feat: Add undo redo
afonsobspinto Apr 13, 2026
ba22140
feat: Style undo redo buttons
afonsobspinto Apr 13, 2026
09cd399
fix: Fix reroot call
afonsobspinto Apr 13, 2026
528571f
fix: Fix parsing after split
afonsobspinto Apr 14, 2026
dc3399c
fix: Fix split undo
afonsobspinto Apr 14, 2026
43a27f8
fix: Reorder nodes on split undo
afonsobspinto Apr 14, 2026
32eb893
style: Apply format and linting
afonsobspinto Apr 15, 2026
1fe21c1
Merge branch 'master' into feature/edit-mode
afonsobspinto Apr 15, 2026
7ece244
Merge branch 'feature/edit-mode' into fix/set-node-position
afonsobspinto Apr 16, 2026
32e592b
Merge pull request #126 from MetaCell/fix/set-node-position
afonsobspinto Apr 16, 2026
dcf0cff
Merge branch 'feature/edit-mode' into fix/set-node-position
afonsobspinto Apr 16, 2026
c589c24
Merge branch 'fix/set-node-position' into feature/edit-mode
afonsobspinto Apr 16, 2026
4253c16
Merge branch 'fix/set-node-position' into feature/edit-mode
afonsobspinto Apr 16, 2026
372cd08
feat: check if fetch error due to non existant skeleton
seankmartin Apr 16, 2026
0ed6da5
feat: cache non-existant skeletons in skeleton state
seankmartin Apr 16, 2026
39bf063
feat: change replaceCachedSegmentNodes to store empty array in cache …
seankmartin Apr 17, 2026
b4dc503
test: add test for new cache behaviour
seankmartin Apr 17, 2026
a45a745
Merge pull request #127 from MetaCell/fix/NA-691
afonsobspinto Apr 17, 2026
52e2dd9
refactor: Simplify and consolidate spatially indexed skeletons code
afonsobspinto Apr 19, 2026
3462fb2
Merge branch 'feature/edit-mode' of github.com:MetaCell/neuroglancer …
afonsobspinto Apr 19, 2026
4a7dc0a
docs: Add licence to new files
afonsobspinto Apr 19, 2026
242397c
style: Apply frontend linting
afonsobspinto Apr 19, 2026
ae8ec4d
refactor: Remove unnecessary attributes from interfaces
afonsobspinto Apr 19, 2026
372b655
feat: Remove label property
afonsobspinto Apr 20, 2026
c357d26
feat: Clean node anchors for merge on unselection
afonsobspinto Apr 20, 2026
863c3ff
feat: change co-ord display to be in units in both spatial skeletons …
seankmartin Apr 20, 2026
ee880f5
fix: correct layout of header and elements in cells
seankmartin Apr 20, 2026
da64363
fix: don't set state.value to undefined after super.captureSelectionS…
seankmartin Apr 21, 2026
ff0cf72
refactor: change to removing custom captureSelectionState logic
seankmartin Apr 21, 2026
de52e75
feat: Remove node coordinates search
afonsobspinto Apr 21, 2026
0a9b531
Merge pull request #128 from MetaCell/feat/NA-668
afonsobspinto Apr 21, 2026
53ab7fa
Merge pull request #129 from MetaCell/fix/NA-693
seankmartin Apr 21, 2026
6e48ad2
fix: listen to color changes in seg edit tab
seankmartin Apr 22, 2026
08de25e
feat: Allow merge with non-visible node
afonsobspinto Apr 22, 2026
56455e5
Merge branch 'feature/edit-mode' into feature/NA-718
afonsobspinto Apr 22, 2026
ff635b2
feat: Add pending message
afonsobspinto Apr 22, 2026
9ed4f02
feat: Update default grid size and rename catmaid metadata key
afonsobspinto Apr 23, 2026
7ae622e
Merge pull request #130 from MetaCell/fix/NA-664
afonsobspinto Apr 23, 2026
31ba188
Merge pull request #132 from MetaCell/feature/NA-688
seankmartin Apr 23, 2026
61f2a0c
refactor: Simplify root parsing
afonsobspinto Apr 23, 2026
4b63b55
Merge pull request #131 from MetaCell/feature/NA-718
seankmartin Apr 23, 2026
a77e943
refactor: remove mouseState listener in edit tab
seankmartin Apr 24, 2026
5574562
chore: lint and format
seankmartin Apr 24, 2026
3681ee0
merge feature/edit-mode and lint+format again
seankmartin Apr 24, 2026
7185dc4
Merge pull request #134 from MetaCell/chore/lint
seankmartin Apr 24, 2026
e2a1ef0
refactor: extract logic around hovered node into it's own class
seankmartin Apr 24, 2026
4178ba0
merge: merge feature branch
seankmartin Apr 24, 2026
2203fe0
chore: fix lint
seankmartin Apr 24, 2026
5db1b11
fix: Properly rewire children under recreated node (undo delete)
afonsobspinto Apr 24, 2026
080374e
Merge branch 'feature/edit-mode' into feature/NA-721
afonsobspinto Apr 24, 2026
fb4698e
Merge pull request #133 from MetaCell/fix/NA-727
seankmartin Apr 24, 2026
92beea2
feat: warn on too many skel attributes
seankmartin Apr 24, 2026
12d37fc
perf, refactor: don't bind twice for vertex attrs in skel
seankmartin Apr 24, 2026
808df70
Merge pull request #138 from MetaCell/fix/NA-705
afonsobspinto Apr 24, 2026
51812da
Merge pull request #136 from MetaCell/feature/NA-721
seankmartin Apr 24, 2026
5391848
docs: add v1 of spatial edit docs
seankmartin Apr 24, 2026
05dec91
fix: add to index and small accuracy of edit docs
seankmartin Apr 27, 2026
5bcb549
docs: update on actions, chunks, and merge survivor
seankmartin Apr 27, 2026
8657d9f
Merge pull request #139 from MetaCell/feat/NA-701
seankmartin Apr 27, 2026
ff675dd
refactor: Use inline 1e-9 instead of METERS_PER_NANOMETER
afonsobspinto Apr 28, 2026
75936af
refactor: Move cast to getMeshSource
afonsobspinto Apr 28, 2026
291c60d
feat: Move to parent if exists from a undo of an add node
afonsobspinto Apr 28, 2026
0b4c3dd
fix: account for both hidden and object alpha for skipping rendering
seankmartin Apr 29, 2026
e652048
Merge pull request #140 from MetaCell/feature/NA-704
seankmartin Apr 29, 2026
ebfa4ba
Merge pull request #141 from MetaCell/feature/NA-722
seankmartin Apr 29, 2026
631cdcf
feat: Change skeleton viewer to use virtual list; Removes show and ex…
afonsobspinto Apr 29, 2026
c8ac0fd
feat: Make skeleton tab stateful
afonsobspinto Apr 29, 2026
1dfaa6d
fix: Ignore historical labels when parsing description
afonsobspinto Apr 29, 2026
57537af
feat: Simplify selected spatial skeleton node info
afonsobspinto Apr 29, 2026
116bf31
refactor: WIP - Tight boundaries between generic spatial skeleton and…
afonsobspinto Apr 30, 2026
79ba410
fix: Stop evicting cached full skeleton data for non selected visible…
afonsobspinto Apr 30, 2026
954f21f
feat: Update selection on hover
afonsobspinto Apr 30, 2026
9115319
refactor: WIP - Simplify skeleton api
afonsobspinto Apr 30, 2026
a08b4a9
Merge pull request #144 from MetaCell/feature/NA-753
seankmartin Apr 30, 2026
f0d94ae
Merge branch 'feature/edit-mode' into fix/NA-735
seankmartin May 1, 2026
d4a25f6
refactor: remove custom functions for spatial skeleton json management
seankmartin May 1, 2026
0dc8ee2
wip: remove unwanted parts of state
seankmartin May 1, 2026
68b2194
refactor: remove code related to old state management
seankmartin May 1, 2026
be339cb
refactor: remove customisation from skeleton grid render scale
seankmartin May 1, 2026
659008e
refactor: remove chunk stats code
seankmartin May 1, 2026
8051feb
refactor: remove visibility and double watches
seankmartin May 1, 2026
f37ecc8
refactor: clean up types in isReady
seankmartin May 1, 2026
1c0bdfb
fix: add another case of hidden opacity
seankmartin May 1, 2026
33de761
fix: correct transparent logic
seankmartin May 1, 2026
6936eb5
chore: remove confusing comment
seankmartin May 1, 2026
5927d48
Merge pull request #143 from MetaCell/fix/NA-735
afonsobspinto May 4, 2026
593c7d6
Merge remote-tracking branch 'origin/feature/edit-mode' into feature/…
afonsobspinto May 4, 2026
012b15a
merge feature/edit-mode
seankmartin May 4, 2026
c36911d
refactor: stub draw methods
seankmartin May 4, 2026
6a08e2f
refactor: remove uneeded guards
seankmartin May 4, 2026
915315a
refactor: remove custom state fn
seankmartin May 4, 2026
464b003
wip: experiment with layer consolidation
seankmartin May 4, 2026
6b1e341
fix: remove resolving to nearest grid
seankmartin May 4, 2026
17d92f3
fix: update tests for removed code
seankmartin May 4, 2026
a0fe01a
fix: only show current / current as lod in render scale widget
seankmartin May 4, 2026
3aa6395
fix: don't triple count histogram for 3 panels
seankmartin May 4, 2026
9dad654
fix: remove some counting issues on panels
seankmartin May 4, 2026
655795f
debug: add visual debugging for overlay and browse interaction
seankmartin May 5, 2026
40ff1cb
perf: small perf, not check excluded segs if no shader
seankmartin May 5, 2026
62c5822
typing: clean up setColor type
seankmartin May 5, 2026
d9e1b00
perf: avoid flipping bind back and forth between node/edge shader
seankmartin May 5, 2026
1fd3a6c
refactor: continue cleaning up draw
seankmartin May 5, 2026
b39d84b
fix: correct lint
seankmartin May 5, 2026
128872e
refactor: WIP - Tight boundaries between generic spatial skeleton and…
afonsobspinto May 4, 2026
e140fb0
feat: Remove LOD from generic api
afonsobspinto May 5, 2026
b662b52
Merge pull request #145 from MetaCell/feat/NA-641
afonsobspinto May 5, 2026
3a35612
Merge remote-tracking branch 'origin/feature/edit-mode' into feature/…
afonsobspinto May 5, 2026
219bd34
Merge branch 'feature/edit-mode' into feat/NA-711
seankmartin May 5, 2026
e05f198
merge: merge feature/edit-mode after state simplifiication
seankmartin May 5, 2026
20d2d39
feat: remove uneeded skeleton regular source check from rendering
seankmartin May 5, 2026
0d1273f
fix: correct access
seankmartin May 5, 2026
2cc800e
feat: Add read-only flag
afonsobspinto May 5, 2026
ceb62ba
refactor: combine debounces into one
seankmartin May 5, 2026
259a574
fix: set view owner
seankmartin May 5, 2026
e006de2
fix: remove double attachment
seankmartin May 5, 2026
6b63aef
refactor: clean up debug
seankmartin May 5, 2026
5ad1f09
feat: Make spatially indexed skeletons metadata mandatory
afonsobspinto May 5, 2026
9516fd0
docs: Update user guide
afonsobspinto May 5, 2026
2778578
refactor: clean up chunk usage in FE for browse pass
seankmartin May 6, 2026
a1137bd
refactor: small change to use 3fv not 3f
seankmartin May 6, 2026
984f93e
debug: add chunk color and wireframe debugs
seankmartin May 6, 2026
9992aa3
feat: Use single source of truth for read-only
afonsobspinto May 6, 2026
02265f0
refactor: update model matrix handling
seankmartin May 6, 2026
64ce708
refactor: make bounding box draw more general
seankmartin May 6, 2026
9debdce
feat: use wireframe from render context
seankmartin May 6, 2026
4e3a5a9
refactor: Modify edit interface to require commands
afonsobspinto May 6, 2026
0818b71
feat: add debug to remove cross chunk nodes
seankmartin May 6, 2026
c3dedc0
fix: set default debug to false
seankmartin May 6, 2026
47004dc
perf: avoid rebuilding on cache hit
seankmartin May 6, 2026
0e805ab
feat: Split editNodeProperties into editNodeRadius and editNodeConfi…
afonsobspinto May 6, 2026
ec43d1e
hotfix: Force second request to catmaid to get live tags only
afonsobspinto May 6, 2026
6c2dfae
Merge pull request #150 from MetaCell/feat/NA-615
afonsobspinto May 6, 2026
d64ee50
Merge pull request #147 from MetaCell/refactor/skeleton-layers
afonsobspinto May 6, 2026
8f29b6e
Merge remote-tracking branch 'origin/feature/edit-mode' into feature/…
afonsobspinto May 6, 2026
f714b04
fix: correct 3fv call to use vec3
seankmartin May 7, 2026
5257f24
Merge pull request #148 from MetaCell/feat/NA-711
seankmartin May 7, 2026
4799d08
fix: use string based chunk key and sep debug mode for colors/wireframe
seankmartin May 7, 2026
7a145ab
feat: keep colors consistent across sessions
seankmartin May 7, 2026
4b4261d
fix: remove debug flag from catmaid re nodes in box
seankmartin May 7, 2026
fbd3d84
Merge branch 'debug/chunk-debugging' of https://github.com/MetaCell/n…
seankmartin May 7, 2026
5152d6a
Merge pull request #149 from MetaCell/debug/chunk-debugging
seankmartin May 7, 2026
e9c3f39
feat: minor change, formatting and use white wireframe to match ng
seankmartin May 7, 2026
0e494a5
Merge branch 'feature/edit-mode' into feature/NA-767
afonsobspinto May 7, 2026
0f0a01f
refactor: Rename readOnly to readonly
afonsobspinto May 7, 2026
3e9c7fa
feat: Use getDefaultSpatiallyIndexedSkeletonChunkSize when metadata i…
afonsobspinto May 7, 2026
a96390c
refactor: Merge edit and spatial skeleton errors
afonsobspinto May 7, 2026
5892780
lint: Run linter and formatter
afonsobspinto May 7, 2026
d4b79e1
refactor: extract common rendering to both passes
seankmartin May 7, 2026
9e6dd11
refactor: extract mousestate and pick transforming to reused functions
seankmartin May 7, 2026
cd850ba
feat: add frame based protection to overlay source rebuild
seankmartin May 7, 2026
d59c94e
fix: should have been in prev commit
seankmartin May 7, 2026
ec0573d
fix: more future proof overlay attribute texture setup
seankmartin May 7, 2026
181ea16
refactor: add common funcs for gpu upload/free for skeletons
seankmartin May 7, 2026
904b7c1
refactor: explicitly set to undefined with comment on colorattr for b…
seankmartin May 7, 2026
457af48
refactor: update interfaces and classes
seankmartin May 7, 2026
7e8e8ca
refactor: drop unsused source options from catmaid
seankmartin May 7, 2026
bb90d20
Merge pull request #146 from MetaCell/feature/NA-767
seankmartin May 7, 2026
8ad5abb
refactor: remove casts where possible in frontend.ts
seankmartin May 7, 2026
26a43fd
perf: improve memory management for overlay
seankmartin May 8, 2026
80a13d5
refactor: move generic texture fn to texture_access with test
seankmartin May 8, 2026
50a8176
refactor: remove unclear boundary of gpu_upload and reinline
seankmartin May 8, 2026
d51719f
feat: Target affect chunks for invalidation after edit operations
afonsobspinto May 8, 2026
191f3b3
refactor: align skeleton render with seg render_layer patterns
seankmartin May 8, 2026
f581717
refactor: cleaner var names in render helper
seankmartin May 8, 2026
0a3ec4d
feat: Reduce priority of browse chunks requests
afonsobspinto May 8, 2026
5b8c960
fix: define GPU hash tables up front and registerDisposer on them
seankmartin May 8, 2026
030cd60
Merge branch 'refactor/skeleton-frontend' into feature/NA-716
afonsobspinto May 8, 2026
d01f462
note: TODO an important thing to fix and good refactoring
seankmartin May 8, 2026
1b01ddf
feat: further expand todo
seankmartin May 8, 2026
297edfb
refactor: small cleanup on selected node and seg value
seankmartin May 8, 2026
b9151a5
feat: Keep selection when activating edit tools
afonsobspinto May 8, 2026
046ac6b
refactor: revert change to support more attr types in user path
seankmartin May 8, 2026
31ba572
refactor: move small file back into main FE file
seankmartin May 8, 2026
72a39cc
fix: correct imports, hopefully nothing circular, can come back if need
seankmartin May 8, 2026
19ed4d3
refactor: avoid some overlaps
seankmartin May 8, 2026
3915ef8
Merge pull request #151 from MetaCell/refactor/skeleton-frontend
afonsobspinto May 8, 2026
f440517
feat: Add priority boos to spatially indexed skeletons
afonsobspinto May 10, 2026
0fda0f4
Merge pull request #154 from MetaCell/feature/NA-733
seankmartin May 11, 2026
88c120c
Merge pull request #153 from MetaCell/feature/NA-716
seankmartin May 11, 2026
59afa35
Merge branch 'feature/edit-mode' into refactor/skeleton-frontend-cont
seankmartin May 11, 2026
5d99812
refactor: combine base/common shader fns, rename self var
seankmartin May 11, 2026
74e296e
Merge pull request #155 from MetaCell/refactor/skeleton-frontend-cont
afonsobspinto May 11, 2026
cafe845
fix: correct node highlight
seankmartin May 11, 2026
29328e1
merge: merge feature/edit-mode
seankmartin May 11, 2026
0aef0e3
fix: correct merge conflict
seankmartin May 11, 2026
a612a4b
Merge pull request #157 from MetaCell/fix/node-highlight
afonsobspinto May 11, 2026
c9257e4
Merge branch 'feature/edit-mode' into feature/NA-757
afonsobspinto May 11, 2026
2e40b7b
refactor: Rename functions to match effect on both 2D and 3D
afonsobspinto May 11, 2026
2ead929
Merge pull request #156 from MetaCell/feature/NA-757
seankmartin May 12, 2026
64fe984
fix: correct broken test due to missing webgl context
seankmartin May 12, 2026
ca282c4
refactor: combine overlay geom and retention into one
seankmartin May 12, 2026
c8d783a
test: combine overlay test files after refactor
seankmartin May 12, 2026
7ef998d
refactor: consolidate picking file into frontend
seankmartin May 12, 2026
891ff47
refactor: remove stub file and test on const
seankmartin May 12, 2026
b272f58
chore: add license
seankmartin May 12, 2026
3858d94
refactor: combine some skeleton files and some clearer names
seankmartin May 12, 2026
dee773a
test: rename test after related file change
seankmartin May 12, 2026
097d61c
docs: remove old doc
seankmartin May 12, 2026
704f044
chore: add missing license files
seankmartin May 12, 2026
030a79a
fix: correct lint on calling changed interface
seankmartin May 12, 2026
1dde459
refactor: remove as import
seankmartin May 12, 2026
6a354c9
rename _state file with internal state
seankmartin May 12, 2026
78d83fe
refactor: use annotationId pattern for nodeId
seankmartin May 12, 2026
5b8050c
revert: remove uneeded format hover
seankmartin May 12, 2026
1ffd954
python: add state for new viewer state related to skesl
seankmartin May 12, 2026
f915255
refactor: convert node type as str to enum
seankmartin May 12, 2026
ddc83f4
Merge pull request #159 from MetaCell/refactor/review-skeletons
afonsobspinto May 12, 2026
9ace968
fix: general fix, protect against credentials on no provider
seankmartin May 12, 2026
6636ffc
fix, python: add catmaid credential default provider python
seankmartin May 12, 2026
6718996
fix, python: correct outdated selection state
seankmartin May 12, 2026
7062dd2
feat, python: add catmaid default cred provider
seankmartin May 12, 2026
e971569
fix, python: correct filter type repr in state
seankmartin May 12, 2026
ee5cce8
python, example: add example of controlling skeleton state
seankmartin May 12, 2026
c297f5e
feat: add first version of frag shader culling for skel chunks
seankmartin May 13, 2026
8f58667
refactor: clarify emitDefault and emitRGBA relation
seankmartin May 13, 2026
9aa58de
fix: move chunk setting outside of pick branch
seankmartin May 13, 2026
8e90a2f
fix: correct debug on skeleton chunks
seankmartin May 13, 2026
c15d272
feat: add hover highlight and seg highlight
seankmartin May 13, 2026
9a7ed1a
fix: don't consider lod undefined as not ready
seankmartin May 13, 2026
6506b38
fix: isReady considers only current LOD level
seankmartin May 13, 2026
c36306f
refactor: remove uneeded seen set management, combine chunk manage paths
seankmartin May 13, 2026
bcedeb6
chore: Remove deprecated python tests
afonsobspinto May 14, 2026
3a4b31b
Merge pull request #163 from MetaCell/fix/skeleton-screenshot
afonsobspinto May 14, 2026
991e1ab
Merge pull request #162 from MetaCell/fix/skeleton-highlight
afonsobspinto May 14, 2026
4f7b6fa
Merge pull request #161 from MetaCell/fix/skeleton-double-rendering
afonsobspinto May 14, 2026
1b25340
Merge pull request #160 from MetaCell/refactor/review-skeletons-logic
afonsobspinto May 14, 2026
15125c9
refactor: Deduplicate commands switch logic
afonsobspinto May 14, 2026
ab2aaa5
refactor: Deduplicate CATMAID spatial skeleton code
afonsobspinto May 14, 2026
5c28df6
refactor: Remove deprecated method
afonsobspinto May 14, 2026
45306a2
chore: bump max retained overlay segs
seankmartin May 15, 2026
4ca419b
Merge pull request #165 from MetaCell/feature/deduplicate_commands_code
seankmartin May 15, 2026
67a8f29
chore: lint and format
seankmartin May 15, 2026
a3df1ed
Merge remote-tracking branch 'upstream/master' into feature/edit-mode
afonsobspinto May 15, 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
2 changes: 1 addition & 1 deletion 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/skeleton_editing

.. toctree::
:hidden:
Expand Down Expand Up @@ -42,4 +43,3 @@ Neuroglancer
Neuroglancer is a WebGL-based viewer for volumetric data. It is capable of
displaying arbitrary (non axis-aligned) cross-sectional views of volumetric
data, as well as 3-D meshes and line-segment based models (skeletons).

218 changes: 218 additions & 0 deletions docs/user-guide/skeleton_editing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
Skeleton Editing
================

Neuroglancer supports interactive editing of skeleton annotations, including
adding, moving, and deleting nodes, as well as merging and splitting skeletons.

.. _skeleton-editing-sources:

Supported Sources
-----------------

Skeleton editing is currently only supported on CATMAID data sources. See the
CATMAID documentation to set up a CATMAID server. At minimum you will need:

- A CATMAID project
- A linked project stack
- ``AnonymousUser`` permissions to read and edit the data on that project
- Skeletons initialised for that project

The project stack dimensions and resolution are used to inform the bounding box
of the data in neuroglancer as their product. Skeletons in CATMAID are in 1 nm
units.

The linked CATMAID stack may define spatial skeleton metadata. When present,
Neuroglancer uses this metadata to build the spatially indexed skeleton source
required for editing. Add a ``spatial`` array to the stack metadata, with one
entry for each spatial index level:

.. code-block:: json

{
"spatial": [
{
"chunk_size": [11168145, 11168145, 11168145],
"limit": 500
},
{
"chunk_size": [3939000, 3939000, 3939000],
"limit": 7000
}
],
"cache_provider": "cached_msgpack_grid",
"read_only": false
}

``chunk_size`` is specified in CATMAID project-space nanometers. ``limit`` is
the maximum node count expected for that spatial level and is required.
``cache_provider`` is optional and, when present, is passed to CATMAID node-list
requests. If ``read_only`` is not set to ``false``, Neuroglancer treats the
source as read-only: skeletons can be inspected, but edit actions are disabled.

If ``spatial`` is absent or empty, Neuroglancer derives a default chunk size
from the CATMAID project-space bounds and uses ``limit: 0`` for the generated
spatial level.

After setting this up, enter ``catmaid:<your-catmaid-server-url>/<your-catmaid-project-id>`` as a data source in neuroglancer.

.. _skeleton-editing-subsources:

Layer Subsources
----------------

The data source exposes two skeleton subsources. The first is a spatially indexed
skeleton source, which is required for editing. The second is the regular skeleton
subsource from the pre-existing pipeline for rendering precomputed format skeletons.

In the **Render** tab you can adjust:

- **Opacity (3d)** — controls the opacity of fully loaded, visible skeletons.
- **Hidden Opacity (3d)** — controls the opacity of hidden skeletons, which represent
spatially indexed indicators of nodes in space.

When you make a skeleton visible, a full fetch is triggered and you are guaranteed
to see all nodes and details of that skeleton. Otherwise you see whatever is
provided by the spatial index level selected for the current view. The selected
grid size is controlled via the **Resolution (skeleton grid 2D)** and
**Resolution (skeleton grid 3D)** settings.

The **Seg** tab works as normal for a segmentation layer, allowing you to set the
visibility of segments/skeletons by their ID or by label if one has been assigned.

.. _skeleton-editing-tab:

Skeleton Tab
------------

The **Skeleton** tab is used for editing and viewing information about skeletons.
It is only available for CATMAID sources with an active spatially indexed skeleton
subsource, and only visible skeletons appear here. If the CATMAID stack metadata
does not set ``read_only`` to ``false``, inspection remains available but edit
actions are disabled.

You can find a node by ID or by description, and filter nodes to show only:

- Leaves
- Virtual ends
- True ends
- Nodes with descriptions

You can also pick a subset of the visible skeletons to display information about in this menu.

Skeleton Navigation
~~~~~~~~~~~~~~~~~~~

The skeleton tab provides buttons for navigating through the skeleton tree:

- Go to the root
- Go to the start of the current branch
- Go to the end of the current branch
- Cycle through nodes at the current level
- Go to the parent or child of the current node (if there are multiple children,
one is chosen at random)
- Go to the nearest node that is a leaf but not marked as a true end

You can also interact with nodes in the details viewer by right-clicking to move
to a node, or left-clicking to select it and move to it.

.. _skeleton-node-types:

Node Types
----------

Nodes use symbols to indicate their type:

- **Root** — the root node of the skeleton
- **Regular node** — an interior node along a branch
- **Branch point** — a node with more than one child
- **Virtual end** — a leaf node that has not been marked as a true end
- **True end** — a leaf node manually marked by a reviewer as the end of a branch

You can toggle a node between virtual end and true end by clicking its type icon
in the skeleton tab table. This only applies to visible segments.

.. _skeleton-node-properties:

Node Properties
---------------

To edit the detailed properties of a node, first make the segment visible, then
select the node by either:

- Right-clicking on it in the viewer while holding :kbd:`Control`
- Left-clicking on it in the skeleton tab table

Once a node is selected, you can:

- Delete the node *
- Change the node type *
- Make the node the root of the skeleton *
- Change the radius
- Change the confidence level
- Add or edit a free-text description

.. note::
* These actions can also be performed from the skeleton tab table.

.. _skeleton-editing-tools:

Editing Tools
-------------

To make structural edits to nodes, you must bind at least some of the editing
tools available in the skeleton tab. The available tools are **Edit**, **Merge**,
and **Split**.

To bind a tool, click on it in the UI and hold down a key. To activate the tool,
press :kbd:`Shift` + the bound key. For example, if you bind :kbd:`E` to the Edit
tool, pressing :kbd:`Shift+E` activates it.

An important concept throughout editing is the *selected node*. The selected node
is highlighted with a border in the viewer, highlighted in the skeleton tab table,
and its details are shown in the selection details panel.

Edit Tool
~~~~~~~~~

With the Edit tool active:

- **Move a node** — select the node, then hold :kbd:`Alt` and left-click and drag
it to the new location. This does not use picking to snap to nearby objects.
- **Add a child node** — select an existing node, then :kbd:`Control`-click where
you want to place the new node. The new node is added as a child of the selected
node.
- **Start a new skeleton** — :kbd:`Control`-click with no node selected to add a
root node with no parent.

Merge Tool
~~~~~~~~~~

With the Merge tool active, select the "from" node first and then the "to" node. You must merge from a visible skeleton, but the "to" node may belong to a non-visible skeleton.
The surviving skeleton ID will be the ID of the skeleton containing the "from"
node. The only exception to this is if the CATMAID skeleton has annotations, and one of the skeletons is annotated as ``stable`` -- in this case, the surviving skeleton ID is from the one that was annotated as ``stable``. It is not currently possible to set these annotations within neuroglancer.

Split Tool
~~~~~~~~~~

With the Split tool active, select the node at which to split. The selected node
is included in the newly created skeleton, not the surviving original skeleton.
The edge between the selected node and its parent is deleted, and the selected
node becomes the root of the new skeleton. A split always produces exactly two
skeletons, regardless of whether the selected node is a branch point or a leaf.
You can only split visible skeletons.

.. _skeleton-editing-undo:

Undo and Redo
-------------

The skeleton tab provides **Undo** and **Redo** buttons. When any operation is
performed, its inverse is stored in the history. Note that the inverse of an
atomic operation is not necessarily atomic: for example, undoing a merge involves
a split followed by a reroot. Without the reroot step, the split skeleton could
end up with a different root than it had before the merge.

Undo does not restore the skeleton ID to its pre-operation value, so a merge
followed by an undo will result in one of the skeletons having a new ID compared
to before the merge (specifically, the skeleton that did not "survive" the
original merge).
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@
"neuroglancer/datasource/boss:disabled": "./src/util/false.ts",
"default": "./src/datasource/boss/backend.ts"
},
"#datasource/catmaid/backend": {
"default": "./src/datasource/catmaid/backend.ts"
},
"#datasource/catmaid/register_default": {
"default": "./src/datasource/catmaid/register_default.ts"
},
"#datasource/boss/async_computation": {
"neuroglancer/datasource/boss:enabled": "./src/datasource/boss/async_computation.ts",
"neuroglancer/datasource:none_by_default": "./src/util/false.ts",
Expand Down Expand Up @@ -535,4 +541,4 @@
"default": "./src/util/false.ts"
}
}
}
}
61 changes: 61 additions & 0 deletions python/examples/example_spatial_skeletons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import argparse

import neuroglancer
import neuroglancer.cli
import numpy as np

voxel_size = np.array([10, 10, 10])

shape = (100, 100, 100)

segmentation = np.arange(np.prod(shape), dtype=np.uint32).reshape(shape)

viewer = neuroglancer.Viewer()
dimensions = neuroglancer.CoordinateSpace(
names=["x", "y", "z"],
units="nm",
scales=[10, 10, 10],
)
with viewer.txn() as s:
s.layers.append(
name="a",
layer=neuroglancer.SegmentationLayer(
source=[
neuroglancer.LocalVolume(
data=segmentation,
dimensions=dimensions,
), # example of segmentation that could accompany the skeleton
"catmaid://http://localhost:8000/4", # replace with your catmaid URL/project ID
],
tab="skeleton",
),
)
# Can adjust the skeleton rendering options
s.layers[0].skeleton_rendering.mode2d = "lines"
s.layers[0].skeleton_rendering.line_width2d = 3
s.layers[0].skeleton_rendering.mode3d = "lines_and_points"
s.layers[0].skeleton_rendering.line_width3d = 10

# Can adjust visibility of layer side panel
s.selected_layer.layer = "a"
s.selected_layer.visible = True

# Can set the new spatial related options
layer = s.layers[0]
layer.spatial_skeleton_node_query = "1"
layer.spatial_skeleton_node_filter = neuroglancer.SpatialSkeletonNodeFilterType.LEAF
layer.hidden_object_alpha = 0.8
layer.skeleton_cross_section_render_scale = 4.0
layer.skeleton_perspective_render_scale = 4.0
layer.visible_segments = [649]

# Can pick a specific segment and node to select
selection_for_layers = s.selection.layers
selection_for_layers["a"] = {"value": "649", "nodeId": "131"}

if __name__ == "__main__":
ap = argparse.ArgumentParser()
neuroglancer.cli.add_server_arguments(ap)
args = ap.parse_args()
neuroglancer.cli.handle_server_arguments(args)
print(viewer)
1 change: 1 addition & 0 deletions python/neuroglancer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
InvlerpParameters, # noqa: F401
TransferFunctionParameters, # noqa: F401
ImageLayer, # noqa: F401
SpatialSkeletonNodeFilterType, # noqa: F401
SkeletonRenderingOptions, # noqa: F401
StarredSegments, # noqa: F401
VisibleSegments, # noqa: F401
Expand Down
38 changes: 38 additions & 0 deletions python/neuroglancer/catmaid_credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# @license
# Copyright 2026 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 json
import urllib.request

from . import credentials_provider
from .futures import run_on_new_thread


class CatmaidAnonymousCredentialsProvider(credentials_provider.CredentialsProvider):
def __init__(self, parameters):
super().__init__()
self.server_url = (parameters or {}).get("serverUrl", "")

def get_new(self):
server_url = self.server_url

def func():
token_url = f"{server_url}/accounts/anonymous-api-token"
with urllib.request.urlopen(token_url) as response:
data = json.loads(response.read().decode())
if not isinstance(data, dict) or not isinstance(data.get("token"), str):
raise RuntimeError(f"Unexpected response from {token_url}: {data!r}")
return {"token": data["token"]}

return run_on_new_thread(func)
5 changes: 4 additions & 1 deletion python/neuroglancer/credentials_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ def register(self, key, credentials_provider_getter):
self._providers[key] = credentials_provider_getter

def get(self, key, parameters):
return self._providers[key](parameters)
getter = self._providers.get(key)
if getter is None:
return None
return getter(parameters)


class CredentialsProvider:
Expand Down
8 changes: 8 additions & 0 deletions python/neuroglancer/default_credentials_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from . import (
boss_credentials,
catmaid_credentials,
credentials_provider,
dvid_credentials,
google_credentials,
Expand Down Expand Up @@ -46,6 +47,13 @@
),
)

default_credentials_manager.register(
"CATMAID",
lambda parameters: catmaid_credentials.CatmaidAnonymousCredentialsProvider(
parameters
),
)


def set_boss_token(token):
"""Sets the authentication token for connecting to bossDB.
Expand Down
Loading
Loading