Namespaces¶
Every dataset exposes its functionality through namespaces. Which ones exist depends on
what the dataset can actually do — ds.segmentation is simply absent on neuPrint,
and hasattr(ds, "segmentation") is False. See Capabilities.
Every method below takes the same neuron query (see Selecting neurons) and
a version= override.
Annotations¶
Annotations
¶
Bases: _Namespace
Neuron metadata: types, sides, classes, somas.
Source code in connecto/core/namespaces.py
get
¶
get(x=None, *, fields: dict | None = None, source: str | None = None, raw: bool = False, version=None, units: str = 'nm', verbose: bool = True, **filters) -> DataFrame
Annotations, with canonical columns added and every raw column kept.
Canonical: id, type, side, class, nt, status, soma_x/y/z. type is
coalesced from spec.fields["type"] in priority order; side is
mapped to left/right/center. Pass raw=True for the
untouched backend frame.
verbose (default True) prints one line saying which source is being
read and whether it came from the remote server, the local cache, or a
cache refresh. Set it False to silence that.
Source code in connecto/core/namespaces.py
search
¶
Rows whose type, class or instance matches term.
Source code in connecto/core/namespaces.py
ids
¶
Every annotated neuron in the dataset.
Connectivity¶
Connectivity
¶
Bases: _Namespace
Edges, adjacency and synapses.
edges
¶
edges(x, *, upstream: bool = True, downstream: bool = True, by_roi: bool = False, rois=UNSET, min_weight: int = 1, version=None, cache: bool = False, extra: bool = False, autapses: bool = False) -> DataFrame
Edges to/from the given neurons as pre, post, weight.
A closed schema: identical columns and dtypes on every backend, so
bodyId_pre and pre_pt_root_id both come back as pre, and
FlyWire's edge view does not smuggle in seventeen extra columns that
hemibrain has never heard of. extra=True keeps whatever else the
backend happened to return.
autapses (pre == post) default to off. They are nearly always
segmentation errors, neuPrint omits them entirely, and caveclient's own
synapse_query drops them by default - so leaving them in would make the
same neuron have different connectivity depending on which backend you
asked. Pass autapses=True if you want them; you will get them from
every backend that has them.
Source code in connecto/core/namespaces.py
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | |
adjacency
¶
Weight matrix, rows = sources, columns = targets.
Source code in connecto/core/namespaces.py
synapses
¶
synapses(x, *, pre: bool = True, post: bool = True, min_score=UNSET, transmitters=UNSET, rois=UNSET, version=None, units: str = 'nm') -> DataFrame
Individual synapses, positions in nanometres.
min_score and transmitters raise on datasets that don't have them,
rather than being quietly ignored.
Source code in connecto/core/namespaces.py
synapse_counts
¶
Pre- and post-synapse counts per neuron.
Source code in connecto/core/namespaces.py
transmitters
¶
Predicted transmitter per neuron, from its presynapses.
Source code in connecto/core/namespaces.py
Skeletons¶
Skeletons
¶
Bases: _Namespace
Skeletons, as navis TreeNeurons.
get
¶
Skeletons for the given neurons -> navis.NeuronList.
Source code in connecto/core/namespaces.py
dotprops
¶
Dotprops, for NBLAST. Built from the skeleton.
units defaults to "nm", because everything connecto returns is in
nanometres. NBLAST is calibrated in microns. Score it on nanometre dotprops
and every pair collapses to the floor - two copies of the same cell type come
back at -0.88 instead of +0.70 - which reads as "nothing is similar" rather than
as an error. navis notices and logs a warning, but a log line is easy to miss.
So when the next step is NBLAST, ask for microns::
dp = ds.skeletons.dotprops(x, units="um")
navis.nblast(dp, dp)
If the dataset has an L2 cache, :meth:~connecto.backends.cave.l2.L2.dotprops
gets there without building a skeleton first, and is much cheaper.
Source code in connecto/core/namespaces.py
Meshes¶
Meshes
¶
Voxels¶
Sparse volumes: every voxel belonging to a neuron, as an (N, 3) array.
The one namespace whose cost varies by three orders of magnitude between datasets, so
it is also the one that talks about cost. hemibrain, maleCNS, MANC and fish2 are backed
by DVID, which keeps a live per-body index and answers in a single request; aedes has a
lookup service that does the same. FlyWire, BANC, FANC and MICrONS have a chunkedgraph,
which keeps no such index — so the same question means reading dense blocks and
masking them, touching thousands of voxels for every one it keeps. estimate() tells
you which you are in for before you commit.
scale= never defaults to 0. A hemibrain neuron at scale 0 is 1.17 billion voxels; on
the CAVE route the equivalent request is refused outright rather than left to look like
a hang.
Voxels
¶
Bases: _Namespace
Sparse volumes: every voxel belonging to a neuron.
The one namespace whose cost varies by three orders of magnitude between
datasets, so it is also the one that talks about cost. DVID and the aedes
service keep a per-body index and answer in a single request; a chunkedgraph
keeps none, and the same question there means reading dense blocks and masking
them. estimate() says which you are in for before you commit to it.
get
¶
get(x, *, scale: int | None = None, output: str = 'navis', units: str = 'voxel', version=None, progress: bool = True, verbose: bool = False, **opts)
Sparse volumes for the given neurons.
Parameters¶
scale : int, optional
Pyramid level; each level halves resolution. Defaults to
something that returns a usable neuron without reading the whole
brain - not 0, which for a hemibrain neuron is 1.17 billion
voxels. ds.voxels.scales() lists what is available.
output : "navis" | "raw" | "rle"
navis gives VoxelNeurons; raw a dict of (N, 3)
arrays; rle a dict of (M, 4) runs, which is ~20x smaller
and is what the wire already carries.
units : "voxel" | "nm"
Coordinate space of raw output. navis output is always
voxels plus the units metadata navis expects, so it plots and
measures in nm regardless.
Source code in connecto/core/namespaces.py
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 | |
estimate
¶
What get() would cost, without doing it.
Meaningful mainly on the CAVE route, where the answer is a dense read whose size the caller controls. The indexed routes just say so.
Source code in connecto/core/namespaces.py
scales
¶
Which scales this dataset serves.
That a scale is available says nothing about whether it is affordable -
every CAVE dataset lists scale 0 and none of them can deliver a whole neuron
at it. Use :meth:estimate for the cost.
Source code in connecto/core/namespaces.py
ROIs¶
ROIs
¶
Bases: _Namespace
Neuropils / brain regions.
Somas¶
Somas
¶
Visualisation¶
See the Neuroglancer guide for colouring, groups and layers.
Viz
¶
Bases: _Namespace
Neuroglancer.
scene() hands back the raw dict; neuroglancer_url() hands back a link. Both
take the same arguments - see :func:connecto.viz.construct_scene - so::
ds.viz.neuroglancer_url(ids, color_by="type")
is a link with every cell type in its own colour, and::
scene = ds.viz.scene(ids)
scene = add_skeleton_layer(scene, ds.skeletons.get(ids))
encode_url(scene, viewer="https://ngl.flywire.ai")
is the escape hatch when the canned scene is not enough.
construct_scene
¶
construct_scene(ds, ids=None, *, seg_colors=None, seg_groups=None, invis_segs=None, color_by=None, group_by=None, palette=None, position=None, units: str = 'nm', layout: str = 'xy-3d', image: bool = True, layers=None, viewer: str | None = None, dialect: str | None = None, version=None) -> dict
Build a neuroglancer scene for this dataset.
Parameters¶
ids : IDs to select. Order is meaningful: seg_colors and
seg_groups, when given as plain lists, zip onto it.
seg_colors : One colour for all of them, a list of colours (one per ID), or a
{id: colour} dict. Anything matplotlib understands is a colour:
"red", "#ff0000", (1, 0, 0).
color_by : Colour by a label instead: an annotation field ("type",
"class", ...) or an array of labels aligned to ids. Each
distinct label gets a colour from palette. Mutually exclusive
with seg_colors.
seg_groups : Split the IDs across separate layers, so they can be toggled
independently. A list of group names (one per ID), a
{id: group} dict, or a {group: [ids]} dict.
group_by : As color_by, but for groups: an annotation field or an array.
invis_segs : Selected but not rendered - loaded and listed in the layer with
their visibility switched off, ready to be toggled on in the viewer.
position : Where to point the camera, in nanometres (see units).
units : "nm" (the default, and what every other connecto method returns)
or "voxel" for coordinates already in viewer space.
image : Whether to include the EM image layer. Without it the segments float
in a void, which is rarely what anyone wants.
layers : Extra layer dicts to append verbatim.
Returns¶
scene : dict
Source code in connecto/viz/neuroglancer.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
add_annotation_layer
¶
add_annotation_layer(scene: dict, coords, *, name: str | None = None, color=None, units: str = 'nm') -> dict
Add points, lines or ellipsoids as a new annotation layer.
The shape of coords picks the annotation type::
(N, 3) points x/y/z
(N, 2, 3) line segments start x/y/z, end x/y/z
(N, 4) ellipsoids x/y/z + radius
Coordinates are nanometres by default - so a synapse table from
ds.connectivity.synapses() goes straight in - and are converted to the scene's
own voxel size on the way. The scene is not modified; a new one comes back.
Source code in connecto/viz/neuroglancer.py
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | |
add_skeleton_layer
¶
Add skeletons as line annotations - one layer per neuron.
Takes navis TreeNeuron s (a NeuronList is fine) and draws every
parent-child edge as a line. Useful for showing a skeleton next to the
segmentation it came from, or for putting a neuron from somewhere else - a CATMAID
tracing, a transformed neuron - into the scene.
Units come off the neuron: navis carries them, so a micron-scale neuron (from
ds.l2.dotprops(units="um"), say) is scaled correctly rather than landing a
thousand times too close to the origin.
Source code in connecto/viz/neuroglancer.py
build_url
¶
build_url(ds, ids=None, *, shorten: bool = False, viewer: str | None = None, dialect: str | None = None, **kwargs) -> str
A neuroglancer URL showing the given neurons. See :func:construct_scene.
Source code in connecto/viz/neuroglancer.py
encode_url
¶
Source code in connecto/viz/neuroglancer.py
decode_url
¶
Segmentation¶
Present wherever the dataset declares Cap.SEGMENTATION — which includes neuPrint,
whose flat precomputed:// volumes read as well as CAVE's graphene ones. The methods
that need a chunkedgraph (supervoxels, update_ids, root-ID history) additionally
require Cap.CHUNKEDGRAPH and raise on a flat volume rather than inventing an answer.
Coordinates are nanometres, like everywhere else in connecto; pass units="voxel" if
yours are not.
Segmentation
¶
Bases: _Namespace
Query the segmentation volume, and the chunkedgraph where there is one.
locs_to_segments
¶
The segment ID at each xyz location. locs is Nx3, in nanometres.
On a chunkedgraph dataset this goes via supervoxels, so it honours
version= and answers as of that materialization. On a flat volume there
is only one answer - the volume is the version - and version= is
therefore refused rather than ignored.
Source code in connecto/core/segmentation.py
neuron_to_segments
¶
Which segments a neuron's nodes fall into. Useful for spotting merges.
Source code in connecto/core/segmentation.py
get_voxels
¶
Every voxel belonging to one segment, as raw (N, 3) voxel indices.
Prefer :meth:connecto.core.namespaces.Voxels.get (ds.voxels.get) unless
you specifically want this. That one takes any neuron query rather than a
single ID, returns navis.VoxelNeurons that carry their own nm-per-voxel,
can hand back the compact run-length form, and - where the dataset has an
index behind it - is a single request instead of a dense read.
This stays because it is a different, simpler thing: one segment, one mesh-bounded cutout, no chunkedgraph needed. It is also the only route for a segment that is not a neuron the graph knows about.
Source code in connecto/core/segmentation.py
get_segmentation_cutout
¶
Raw segmentation in a bounding box. bbox is [[x0,y0,z0],[x1,y1,z1]].
Source code in connecto/core/segmentation.py
locs_to_supervoxels
¶
The supervoxel ID at each xyz location.
Reads the graph source, never the spec's display volume. FlyWire's spec
points at the flat v783 bucket - excellent for meshes and for neuroglancer,
useless here: a flat volume hands back root IDs, and a root ID passed off as
a supervoxel is a lie get_roots will happily accept, because it is
idempotent on roots. It would be right at v783 and quietly wrong everywhere
else.
Source code in connecto/core/segmentation.py
update_ids
¶
Map outdated root IDs onto their current equivalents.
Returns old_id, new_id, confidence, changed - confidence being the
fraction of the old neuron that ended up in the new one, so you can see
when an ID has been split rather than merely renamed.
Source code in connecto/core/segmentation.py
find_common_time
¶
The latest timestamp at which all the given root IDs co-existed.
Source code in connecto/core/segmentation.py
Proofreading (CAVE only)¶
Proofreading
¶
Bases: _Namespace
is_proofread
¶
Boolean mask: has each neuron been marked as proofread?
Source code in connecto/backends/cave/proofreading.py
edit_history
¶
Every edit that touched these neurons.
Source code in connecto/backends/cave/proofreading.py
lineage_graph
¶
The merge/split tree that produced this neuron.
L2 cache (CAVE only, and not every datastack)¶
Present only where the dataset declares Cap.L2CACHE. Cheap skeletons and dotprops
straight from the chunkedgraph's level-2 summaries — see
Morphology.
L2
¶
Bases: _Namespace
Level-2 chunk data: cheap skeletons and dotprops.
info
¶
Per-chunk table: position (nm), volume, surface area.
One row per level-2 chunk, with the id of the neuron it belongs to. This is
the raw material the other methods are built from - useful on its own for cheap
volume/area estimates without fetching a mesh.
Source code in connecto/backends/cave/l2.py
graph
¶
The level-2 chunk graph, as networkx.Graph (one per neuron).
Returns a dict keyed by root ID. This is the connectivity of the chunks
themselves - the thing :meth:skeleton walks to find parents.
Source code in connecto/backends/cave/l2.py
skeleton
¶
Skeletons built from the L2 chunk graph -> navis.NeuronList.
Positions are nanometres. Nodes are chunk representative coordinates, and two consequences follow that you have to know about:
Do not measure cable length on these. The path hops from one chunk's
representative point to the next, which zig-zags rather than following the
neurite, so it over-estimates - on FlyWire DA1_lPNs, consistently by about
2x (1.9-2.2x against the same neurons from the skeleton service). Use
ds.skeletons.get() if the number matters.
Radii are estimates. They come from the chunk's volume-to-surface ratio, not from a measurement of the neurite.
What the L2 skeleton is good for is topology and shape at low cost - and, via
:meth:dotprops, NBLAST.
Source code in connecto/backends/cave/l2.py
dotprops
¶
Dotprops straight from the L2 cache -> navis.NeuronList.
No skeletonisation: rep_coord_nm is the point and pca_0 the vector, both
computed server-side.
Chunks with a degenerate (all-zero) principal axis are dropped - they are too blobby to have a direction, and passing a zero vector to NBLAST would have it silently score them as if they did.
units defaults to "nm", like everything else connecto returns. NBLAST
is calibrated in microns: hand it nanometre dotprops and every score collapses
to the floor, which looks like "nothing matches" rather than like an error. So
for NBLAST, ask for microns::
dp = ds.l2.dotprops(x, units="um")
navis.nblast(dp, dp)