Segment Properties#

The segmentprops module provides tools for reading/writing neuroglancer precomputed segment properties.

ngsidekick.segmentprops.segment_properties_json(df, label_col=None, *, description_col=None, string_cols=[], number_cols=[], tag_cols=[], tag_prefix_mode='all', sort_tags=False, tag_descriptions={}, col_descriptions={}, drop_empty=True, output_path=None)[source]#

Given a DataFrame, construct the JSON representation for neuroglancer segment properties (i.e. segment properties ‘info’ file) according to the neuroglancer spec: google/neuroglancer

Parameters:
  • df (DataFrame) –

    DataFrame whose index contains segment IDs. For clarity of intent, we require that the Index be named ‘segment’ or ‘body’.

    All columns will be converted to segment properties. If a column is not explicitly listed in the following arguments, its property type will be inferred from the column dtype (or column name, in the case of label/description).

    The column dtypes can be string, category, or number, but 64-bit values will be downcast to 32-bit. Boolean columns are only valid as tags.

    The order of the input columns determines the order in which properties will be written. Neuroglancer preserves that order when displaying columns of numeric properties.

  • label_col (Optional[str]) – Name of the column to use for the ‘label’ property, which is shown in neuroglancer by default. If the column happens to be named ‘label’, then you need not provide it here. Or, if your dataframe contains only one column (and it’s non-numeric), we assume it is the label.

  • description_col (Optional[str]) – Name of the column to use as the ‘description’ property. If you name the column ‘description’, then you need not provide it here.

  • string_cols (List[str]) – Names of the columns to represent as ‘string’ properties. (Usually unnecessary. Non-numeric columns become string properties by default, unless they are named in tag_cols.)

  • number_cols (List[str]) – Names of the columns to represent as ‘number’ properties. (Usually unnecessary. Numeric columns become number properties by default.)

  • tag_cols (List[str]) –

    Names of the columns from which to generate the (combined) ‘tags’ property. If you want a column to be used for both tags _and_ a different property, be sure to list it explicitly in both arguments. For example:

    segment_properties_json(df, label_col='cell_class', tag_cols=['cell_class', ...])
    

    In addition to string/category inputs, columns with dtype bool can also be used for tags, in which case the False items are discarded and the True items are tagged with the column name.

  • tag_prefix_mode (Literal['all', 'disambiguate', None]) –

    Either 'all' or 'disambiguate' or None.

    • If 'all', then all tags will be prefixed with the name of their source column, (e.g. status:Anchor), other than those which came from boolean columns.

    • If 'disambiguate', then only tags which appear in multiple columns be prefixed with the name of their source column.

    • If None, then no disambiguation is performed.

  • sort_tags (bool) – If True, order tags alphabetically (after prefixes are applied, if any) so they are listed in sorted order in the neuroglancer UI. Otherwise, tags are listed according to the order given by ‘tag_cols’, with tags from earlier columns preceding tags from later columns, but tags within each column will be sorted with respect to each other. Note: For categorical input columns with ordered categories, the sort order is determined by the categorical’s intrinsic ordering, not alphanumeric sorting.

  • tag_descriptions (Dict[str, str]) – Optional. A dict of {tag: description} describing each tag value. Missing tags will be given a default description.

  • col_descriptions (Dict[str, str]) – Optional. A dict of {column: description} describing each property (input column) other than ‘tags’.

  • drop_empty (bool) – If any IDs in the input have no non-empty (null or “”) properties, then drop them from the output entirely so they don’t show up in neuroglancer’s default segment list.

  • output_path (Optional[str]) – If provided, export the JSON to a file.

Return type:

Dict[str, Union[str, Dict]]

Returns:

JSON data (as a dict) which should be written into an ‘info’ file to host neuroglancer precomputed segment properties.

Example

In [41]: print(df)
Out[41]:
            type              class       hemilineage  has_soma  PreSyn  PostSyn
segment
910719  IN13B018   intrinsic_neuron               13B      True     786     3164
160503    PFNm/p            central          DM3_CX_p      True      40      177
908822  IN03B079   intrinsic_neuron               03B      True     176      951
10552      DNp29  descending_neuron  putative_primary      True    1567     4559
43797     MeVP11  visual_projection               NaN      True     158      504
232845     R1-R6            sensory               NaN     False      25       18
547654     R1-R6            sensory               NaN     False      57       29
803197  IN07B019   intrinsic_neuron               TBD      True     796     3615
75597      KCg-m            central              MBp4      True     223      802
165485   vDeltaK            central               NaN      True      36      282

In [42]: info = segment_properties_json(df, 'type', tag_cols=['class', 'hemilineage', 'has_soma'])

