Skip to content

VIS-4a: remove braincell.vis; Morphology.to_vis_data, NodeTree.to_topology_data, Cell.topology_data - #198

Merged
chaoming0625 merged 2 commits into
mainfrom
vis-4a
Nov 8, 2026
Merged

chaoming0625 merged 2 commits into
mainfrom
vis-4a

Conversation

@chaoming0625

@chaoming0625 chaoming0625 commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

VIS-4a: braincell.vis is deleted. Plotting lives in braintools.visualize.morphology (bvm), which arrived with braintools 0.5.0 (chaobrain/braintools#143). braincell converts its objects with three adapter methods, and vis2d/vis3d draw through bvm. This is breaking with no deprecation, by the maintainers' decision for 0.3. The migration is the pair of tables in the changelog.

Changes

  • Deleted: braincell/vis/ (81 files, −18 447 lines).
    • braincell/__init__.py no longer imports or exports vis.
    • import braincell.vis raises ModuleNotFoundError.
    • import braincell loads no braintools.visualize.morphology module (subprocess test).
  • Morphology.to_vis_data() → MorphologyData, also exposed as __morphology_data__.
    • Branch index is the position in Morphology.branches, so evaluated masks keep their branch indices.
    • Geometry is in µm; children keep MorphoBranch.children order; the root's parent_x/child_x are None.
    • It is cached on (revision): same object until an edit, a new one after.
  • NodeTree.to_topology_data() → TopologyGraph(level="node"), also exposed as __topology_data__.
  • Cell.topology_data(level="node", *, value=None, region=None, locset=None) → TopologyGraph.
    • It has the selection and field-resolution logic of the old plot_cell_topology, calling the existing field_resolution functions unchanged.
    • The errors are the same as before; the caller is named Cell.topology_data(level=...).
    • A (T, n) value array gives one frame per row.
    • Branch-level rejection of colour-map arguments now happens in bvm.plot_topology_graph (it checks graph.level == "branch").
  • vis2d/vis3d keep the same signatures. Their bodies do from braintools.visualize import morphology as bvm, and show=True still calls plt.show().
  • morph/__init___test.py: _UPWARD = ("braincell.io", "braincell.filter", "braintools.visualize.morphology") drops braincell.vis and adds braintools.visualize.morphology.
  • Tests:
    • Fixtures: morph/_testing.py gains make_root_split_tree and make_projected_node_tree, moved from the deleted vis fixtures.
    • Pixel baselines: braincell/vis_baseline_test.py and braincell/vis_baselines/ hold the VIS-2 baselines (the same 9 PNGs, tol=0, Linux only). They are now drawn through the adapters: morpho.vis2d, bvm.plot2d(morpho, values=...), bvm.plot_dendrogram/plot_sholl(morpho), bvm.plot_topology_graph(cell.topology_data("cv", region=...)) and bvm.plot_topology_graph(cell.node_tree). The two counter-examples still fail the comparison. The two SWC 3D tests (scene building, and PyVista off-screen) moved into the same file.
    • vis2d/vis3d tests: they patch braintools.visualize.morphology.plot2d/plot3d, assert that every argument is forwarded, and check show. No braintools test doubles are imported.
  • Packaging: pyproject.toml has vis = ["braintools[morphology]>=0.5"]; dependencies already had braintools>=0.5 from QUAD-2b. MANIFEST.in prunes braincell/vis_baselines.
  • Docs:
    • docs/apis/vis.rst is now a short page listing the adapters and wrappers.
    • Updated: README.md (features, example, extras table), docs/index.rst, docs/developer/{testing,troubleshooting,project_layout}.md, and docstrings in morph/morphology.py, morph/branch.py, morph/_testing.py, field_resolution.py, filter/_testing.py, io/_testing.py and quad/_testing.py.
  • Changelog: a Breaking Changes entry with both tables and the three new methods.
  • Out of scope: notebooks are VIS-4b. Until VIS-4b merges, their old braincell.vis calls do not run; the docs build does not execute notebooks.

How the 33 cell_topology tests map

The new tests are in _multi_compartment/cell_test.py (CellTopologyData*):

  • Guards (3 tests):
    • non-Cell argument: dropped (it is a method now);
    • unknown level → test_an_unknown_level_names_the_valid_ones;
    • node level needs init_state → test_node_level_requires_init_state.
    • Added: test_node_is_the_default_level.
  • CV level (10 tests):
    • the smoke test became test_graph_before_init (ids, edges, root);
    • fraction → test_region_gives_area_coverage_fractions (0.5833…);
    • any mode forwarding: dropped (coverage_mode stays a plot argument);
    • locset → test_locset_is_full_intensity;
    • V, raw point values, layout_id, value plus region, and more than one root CV each map 1:1.
    • Added: (T, n) frames, unknown layout_id → KeyError, wrong length → ValueError.
  • Branch level (7 tests):
    • smoke → test_graph_before_init;
    • length fraction 0.5 → test_region_gives_length_coverage_fractions;
    • all mode forwarding: dropped (a plot argument);
    • locset and value rejection map 1:1;
    • colour-map parameters → test_the_plot_rejects_colormap_arguments_for_a_branch_graph, now asserted on bvm.plot_topology_graph;
    • "several unsupported reported together" → test_both_unsupported_arguments_are_reported_together (value plus locset now hits the value-with-highlight guard first).
  • Node level (11 tests):
    • default level, region/locset → midpoint ids, value plus region, raw CV → point values, V (label "V"), ambiguous channel, layout_id, ion na.E: 1:1;
    • region forwarding is covered by the region test;
    • smoke → test_the_graph_draws (topology_data(value="V") and cell.node_tree both draw).
    • Added: test_graph_matches_the_node_tree, missing field → AttributeError.
  • Population (3 tests): 1:1; the refusal message now names Cell.topology_data(level='cv').
  • Pixel baseline (1 test): moved to vis_baseline_test.py.

Counter-example for the deferred import

Hoisting from braintools.visualize import morphology as bvm to the module level of morph/morphology.py fails UpwardImportsAreDeferredTest:

offenders = []
                    offenders.append(f"{name}.py: {target}")
            offenders,
E       AssertionError: Lists differ: ['morphology.py: braintools.visualize.morphology'] != []
E       
E       First list contains 1 additional elements.
E       First extra element 0:
E       'morphology.py: braintools.visualize.morphology'
E       
E       - ['morphology.py: braintools.visualize.morphology']
E       + [] : braincell.morph is imported before braincell.io / .filter exist, so a module-scope import of one of them makes `import braincell` raise ImportError -- often from a package you did not touch; and `import braincell` must not load braintools.visualize.morphology. Move the import into the method body.
braincell/morph/__init___test.py:152: AssertionError

Verification

  • pytest braincell (local, braintools at bdff413): 2741 passed, 12 skipped, 1 failed. The one failure is test_braincell_vis_no_longer_exists. It is an artefact of my local environment: braincell is installed editable from another checkout, and the editable finder still resolves braincell.vis there. With that finder removed, the import raises ModuleNotFoundError. CI installs this branch.
  • pytest braincell/vis_baseline_test.py: 13 passed (9 baselines at tol=0, 2 counter-examples, 2 SWC tests).
  • pre-commit run --all-files passes.
  • CI on head e7755b6: all 16 check-runs success or skipped (slow_tests skipped); ci-ok success, including docs, coverage, lint, build_package, the Linux/macOS/Windows matrix and the NEURON compare jobs.

…ology_data, Cell.topology_data

Plotting lives in braintools.visualize.morphology. vis2d/vis3d keep their
signatures and call bvm.plot2d/plot3d; the three adapters convert
braincell objects into its neutral data, and Morphology / NodeTree
implement the protocols, so every plot accepts them directly.

The cell_topology tests are rewritten against Cell.topology_data; the
pixel baselines and the two SWC 3D tests move to vis_baseline_test.py and
draw through the adapters with the same images and tol=0. Breaking, no
deprecation; changelog has the old-to-new tables.
@chaoming0625
chaoming0625 marked this pull request as ready for review November 8, 2026 19:47
@chaoming0625
chaoming0625 requested a review from TLDSZ as a code owner November 8, 2026 19:47
@chaoming0625
chaoming0625 merged commit 2c8dff0 into main Nov 8, 2026
16 checks passed
@chaoming0625
chaoming0625 deleted the vis-4a branch November 8, 2026 19:47
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