Skip to content

Add skeleton and mesh downloads to the neuroglancer view - #178

Merged
floesche merged 3 commits into
mainfrom
feature/175-download-swc-and-obj
Sep 10, 2026
Merged

floesche merged 3 commits into
mainfrom
feature/175-download-swc-and-obj

Conversation

@floesche

@floesche floesche commented Sep 9, 2026

Copy link
Copy Markdown
Member

What this adds

A download icon next to the "open in new window" icon above the Neuroglancer view. It opens a modal dialog where the user picks a format and gets one zip file with one file per displayed neuron. For the male CNS the formats are coarse SWC skeleton, high-resolution SWC skeleton, and OBJ mesh (converted in the browser from the Neuroglancer legacy mesh, vertices in nanometers). Neurons without a file end up in missing_body_ids.txt inside the zip, and selections above 50 neurons ask for confirmation first.

How it works

  • Formats are configured per dataset in a new neuroglancer.download_formats list (see config/README.md). Each entry has a key, label, url_template with a {body_id} placeholder, and a kind (swc or ngmesh). Entries are validated when the config loads.
  • The list is embedded into the generated neuroglancer-url-generator.js; static/js/swc-download.js does the fetching, the OBJ conversion, and the zipping with the vendored fflate library, so everything still works in a local file system (vs web server).
  • The icon, the dialog and the two scripts are only rendered when the list is non-empty. Datasets without formats (hemibrain, optic lobe, FAFB, wasp) are unchanged.

Limitation worth knowing

The viewer is a cross-origin iframe, so the page cannot read its current URL. By default the download covers what the page sent to the viewer: the type's neurons plus the partners and ROIs ticked in the tables. Selections changed inside Neuroglancer are not visible to the page. For that case the dialog has a URL field: open the viewer in a new window, copy the URL, paste it, and the page parses the neuron layer's segments from it.

Files are fetched through the GCS JSON API (https://www.googleapis.com/storage/v1/b/<bucket>/o/<object>?alt=media) because the plain storage.googleapis.com URLs send no CORS headers.

Testing

  • New tests: config parsing and validation, embedding of the format list in the generated JS, and template gating (link, dialog and scripts appear only with formats configured). Full suite passes (421 tests), ruff clean.
  • Generated Tm3 pages with the CNS config, with the key removed, and with an empty list; only the first contains the download markup.
  • OBJ conversion checked against an independent Python parse of a real mesh fragment (same vertex and face counts, first vertex, first triangle, all indices in range).
  • Fetch and zip path exercised under node against the real bucket, including a 404 body ID landing in missing_body_ids.txt.
  • Not yet clicked through in a browser. Please try the dialog on a generated CNS page, including the OBJ option and the paste-URL path.

Also in this PR

Documentation in the user guide, developer guide, config/README.md, the generated-site README, the help page, and the top-level README.

Closes #175.

Closes #175. The "Neuron Visualization" header gets a download icon that opens a modal dialog. The dialog fetches one file per displayed neuron in the chosen format and saves them as a single zip archive, built in the browser with fflate. Neurons without a file are listed in missing_body_ids.txt inside the zip, and selections above 50 neurons ask for confirmation first.

Formats come from a new `neuroglancer.download_formats` list in the dataset config (key, label, url_template with a `{body_id}` placeholder, kind). `kind: swc` stores the response verbatim; `kind: ngmesh` addresses the Neuroglancer legacy mesh manifest, fetches its fragments and converts them to Wavefront OBJ (vertices in nanometers) client-side. Entries are validated at load time (placeholder present, known kind, unique keys). The icon, dialog and scripts are only rendered when the list is non-empty, so datasets without configured formats are unchanged. The male CNS config offers coarse SWC, high-resolution SWC and OBJ mesh from the public flyem-male-cns bucket.

The embedded viewer is a cross-origin iframe, so the page cannot read its current URL. Body IDs therefore default to the page's own neuroglancer state (type neurons plus ticked partners), which `initializeNeuroglancerLinks()` now exposes on `window`. As a fallback for selections changed inside the viewer, the dialog accepts a pasted Neuroglancer URL and takes the segments of the neuron layer, using the same layer lookup as the URL generator (`findMainSegmentationLayer`). Files are fetched through the GCS JSON API endpoint, since the plain storage.googleapis.com URLs send no CORS headers.
The download feature was a single bullet under "Viewing the 3D Model". It now has a "Downloading Neurons" subsection below "External neuPrint Link" that explains the dialog, the three formats offered for the male CNS (coarse SWC, high-resolution SWC, OBJ mesh) with their size and use cases, and the difference between leaving the Neuroglancer URL field empty (neurons the page sent to the viewer) and pasting a Neuroglancer URL (exactly the neurons visible in that view, including changes made inside Neuroglancer). Adds a screenshot of the dialog and reuses the "copy URL" screenshot. The section is still rendered only when the dataset configures download formats.
@floesche
floesche merged commit 7a54e73 into main Sep 10, 2026
8 checks passed
@floesche
floesche deleted the feature/175-download-swc-and-obj branch September 10, 2026 14:23
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.

Add download button for SWC files

1 participant