Skip to content

Summary

py3r.behaviour.summary.summary.Summary

Summary(trackingfeatures: Features)

stores and computes summary statistics from features objects

features instance-attribute

features = trackingfeatures

data instance-attribute

data = dict()

meta instance-attribute

meta = dict()

handle instance-attribute

handle = handle

tags instance-attribute

tags = tags

save

save(
    dirpath: str,
    *,
    data_format: str = "parquet",
    overwrite: bool = False,
) -> None

Save this Summary (including nested Features/Tracking) to a directory.

Examples
>>> import tempfile, os, pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> # add a boolean feature for summary methods to use
>>> mask = pd.Series([True, False] * (len(t.data)//2 + 1))[:len(t.data)]
>>> mask.index = t.data.index
>>> f.store(mask, 'mask', meta={})
>>> s = Summary(f)
>>> with tempfile.TemporaryDirectory() as d:
...     s.save(d, data_format='csv', overwrite=True)
...     os.path.exists(os.path.join(d, 'manifest.json'))
True

load classmethod

load(dirpath: str) -> Summary

Load a Summary previously saved with save().

Examples
>>> import tempfile, pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> f.store(pd.Series(range(len(t.data)), index=t.data.index), 'counter', meta={})
>>> s = Summary(f)
>>> with tempfile.TemporaryDirectory() as d:
...     s.save(d, data_format='csv', overwrite=True)
...     s2 = Summary.load(d)
>>> isinstance(s2, Summary) and 'counter' in s2.features.data.columns
True

count_onset

count_onset(column: str) -> SummaryResult

Count times boolean series changes False->True, ignoring nans. If first non-nan value is True, that counts as an onset.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> mask = pd.Series([False, True, False, True, False][:len(t.data)], index=t.data.index)
>>> f.store(mask, 'mask', meta={})
>>> s = Summary(f)
>>> res = s.count_onset('mask')
>>> bool(res.value == 2)
True

calculate_latency_nth_onset

calculate_latency_nth_onset(
    column: str,
    target_value: str | float | int = None,
    threshold_op: Literal[
        ">", ">=", "<=", "<", "==", "!="
    ] = "==",
    nth_event: int = 1,
    integration_window=1,
)

Compute the latency (in seconds) of the N-th onset event in a feature column.

This method extracts a column from features.data, passes it on to latencies_from_series, and returns the index of the N-th False → True transition. If fewer than nth_event events are present, NaN is returned.

The column may already be boolean or may be thresholded against target_value using threshold_op. Optional temporal integration (boolean smoothing) can be applied prior to onset detection.

Parameters

column : str Name of the column in features.data to analyze. target_value : str | float | int | None, optional Value to compare against for non-boolean columns. Required unless the column is already boolean. threshold_op : {">", ">=","<=", "<", "==", "!="}, default "==" Comparison operator used to generate the boolean condition. Only "==" and "!=" are valid for string-valued columns. nth_event : int, default 1 Index of the onset event to return (1 = first, note). integration_window : int, default 1 = no smoothing Window size for boolean integration/smoothing prior to latency extraction.

Returns

SummaryResult A SummaryResult whose value is the index of the selected onset event, or NaN if the event does not exist.

Raises

ValueError If column is not found in features.data. ValueError Propagated from latencies_from_series if thresholding arguments are invalid.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=1)
>>> f = Features(t)
>>> mask = pd.Series([False, True, False, True, False], dtype = bool)
>>> f.store(mask, 'mask', meta={})
>>> s = Summary(f)
>>> res = s.calculate_latency_nth_onset('mask')
>>> res.value
1.0

>>> print(res._func_name)
latency_mask_==_True_int1_n1

Selecting a later onset:

>>> res = s.calculate_latency_nth_onset('mask', nth_event=2)
>>> res.value
3.0

Selecting a later onset (i.e non existing) creates nan:

>>> res = s.calculate_latency_nth_onset('mask', nth_event=3)
>>> res.value
nan

Using thresholding on numeric data:

>>> speed = pd.Series([0.1, 0.2, 0.8, 0.9, 0.1], dtype = float)
>>> f.store(speed, 'speed', meta={})
>>> res = s.calculate_latency_nth_onset('speed', target_value=0.5, threshold_op='>')
>>> res.value
2.0

Using thresholding on int data:

>>> id = pd.Series([2, 1, 3, 2, 1], dtype = int)
>>> f.store(id, 'id', meta={})
>>> res = s.calculate_latency_nth_onset('id', target_value=2, threshold_op='<')
>>> res.value
1.0

Using thresholding on string value:

>>> cluster = pd.Series(['A', 'A', 'B', 'A', 'A'], dtype = str)
>>> f.store(cluster, 'cluster', meta={})
>>> res = s.calculate_latency_nth_onset('cluster', target_value='B')
>>> res.value
2.0

time_true

time_true(column: str) -> SummaryResult

returns time in seconds that condition in the given column is true

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> mask = pd.Series([True] * len(t.data), index=t.data.index)
>>> f.store(mask, 'mask', meta={})
>>> s = Summary(f)
>>> res = s.time_true('mask')
>>> bool(res.value > 0)
True

time_false

time_false(column: str) -> SummaryResult

returns time in seconds that condition in the given column is false

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> mask = pd.Series([False] * len(t.data), index=t.data.index)
>>> f.store(mask, 'mask', meta={})
>>> s = Summary(f)
>>> res = s.time_false('mask')
>>> bool(res.value > 0)
True

total_distance

total_distance(
    point: str,
    startframe: int | None = None,
    endframe: int | None = None,
) -> SummaryResult

returns total distance traveled by a tracked point between optional start and end frames Examples


>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = Summary(f)
>>> res = s.total_distance('p1', 0, 4)
>>> isinstance(res.value, (int, float))
True

by_state

by_state(
    column: str,
    all_states: list | None = None,
    max_states: int = 100,
) -> _ByStateDispatcher

Return a dynamic state-grouped dispatcher for Summary methods.

Parameters

column: Name of the state column in features.data used to create per-state subsets. all_states: Optional explicit state list to define which states are evaluated and in what output order. This list is inclusive: states not present in the data are still evaluated on empty subsets and included in the output. max_states: Safety guard limiting the number of evaluated states. Raises ValueError if the effective number of states exceeds this value.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> idx = t.data.index
>>> f.store(pd.Series(['A', 'A', 'B', 'B', 'A'][:len(idx)], index=idx), 'state', meta={})
>>> f.store(pd.Series([1, 2, 3, 4, 5][:len(idx)], index=idx), 'x', meta={})
>>> s = Summary(f)
>>> res = s.by_state('state', all_states=['B', 'C', 'A']).sum_column('x')
>>> res.value.index.tolist()
['B', 'C', 'A']
>>> int(res.value['C'])  # inclusive all_states: state absent in data still included
0
>>> int(res.value['B'])
7

sum_column

sum_column(column: str) -> SummaryResult

Sum all non-NaN values in a features.data column and return as a SummaryResult.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = pd.Series([1, 2, 3, 4, 5][:len(t.data)], index=t.data.index)
>>> f.store(s, 'x', meta={})
>>> summ = Summary(f)
>>> res = summ.sum_column('x')
>>> bool(res.value == 15)
True

mean_column

mean_column(column: str) -> SummaryResult

Mean of all non-NaN values in a features.data column and return as a SummaryResult.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = pd.Series([1, 2, 3, 4, 5][:len(t.data)], index=t.data.index)
>>> f.store(s, 'x', meta={})
>>> summ = Summary(f)
>>> res = summ.mean_column('x')
>>> bool(res.value == 3)
True

median_column

median_column(column: str) -> SummaryResult

Median of all non-NaN values in a features.data column and return as a SummaryResult.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = pd.Series([1, 2, 3, 4, 5][:len(t.data)], index=t.data.index)
>>> f.store(s, 'x', meta={})
>>> summ = Summary(f)
>>> res = summ.median_column('x')
>>> bool(res.value == 3)
True

max_column

max_column(column: str) -> SummaryResult

Max of all non-NaN values in a features.data column and return as a SummaryResult.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = pd.Series([1, 2, 3, 4, 5][:len(t.data)], index=t.data.index)
>>> f.store(s, 'x', meta={})
>>> summ = Summary(f)
>>> res = summ.max_column('x')
>>> bool(res.value == 5)
True

min_column

min_column(column: str) -> SummaryResult

Min of all non-NaN values in a features.data column and return as a SummaryResult.

Examples
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = pd.Series([1, 2, 3, 4, 5][:len(t.data)], index=t.data.index)
>>> f.store(s, 'x', meta={})
>>> summ = Summary(f)
>>> res = summ.min_column('x')
>>> bool(res.value == 1)
True

store

store(
    summarystat: Any,
    name: str,
    overwrite: bool = False,
    meta: Any = None,
) -> None

stores a summary statistic and optional metadata, with optional overwrite protection Examples


>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = Summary(f)
>>> s.store(123, 'num_events', meta={'unit':'count'})
>>> s.data['num_events'] == 123 and s.meta['num_events']['unit'] == 'count'
True

copy

copy() -> Summary

Creates an independent copy of this Summary object.

The returned object shares no mutable state with the original: Features is copied via Features.copy(), and data/meta/tags via deepcopy.

Examples
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = Summary(f)
>>> s_copy = s.copy()
>>> s_copy.handle == s.handle
True
>>> s_copy.features.tracking.data is not s.features.tracking.data
True

make_bin

make_bin(startframe: int, endframe: int) -> Summary

creates a copy of the Summary object with the dataframes restricted from startframe to endframe, inclusive Examples


>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = Summary(f)
>>> b = s.make_bin(0, 2)
>>> isinstance(b, Summary)
True

make_bins

make_bins(numbins: int) -> list[Summary]

creates a list of Summary objects, with frames restricted into numbins even intervals. start/endpoints are duplicated between intervals to ensure no loss in e.g. distance calculations Examples


>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> s = Summary(f)
>>> bins = s.make_bins(3)
>>> len(bins) == 3 and all(isinstance(b, Summary) for b in bins)
True

transition_matrix

transition_matrix(
    column: str, all_states=None
) -> SummaryResult

Returns a transition matrix for a given column in self.features.data, with rows and columns as the unique values of the column or as specified by all_states. Examples


>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> states = pd.Series(['A','A','B','B','A'][:len(t.data)], index=t.data.index)
>>> f.store(states, 'state', meta={})
>>> s = Summary(f)
>>> res = s.transition_matrix('state')
>>> isinstance(res.value, pd.DataFrame)
True

count_state_onsets

count_state_onsets(
    column: str, all_states: list | None = None
) -> SummaryResult

counts the number of times a state is entered in a given column

Parameters

column: Name of the state column in features.data. all_states: Optional explicit state ordering to control index presence/order in the returned Series. When provided, the output is reindexed to all_states and missing states are filled with 0. Examples


>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> states = pd.Series(['A','A','B','B','A'][:len(t.data)], index=t.data.index)
>>> f.store(states, 'state', meta={})
>>> s = Summary(f)
>>> res = s.count_state_onsets('state', all_states=['B', 'C', 'A'])
>>> res.value.index.tolist()
['B', 'C', 'A']
>>> res.value.tolist()
[1, 0, 2]
>>> res._params['all_states']
['B', 'C', 'A']
>>> res = s.count_state_onsets('state', all_states=['A'])
>>> res.value.tolist()
[2]
>>> res.value.index.tolist()
['A']
>>> hasattr(res, 'value')
True

time_in_state

time_in_state(
    column: str, all_states: list | None = None
) -> SummaryResult

returns the time spent in each state in a given column

Parameters

column: Name of the state column in features.data. all_states: Optional explicit state ordering to control index presence/order in the returned Series. When provided, the output is reindexed to all_states and missing states are filled with 0. Examples


>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='ex', fps=30)
>>> f = Features(t)
>>> states = pd.Series(['A','A','B','B','A'][:len(t.data)], index=t.data.index)
>>> f.store(states, 'state', meta={})
>>> s = Summary(f)
>>> res = s.time_in_state('state', all_states=['B', 'C', 'A'])
>>> res.value.index.tolist()
['B', 'C', 'A']
>>> [round(v, 4) for v in res.value.tolist()]
[0.0667, 0.0, 0.1]
>>> res._params['all_states']
['B', 'C', 'A']
>>> res = s.time_in_state('state', all_states=['A'])
>>> [round(v, 4) for v in res.value.tolist()]
[0.1]
>>> res.value.index.tolist()
['A']
>>> hasattr(res, 'value')
True

