Skip to content

Fix precomputed axes, units and layer type; one precomputed.zip per image - #236

Open
Robbie1977 wants to merge 6 commits into
developmentfrom
fix/precomputed-axes-layer-type-zip
Open

Robbie1977 wants to merge 6 commits into
developmentfrom
fix/precomputed-axes-layer-type-zip

Conversation

@Robbie1977

Copy link
Copy Markdown
Collaborator

This follows up #235 with the changes VFB needs before running the pipeline over the image store. Tested end-to-end on real JRC2018U folders: the template, two painted domains, FlyWire/hemibrain/LM neurons, a GAL4 line, a split line, an MCFO fragment and a VT line.

Axes. convert_nrrd.py transposed pynrrd's X,Y,Z array to Z,Y,X and reversed the header spacing to match, so every volume came out with x and z swapped (JRC2018U: size [174, 566, 1210], resolution [1.0, 0.519, 0.519]). The swap_xz on volume_man.obj meshes was compensating for that rather than fixing it: checked against the NRRD voxel extents of templates, domains, FlyWire/hemibrain neurons and LM neurons, every OBJ and SWC is already X,Y,Z in microns. The transpose, the reversal and swap_xz are gone.

Units. resolution, voxel_offset and mesh vertices are now in the units the precomputed spec defines: nanometres and voxel units (voxel_offset was the micron space origin). The frontend's shared coordinate space, which encoded the swapped axes and micron-as-nanometre scales, is now 1 nm per unit on x, y, z with the anterior view as default orientation.

Layer type. Every VFB NRRD is uint8, so choosing by dtype made templates and expression patterns 256-segment segmentations. The KB query now returns a category and the type follows what the image is:

category layer chunks mesh
template image intensities none
expression (VFBexp_* / VFBext_* classes) image intensities none
object (neurons, clones, painted domains) segmentation {0,1}, segment 1 volume_man.obj → generated from volume.swc → marching cubes

Without a KB category (--ids, filesystem scan) the same decision is made from the data.

One output per folder: precomputed.zip. Built in --work-dir (local scratch), copied in as a tmp name and renamed, so readers never see a partial file. It carries provenance.json (pipeline version + source size/mtime) so re-runs skip up-to-date folders and a PIPELINE_VERSION bump regenerates everything. The frontend builds <folder>/precomputed.zip|zip:|neuroglancer-precomputed: directly instead of crawling two directory listings, and uses type: 'auto' with segments: ['1'] so segmentation layers show their mesh. What the default scene should look like (template + domains + neurons) is still the open design question from the #235 thread — this just makes each layer render correctly.

Batch runs. --use-kb --list-targets targets.tsv writes the discovered targets with their category (40 s for the 680k JRC2018U images); workers take --targets-file batch.tsv --results results.jsonl, so only the planning step talks to the KB and each image gets one result line for the report.

Also: KB discovery uses the HTTP transaction endpoint via requests (vfb-connect dropped); --generate-mesh, --mesh-from-obj, --merge-segments, --min/max-intensity, --overwrite, --compress are removed as the category now decides. README updated.

Measured (one core): template 29 MB / 5 s; neurons and domains 0.3–0.9 MB / ~2 s; dense GAL4 16 MB / 5 s. VFB will run this as a low-priority Argo job over the ~680k JRC2018U images.

…mage

The NRRD path transposed pynrrd's X,Y,Z array to Z,Y,X and reversed the
header spacing to match, so every volume came out with x and z swapped
(JRC2018U: size [174, 566, 1210], resolution [1.0, 0.519, 0.519]). The
swap_xz applied to volume_man.obj meshes compensated for that rather than
fixing it; checked against the NRRD voxel extents of templates, painted
domains, FlyWire/hemibrain neurons and LM neurons, every OBJ and SWC is
already X,Y,Z in microns. Drop the transpose, the spacing reversal and
swap_xz.

Write resolution, voxel_offset and mesh vertices in the units the
precomputed spec defines: nanometres and voxel units (voxel_offset was the
micron space origin). The frontend's shared coordinate space, which had
encoded the swapped axes and micron-as-nanometre scales, now uses 1 nm per
unit on x, y and z with the anterior view as default orientation.

Decide the layer type from what the image is, not from the dtype: every
VFB NRRD is uint8, so templates and expression patterns were coming out as
256-segment segmentations. The KB query now returns a category (template /
expression / object); templates and expression patterns are image layers
with their intensities, neurons, clones and painted domains are
segmentation layers with every non-zero voxel as segment 1 plus one mesh
(volume_man.obj when it has faces, else generated from volume.swc, else
marching cubes). The same decision is made from the data when there is no
KB category.

One output per image folder: precomputed.zip, built in a local work dir
and copied in as a tmp name then renamed, with a provenance.json entry
(pipeline version + source file size/mtime) that makes re-runs skip
up-to-date folders. The frontend builds the layer URL directly
(<folder>/precomputed.zip|zip:|neuroglancer-precomputed:) instead of
crawling two HTML directory listings for a neuroglancer/ folder, and lets
Neuroglancer pick the layer type from the source with segment 1 shown.

KB discovery goes through the HTTP transaction endpoint with requests;
vfb-connect and its import stubbing are no longer needed.
A scheduled run has one plan pod that discovers the targets (KB query,
40 s for the 680k JRC2018U images) and many workers that each take a
batch. The workers need the category the plan found, not a KB round trip
of their own, and the report needs to know what each worker did:

  --list-targets TSV   write image_dir, vfb_id, template_id, category and exit
  --targets-file TSV   process one such batch
  --results JSONL      one line per image: layer type, bytes, seconds, error
numpy < 2.4 and scipy < 1.15: the cluster's VMs expose a qemu64 CPU and
newer wheels assume x86-64-v2. The optional Draco/igneous and navis
dependencies are left out; the production path uses legacy meshes.
cloud-volume creates ~/.cloudfiles and ~/.cloudvolume on first mesh
write; with no home for uid 1000 every segmentation failed with
'Permission denied: /.cloudfiles' on the first cluster run.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant