Conversation
Ports quickflat/laminar.py into the browser: draw a line across the
flatmap and get the W x H matrix spanning that line (gamma) and cortical
depth (alpha, pial to white matter), sampled from the volume.
Everything is computed client-side, nothing is round-tripped to python:
laminar.js FlatIndex is a uniform grid over the flatmap triangles,
standing in for the scipy Delaunay/trifinder (the flatmap
already carries its own triangulation). For each of the W+1
columns it locates the flatmap point and barycentrically
interpolates the pial position, the white matter position
and the two surface areas -- _column_geometry(), once per
column rather than once per pixel.
Shaders.laminar Per fragment, turns alpha into an equivolume depth
(_depth_blend), mixes pial/wm to get that pixel's own
anatomical coordinate, pushes it through volxfm and samples
+ colormaps it via the same colorlut() the surface shader
uses. So each panel pixel maps to its own point in the
volume, and vmin/vmax/colormap/sampler follow the dataview.
The line lives in the shared, nudged flatmap space (the uv attribute),
which is the same merged space laminar.py triangulates. That makes the
profile independent of the view state and lets a line run across both
hemispheres, with columns landing in the gap coming out transparent.
The line is drawn into a flatmap-space texture that the surface shader
composites through vUv alongside the ROI overlay, so it sits on the
cortex in every view -- flattened, inflated or folded -- with the right
occlusion. Endpoints are dragged from a screen-space overlay that is
only active while the brain is flat.
UI: a "depth profile" folder (show / equivolume / samples / depths /
reset_line, shortcut J) and a draggable panel. The readout reports the
endpoints in raw flatmap units, i.e. the arguments make_laminar_profile()
takes.
Verified against cortex.quickflat.laminar on S1: the columns computed in
the browser match _column_geometry to within CTM quantization (<0.002
voxels). The equivolume spacing uses the viewer's smoothed per-vertex
areas rather than laminar.py's raw triangle areas, so the profile's
depths agree with what the surface shader draws at the same depth.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add cortical depth profiles to the webgl viewer
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Visualize laminar data with quickflat tool or webgl.
Closes #731.
quickflat/laminar.py
Given two points (flatmap coordinates) on the surface, grab cortical depth data along the line that connects the two points.
webgl
Ports quickflat/laminar.py into the browser: draw a line across the flatmap and get the W x H matrix spanning that line (gamma) and cortical depth (alpha, pial to white matter), sampled from the volume.
Everything is computed client-side, nothing is round-tripped to python:
laminar.js FlatIndex is a uniform grid over the flatmap triangles,
standing in for the scipy Delaunay/trifinder (the flatmap
already carries its own triangulation). For each of the W+1
columns it locates the flatmap point and barycentrically
interpolates the pial position, the white matter position
and the two surface areas -- _column_geometry(), once per
column rather than once per pixel.
Shaders.laminar Per fragment, turns alpha into an equivolume depth
(_depth_blend), mixes pial/wm to get that pixel's own
anatomical coordinate, pushes it through volxfm and samples
uses. So each panel pixel maps to its own point in the
volume, and vmin/vmax/colormap/sampler follow the dataview.
The line lives in the shared, nudged flatmap space (the uv attribute), which is the same merged space laminar.py triangulates. That makes the profile independent of the view state and lets a line run across both hemispheres, with columns landing in the gap coming out transparent.
The line is drawn into a flatmap-space texture that the surface shader composites through vUv alongside the ROI overlay, so it sits on the cortex in every view -- flattened, inflated or folded -- with the right occlusion. Endpoints are dragged from a screen-space overlay that is only active while the brain is flat.
UI: a "depth profile" folder (show / equivolume / samples / depths / reset_line, shortcut J) and a draggable panel. The readout reports the endpoints in raw flatmap units, i.e. the arguments make_laminar_profile() takes.
Verified against cortex.quickflat.laminar on S1: the columns computed in the browser match _column_geometry to within CTM quantization (<0.002 voxels). The equivolume spacing uses the viewer's smoothed per-vertex areas rather than laminar.py's raw triangle areas, so the profile's depths agree with what the surface shader draws at the same depth.