Feature: example linear registration pipeline#116
Feature: example linear registration pipeline#116seankmartin wants to merge 65 commits intomasterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements a feature to support linear registration workflows with custom clipping behavior for annotation layers across different coordinate spaces. The implementation adds a clipDimensionsWeight property that allows fine-grained control over which dimensions should be clipped during annotation rendering.
Changes:
- Added
clipDimensionsWeighttracking and state management across viewer components - Implemented Python bindings for
clip_dimensions_weightin annotation layers and viewer state - Created a comprehensive example script demonstrating interactive linear registration using point annotations
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/layer_groups_layout.ts | Added clipDimensionsWeight to common viewer state |
| src/layer_group_viewer.ts | Added clipDimensionsWeight property and type import |
| src/layer/annotation/index.ts | Added JSON key constant and state management for clipDimensionsWeight |
| src/data_panel_layout.ts | Added clipDimensionsWeight to ViewerUIState interface and common state |
| src/annotation/renderlayer.ts | Implemented clip dimension weight application in annotation projection parameters |
| src/annotation/annotation_layer_state.ts | Created TrackableClipDimensionsWeight class for state management |
| python/neuroglancer/viewer_state.py | Added Python bindings for clip_dimensions_weight and LinkedDisplayDimensions |
| python/neuroglancer/init.py | Exported LinkedDisplayDimensions |
| python/examples/example_linear_registration.py | Added comprehensive linear registration workflow example |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
afonsobspinto
left a comment
There was a problem hiding this comment.
Clicking 't' right away with the
afonsobspinto
left a comment
There was a problem hiding this comment.
The happy flow looks correct to me.
If the user doesn't follow the instructions the script crashes but I don't think that's a problem.
I only tried the demo mode following the video example and it worked similarly 👍
Summary
ViewerStateto expose thedisplayDimensionsof the Neuroglancer viewer state.Setup
From the repository main directory:
Linear registration workflow
The workflow is described in more detail in the docstring in the example file. But in short the most likely use path is as follows:
python -i example_linear_registration.py --url https://neuroglancer.demo.appspot.com/...In images that might look like this. This image is after placing the fixed and reference layers in the right layer groups:

And then after placing a number of points:

Here is a video of using the tool on the default included demo data, the points placed here could be a bit better, this is moreso to give an idea of the different steps of estimation and actions on pressing the custom functions bound to keys for the workflow:
https://github.com/user-attachments/assets/41f27c77-94d9-452d-9317-8fda9c2c3827
New annotation layer state -
clipDimensionsWeightOne problem arose during this script setup. As part of the script we created a second coordinate space. The annotations representing the registration points would contain information for both coordinate spaces. This allowed to conveniently know which points were linked, allow moving to the same spot in the fixed image and moving image quickly, allowing adjusting the points easily etc. There was one issue with this though, which is that the non-display dimension clipping meant that moving in the left panel caused the annotations in the right panel to disappear, and vice versa. Here shows the issue, and the state change proposed to allow changing the default weight on dimensions that are non-display dimensions. Setting that weight to zero means that no clipping happens on the specified dimension when it is a non display dimension.
2026-02-05.12-39-31.mp4
There are a few points to note about this though:
#uicontroldirective, but unsure if we want to introduce that kind of pattern. Either way, it could be something like#dimweight[0]=0.0 #dimweight[2]=0.5.clipDimensionsWeight. This is definitely a bit undesirable, but considering that I would imagine this state feature is likely only used by advanced users that might be ok. Regardless, thought it would be good to agree on the state representation / overall strategy here before worrying too much about those details.