neu_mark.ops

The write operations, as functions the CLI is a thin shell over.

Each takes an already-opened source (from an open_*_source function in neu_mark.dvid), which carries the concrete uuid rather than a ref. The caller resolves the node once, so the tables, the provenance record and a destination name such as --dst {uuid:8} all describe the same node.

Each fetches for an explicit body list, writes tables, then writes provenance. There is no dask or manifest: 20,000 bodies take about 16 minutes in one process.

Attributes

Functions

annotation_source(dst, *[, connections, points, ...]) → dict[str, Any]

Write a precomputed LINE annotation source: one line per synaptic connection.

enrich_for_source(connections, points[, roi_spec])

(connections with each end's conf (and roi), build kwargs) for

fetch_bodies(source, dst[, bodies, fmt, everything]) → dict[str, Any]

Body annotations -> a bodies table, for a body list or the whole instance.

fetch_points(source, dst, bodies, *[, threads, fmt, ...]) → dict[str, Any]

Point annotations for bodies -> points + relationships tables.

segment_properties(bodies_source, dst, bodies, *[, ...]) → dict[str, Any]

Build a segment_properties source and, by default, link the volume to it.

write_selected_bodies(source, path, *[, min_synapses, ...]) → dict[str, Any]

Choose which bodies are worth fetching annotations for, and write the list.

Module Contents

neu_mark.ops.annotation_source(dst: str, *, connections=None, points=None, source: Mapping[str, Any] | None = None, bodies: Sequence[int] | None = None, voxel_size_xyz: Sequence[float] = (8.0, 8.0, 8.0), bounds: tuple[Sequence[float], Sequence[float]] | None = None, include_partial: bool = True, per_cell: int = 4000, roi_spec: str | None = None, listed: Sequence[int] | None = None, threads: int = _dvid.DEFAULT_THREADS) → dict[str, Any]

Write a precomputed LINE annotation source: one line per synaptic connection.

Pass connections and points from an earlier neu-mark points run, or a source and bodies to fetch now. bounds (the format’s required lower_bound/upper_bound) defaults to the data’s extent plus one voxel. roi_spec (a roi-layers spec) adds the roi and neuropil properties, by the spec’s ids, from the points’ roi column. listed (body ids) adds pre_listed / post_listed.

neu_mark.ops.enrich_for_source(connections, points, roi_spec: str | None = None)

(connections with each end's conf (and roi), build kwargs) for neu_mark.annsource.build(); the CLI’s dry run shares it.

neu_mark.ops.fetch_bodies(source: Mapping[str, Any], dst: str, bodies: Sequence[int] | None = None, *, fmt: str = 'parquet', everything: bool = False) → dict[str, Any]

Body annotations -> a bodies table, for a body list or the whole instance.

source comes from neu_mark.dvid.open_bodies_source(); it carries a concrete uuid.

everything=True reads every record in the instance instead (neu_mark.dvid.fetch_all_body_annotations()), a different population from a synapse-selected list. Written to its own destination, apart from the point tables.

neu_mark.ops.fetch_points(source: Mapping[str, Any], dst: str, bodies: Sequence[int] | None, *, threads: int = _dvid.DEFAULT_THREADS, fmt: str = 'parquet', drop_unmatched: bool = False, rois: Sequence[str] | None = None, on_roi_overlap: str = 'warn', roi_source: Mapping[str, Any] | None = None, write_connections: bool = False) → dict[str, Any]

Point annotations for bodies -> points + relationships tables.

source comes from neu_mark.dvid.open_points_source(); it carries a concrete uuid. bodies=None fetches the whole instance by region, with every element’s body from the labelmap (neu_mark.dvid.fetch_all_points()).

drop_unmatched removes relationships whose partner body was not resolved. It is off by default: an unfetched partner looks the same as a missing synapse, so dropping them at low coverage makes an incomplete connectome look complete. Check the match rate first.

roi_source is the node whose rois label the points (default source’s), for ROIs drawn on a later node than the points and body ids; the record names it.

neu_mark.ops.segment_properties(bodies_source: Mapping[str, Any], dst: str, bodies: Sequence[int], *, counts_source: Mapping[str, Any] | None = None, labelmap_source: Mapping[str, Any] | None = None, synapses: str | None = None, roi_spec: str | None = None, rules_path: str | None = None, label: str | None = None, drop: Sequence[str] = (), max_tags: float | None = None, link: bool = True, table: str | None = None, dry_run: bool = False) → dict[str, Any]

Build a segment_properties source and, by default, link the volume to it.

dst is the segmentation volume. The document goes to <dst>/segment_properties/info, and linking adds a "segment_properties" key to the volume’s own info, which is what makes neuroglancer show names and tags. link=False writes the document without touching the volume; dry_run builds and reports without writing anything but the table.

table is a path (.parquet, .csv or .feather) for a row per requested body (neu_mark.segprops.as_table()), written with its provenance, dry run or not.

rules_path loads a rules module (without one the document has labels and numbers only); label names the label column, overriding the module’s LABEL; drop names rules whose bodies are excluded rather than tagged. counts_source (a labelsz instance) adds pre/post/syn, and labelmap_source adds voxels.

synapses is a directory an earlier points --rois run wrote; it gives the rules a synapse_neuropils column (neu_mark.tables.body_neuropil_fractions()), and roi_spec (a roi-layers spec) a synapse_neuropils_top column grouping those by top-level neuropil.

neu_mark.ops.write_selected_bodies(source: Mapping[str, Any], path: str, *, min_synapses: int = 10, min_pre: int = 0, min_post: int = 0, limit: int | None = None) → dict[str, Any]

Choose which bodies are worth fetching annotations for, and write the list.

The list goes to path, in the format its extension names (.csv, .parquet or .feather), and its provenance record beside it as <name>.provenance.json.

Uses DVID’s ranked labelsz index, which takes seconds, and selects on synapses rather than size.

The default threshold is on the total, not on pre and post separately: sensory neurons may have no postsynapses, and a neuron leaving the volume may have no presynapses. min_pre / min_post add per-type minimums.

The provenance record names the node the list was computed from, since proofreading changes body ids.

neu_mark.ops.BODY_TABLES = ('bodies',)
neu_mark.ops.POINT_TABLES = ('points', 'relationships')
neu_mark.ops.logger