Summary
py3r.behaviour.summary.summary.Summary ¶
Summary(trackingfeatures: Features)
stores and computes summary statistics from features objects
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
snssuperplot ¶
snssuperplot(metric, **kwargs)
Superplot -- see :meth:SummaryCollection.snssuperplot.