In [43]: # Note: The output below has been indented by hand for clarity.
    ...: print(json.dumps(info))
{
    "@type": "neuroglancer_segment_properties",
    "inline": {
        "ids": ["910719", "160503", "908822", "10552", "43797", "232845", "547654", "803197", "75597", "165485"],
        "properties": [
            {
                "id": "type",
                "type": "label",
                "values": ["IN13B018", "PFNm/p", "IN03B079", "DNp29", "MeVP11", "R1-R6", "R1-R6", "IN07B019", "KCg-m", "vDeltaK"]
            },
            {
                "id": "PreSyn",
                "type": "number",
                "data_type": "int32",
                "values": [786, 40, 176, 1567, 158, 25, 57, 796, 223, 36]
            },
            {
                "id": "PostSyn",
                "type": "number",
                "data_type": "int32",
                "values": [3164, 177, 951, 4559, 504, 18, 29, 3615, 802, 282]
            },
            {
                "id": "tags",
                "type": "tags",
                "tags": [
                    "class:central", "class:descending_neuron", "class:intrinsic_neuron",
                    "class:sensory", "class:visual_projection",
                    "has_soma",
                    "hemilineage:03B", "hemilineage:13B", "hemilineage:DM3_CX_p", "hemilineage:MBp4",
                    "hemilineage:TBD", "hemilineage:putative_primary"
                ],
                "values": [
                    [2, 5, 7],
                    [0, 5, 8],
                    [2, 5, 6],
                    [1, 5, 11],
                    [4, 5],
                    [3],
                    [3],
                    [2, 5, 10],
                    [0, 5, 9],
                    [0, 5]
                ]
            }
        ]
    }
}
ngsidekick.segmentprops.segment_properties_to_dataframe(js, consolidate_tags_by_prefix=True, return_separate_tags=False)[source]#

Converts segment properties info JSON to DataFrame.

Parameters:
  • js (dict) – The JSON representation of the segment properties.

  • consolidate_tags_by_prefix (bool) – If True, consolidate boolean tag columns into Categorical columns according to their prefix, assuming the data was written using according to the naming conventions followed by segment_properties_json(…, tag_prefix_mode=”all”). Otherwise, a separate boolean column is created for each unique tag – potentially tons of columns (and RAM)!

  • return_separate_tags (bool) – If True, return two dataframes, for scalar columns and tag columns. Otherwise, combine them into a single dataframe.

Returns:

If return_separate_tags=True, return (scalar_df, tags_df). By default, concatenate them across columns into a single dataframe.

ngsidekick.segmentprops.select_segment_properties(info, subset, scalar_expressions={}, tag_expressions={})[source]#

Given the JSON data from a neuroglancer segment properties ‘info’ file, select a subset of the properties and/or tags and return the reduced JSON info.

You can also add new properties and/or tags by providing expressions (in pandas eval syntax) to be evaluated using the source data.

In addition to expressions, you can provide a template string to be evaluated with Python string formatting.

The variables available to the expressions are the columns extracted from the source data as produced via segment_properties_to_dataframe(). The tag list is parsed into separate columns according to their prefixes (assuming ‘:’ delimits the prefix).

The ‘label’ column is special: It is the one that will be displayed in the neuroglancer segment list.

Parameters:
  • info (dict) – The JSON data from a neuroglancer segment properties ‘info’ file.

  • subset (List[str]) – The subset of properties or tag categories to select. Special values: - ‘_all’: Select all properties and tags. - ‘_all_tags’: Select all tag categories. - ‘_default’: Select all properties and tags that have less than 1000 unique values. - ‘_default_tags’: Select all tag categories that have less than 1000 unique values.

  • scalar_expressions (Dict[str, str]) – Expressions to be evaluated using the source data to compute new properties.

  • tag_expressions (Dict[str, str]) – Expressions to be evaluated using the source data to compute new tags.

Return type:

dict

Returns:

The reduced/enhanced JSON data from a neuroglancer segment properties ‘info’ file.

Note

For the purpose of expression evaluation, we treat ‘~’ and missing values (untagged) as “”.

Examples:

new_info = select_segment_properties(info, subset=['superclass', 'type'])
new_info = select_segment_properties(
    info,
    scalar_expressions={
        'size': 'length * width * height',
        'label': "{type} ({superclass})"
    },
)
new_info = select_segment_properties(
    info,
    tag_expressions={
        'is_left_hemilineage_01': 'hemilineage in ("01A", "01B") and soma_side == "L"'
    }
)

See also

The ngsidekick-server project wraps this function in a web service to enable dynamic segment property selection directly in neuroglancer (via user-provided source URLs).