plot_chord

plot_chord(
    column: str,
    all_states: list[str | int] | None = None,
    *,
    fromkey: str | None = None,
    cmap: str | list | None = None,
    show: bool = True,
    save_dir: str | None = None,
    **kwargs,
)

Plot a simple chord diagram of state transitions for this recording.

Parameters

column: Name of the categorical column in features.data to compute transitions from. all_states: Optional explicit list/array of states to define row/column presence and order. Required when fromkey is not provided. fromkey: Optional key in summary.data containing a precomputed transition DataFrame. If provided, this is used directly instead of computing transitions from column. kwargs: Additional keyword arguments to pass to pycirclize.chordDiagram.

Returns

fig_like: Backend-dependent figure-like handle (from pycirclize).

Examples
>>> # xdoctest: +REQUIRES(module: pycirclize)
>>> import tempfile, os
>>> import pandas as pd
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.features.features import Features
>>> from py3r.behaviour.summary.summary import Summary
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t = Tracking.from_dlc(str(p), handle='A', fps=30)
>>> f = Features(t)
>>> # simple 3-state sequence to induce transitions
>>> states = pd.Series(['0','1','2','1','0'] * (len(t.data)//5 + 1))[:len(t.data)]
>>> states.index = t.data.index
>>> f.store(states, 'state', meta={})
>>> s = Summary(f)
>>> with tempfile.TemporaryDirectory() as outdir:
...     _ = s.plot_chord('state', all_states=['0','1','2'], show=False, save_dir=outdir)
...     os.path.exists(os.path.join(outdir, 'A_chord_state.png'))
True

snsstrip

snsstrip(metric, **kwargs)

Strip plot -- see :meth:SummaryCollection.snsstrip.

snsswarm

snsswarm(metric, **kwargs)

Swarm plot -- see :meth:SummaryCollection.snsswarm.

snsbar

snsbar(metric, **kwargs)

Bar plot -- see :meth:SummaryCollection.snsbar.

snsbox

snsbox(metric, **kwargs)

Box plot -- see :meth:SummaryCollection.snsbox.

snsviolin

snsviolin(metric, **kwargs)

Violin plot -- see :meth:SummaryCollection.snsviolin.

snspoint

snspoint(metric, **kwargs)

Point plot -- see :meth:SummaryCollection.snspoint.

snssuperplot

snssuperplot(metric, **kwargs)

Superplot -- see :meth:SummaryCollection.snssuperplot.