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:

Name Type Description Default

column

str

Name of the column in features.data to analyze.

required

target_value

str | float | int | None

Value to compare against for non-boolean columns. Required unless the column is already boolean.

None

threshold_op

('>', '>=', '<=', '<', '==', '!=')

Comparison operator used to generate the boolean condition. Only "==" and "!=" are valid for string-valued columns.

">"

nth_event

int

Index of the onset event to return (1 = first, note).

1

integration_window

int

Window size for boolean integration/smoothing prior to latency extraction.

1 = no smoothing

Returns:

Type Description
SummaryResult

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

Raises:

Type Description
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:

Name Type Description Default

column

str

Name of the state column in features.data used to create per-state subsets.

required

all_states

list | None

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.

None

max_states

int

Safety guard limiting the number of evaluated states. Raises ValueError if the effective number of states exceeds this value.

100

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:

Name Type Description Default

column

str

Name of the state column in features.data.

required

all_states

list | None

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.

None

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:

Name Type Description Default

column

str

Name of the state column in features.data.

required

all_states

list | None

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.

None

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:

Name Type Description Default

column

str

Name of the categorical column in features.data to compute transitions from.

required

all_states

list[str | int] | None

Optional explicit list/array of states to define row/column presence and order. Required when fromkey is not provided.

None

fromkey

str | None

Optional key in summary.data containing a precomputed transition DataFrame. If provided, this is used directly instead of computing transitions from column.

None

kwargs

Additional keyword arguments to pass to pycirclize.chordDiagram.

{}

Returns:

Name Type Description
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.