neu_mark.segprops¶
Building a neuroglancer segment_properties source from the body annotations.
The format is one inline JSON document, written through neu_vol.location. What the
spec allows shapes it:
At most one
label, onedescriptionand onetagsproperty, so every facet pools into the onetagsproperty asprefix:value(side:L,type:Mi1).A segment’s
tagsvalues are indices into thetagsarray, in increasing order.A tag may contain no spaces (they are hyphenated here) and no leading
#. Matching is case-insensitive, so values differing only in case show as one chip in the viewer (case_collisions()reports them); case is preserved.
Facets come from a dataset’s rules module (neu_mark.rules.Rule); nothing is
built in, so with no rules the document carries labels and numbers only. The label is the
rules’ label column (a module’s LABEL, or label=); a reserved label rule
replaces it, and with neither, segments are known by id.
The document is inline, so every viewer downloads all of it: max_tags and max_facets
refuse a vocabulary large enough to make the layer unusable (resolve_tag_limit()).
Attributes¶
Functions¶
|
One row per body: what the document says about it, then the record it came from. |
|
The |
|
|
|
Refuse a vocabulary big enough to make the layer unusable. Returns the limit applied. |
|
A sort key for tags: facets in the order their rules are declared, a prefix no rule |
|
Every facet |
|
The report as lines, for a CLI to print. |
|
Sort key for tags: case-insensitive, with runs of digits compared as numbers, and |
|
A tag as the format requires: spaces hyphenated, no leading |
|
|
|
One rule's value as a tag: |
|
Write the document to |
Module Contents¶
- neu_mark.segprops.as_table(bodies, outcomes, ruleset, *, counts=None, sizes=None, requested: Sequence[int] | None = None, described: bool = False)¶
One row per body: what the document says about it, then the record it came from.
Columns:
body,label,description(when a rule writes one),excluded(the drop rule’s reason,"no record", or null for a segment in the document),tags(the full list),tag:<prefix>per facet in rule order (a list for amultirule, else a value or null),flag:<tag>per bare tag, a column pertag=Falserule named after it, the numbers, then every record column. A record column whose name is taken getsrecord:in front, and dict values (the synapse neuropil shares) are JSON text.
- neu_mark.segprops.build(bodies, *, rules=None, label: str | None = None, drop: Sequence[str] = (), counts=None, sizes=None, max_tags: float = DEFAULT_MAX_TAGS, max_facets: int = MAX_FACETS, table: bool = False, requested: Sequence[int] | None = None) dict[str, Any]¶
The
segment_propertiesinfo document, plus a report of what went into it.bodiesis a frame withbodyand whatever property fields exist;countsan optional frame withbody/pre/post/syn;sizesan optional{body: voxels}.rulesis aRuleSet(or anything it accepts); without it the document has labels and numbers only.labelnames the label column, overriding the rules’ own;dropnames rules whose bodies are excluded rather than tagged. Evaluation order: drop rules, then tag rules, then the reservedlabel/descriptionrules, then any othertag=Falserule (reported, and a column of the table, but not in the document).Returns
{"info": …, "report": …}. Check the report’s coverage: a facet that fired on 2% of bodies looks the same in the viewer as one the data does not have.table=Trueadds"table", a DataFrame with a row per body (as_table());requestednames bodies to list there asexcluded="no record"whenbodieshas no row for them.
- neu_mark.segprops.case_collisions(vocabulary: Iterable[str]) dict[str, list[str]]¶
{lowercased: [tags]}for tags that differ only in case.The viewer matches tags case-insensitively, so
type:Tm2andtype:TM2show as one chip while remaining two values in the table.
- neu_mark.segprops.check_vocabulary(vocabulary: Sequence[str], distinct: Mapping[str, set], *, segments: int, max_tags: float = DEFAULT_MAX_TAGS, max_facets: int = MAX_FACETS, facets: Sequence[str] | None = None) int¶
Refuse a vocabulary big enough to make the layer unusable. Returns the limit applied.
Two checks: too many tags (typically a rule echoing the whole instance string) and too many facets (a rule minting a separate facet per value). See
resolve_tag_limit().
- neu_mark.segprops.facet_order(rules: Iterable[Any]) Callable[[str], tuple]¶
A sort key for tags: facets in the order their rules are declared, a prefix no rule declares after those, bare flags last, and
natural_key()within each.
- neu_mark.segprops.facets(record: Mapping[str, Any], ruleset) dict[str, list[str]]¶
Every facet
rulesetgives one body, as{rule name: [tags]}, already tag-normalized. Drop rules are not consulted; exclusion happens inbuild().
- neu_mark.segprops.format_report(report: Mapping[str, Any]) list[str]¶
The report as lines, for a CLI to print.
- neu_mark.segprops.natural_key(tag: str) tuple¶
Sort key for tags: case-insensitive, with runs of digits compared as numbers, and the original text last so the order is total.
- neu_mark.segprops.normalize_tag(value: Any) str | None¶
A tag as the format requires: spaces hyphenated, no leading
#, case preserved. Missing values (includingpd.NA) giveNone, vianeu_mark.explore.normalize().
- neu_mark.segprops.resolve_tag_limit(max_tags: float, segments: int) tuple[int, str]¶
max_tagsas a concrete tag ceiling:(limit, how).Below 1 is a fraction of the segment count, 1 or above an absolute count, decided by value (
1and1.0are the same to TOML and JSON).MIN_TAG_ALLOWANCEfloors a fraction only;max_tags=25means 25.
- neu_mark.segprops.tag_for(rule, value: Any) str | None¶
One rule’s value as a tag:
prefix:value, or a bare tag where prefix is empty.A trailing colon on the prefix is tolerated (
prefix="col:"givescol:C2).
- neu_mark.segprops.write(dst: str, info: Mapping[str, Any], *, subdir: str = SUBDIR) str¶
Write the document to
<dst>/<subdir>/infothrough the kvstore.
- neu_mark.segprops.AT_TYPE = 'neuroglancer_segment_properties'¶
- neu_mark.segprops.DEFAULT_MAX_TAGS = 0.1¶
- neu_mark.segprops.MAX_FACETS = 24¶
- neu_mark.segprops.MIN_TAG_ALLOWANCE = 100¶
- neu_mark.segprops.NO_RECORD = 'no record'¶
- neu_mark.segprops.SEPARATOR = ':'¶
- neu_mark.segprops.SUBDIR = 'segment_properties'¶
- neu_mark.segprops.logger¶