Skip to content

TrackingCollection

py3r.behaviour.tracking.tracking_collection.TrackingCollection

TrackingCollection(tracking_dict: dict[str, Tracking])

Bases: BaseCollection, TrackingCollectionBatchMixin

Collection of Tracking objects, keyed by name (e.g. for grouping individuals) note: type-hints refer to Tracking, but factory methods allow for other classes these are intended ONLY for subclasses of Tracking, and this is enforced

tracking_dict property

tracking_dict

loc property

loc

Slice all elements with Tracking object .loc and return a new collection.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> sub = coll.loc[0:2]
>>> all(len(t.data) == 3 for t in sub.values())
True

iloc property

iloc

Slice all elements with Tracking object .iloc and return a new collection.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> sub = coll.iloc[0:2]
>>> all(len(t.data) == 2 for t in sub.values())
True

is_grouped property

is_grouped

True if this collection is a grouped view.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> coll.is_grouped
False

groupby_tags property

groupby_tags

The tag names used to form this grouped view (or None if flat).

group_keys property

group_keys

Keys for the groups in a grouped view. Empty list if not grouped.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('group','G1'); coll['B'].add_tag('group','G2')
>>> g = coll.groupby('group')
>>> sorted(g.group_keys)
[('G1',), ('G2',)]

from_mapping classmethod

from_mapping(handles_and_filepaths: dict[str, str], *, tracking_loader, tracking_cls=Tracking, **loader_kwargs)

Generic constructor from a mapping of handle -> filepath using a loader callable.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     # create two files for demonstration
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         f1 = d / 'a.csv'; f2 = d / 'b.csv'
...         _ = shutil.copy(p, f1); _ = shutil.copy(p, f2)
...     mapping = {'A': str(f1), 'B': str(f2)}
...     coll = TrackingCollection.from_mapping(mapping, tracking_loader=Tracking.from_dlc, fps=30)
>>> sorted(coll.keys())
['A', 'B']

from_dlc classmethod

from_dlc(handles_and_filepaths: dict[str, str], *, fps: float, aspectratio_correction: float = 1.0, tracking_cls=Tracking)

Load a collection from DLC CSVs.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'a.csv'; b = d / 'b.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> len(coll)
2

from_yolo3r classmethod

from_yolo3r(handles_and_filepaths: dict[str, str], *, fps: float, aspectratio_correction: float = 1.0, tracking_cls=Tracking)

Load a collection from YOLO3R CSVs.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'yolo3r.csv') as p:
...         a = d / 'a.csv'; b = d / 'b.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_yolo3r({'A': str(a), 'B': str(b)}, fps=30)
>>> set(coll.tracking_dict.keys()) == {'A','B'}
True

from_dlcma classmethod

from_dlcma(handles_and_filepaths: dict[str, str], *, fps: float, aspectratio_correction: float = 1.0, tracking_cls=Tracking)

Load a collection from DLC multi-animal CSVs.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlcma_multi.csv') as p:
...         a = d / 'a.csv'; b = d / 'b.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlcma({'A': str(a), 'B': str(b)}, fps=30)
>>> len(coll) == 2
True

from_dogfeather classmethod

from_dogfeather(handles_and_filepaths: dict[str, str], *, fps: float, aspectratio_correction: float = 1.0, tracking_cls=Tracking)

Loads a TrackingCollection from a dict of dogfeather tracking csvs. handles_and_filepaths: dict mapping handles to file paths.

from_folder classmethod

from_folder(folder_path: str, *, tracking_loader, tracking_cls: type = Tracking, **loader_kwargs) -> TrackingCollection

Build a collection by scanning a folder for CSVs (or multi-view subfolders).

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         _ = shutil.copy(p, d / 'A.csv')
...         _ = shutil.copy(p, d / 'B.csv')
...     coll = TrackingCollection.from_folder(str(d), tracking_loader=Tracking.from_dlc, fps=30)
>>> sorted(coll.keys())
['A', 'B']

from_yolo3r_folder classmethod

from_yolo3r_folder(folder_path: str, *, fps: float, aspectratio_correction: float = 1.0, tracking_cls: type = Tracking) -> TrackingCollection

Convenience for from_folder using YOLO3R loader.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'yolo3r.csv') as p:
...         _ = shutil.copy(p, d / 'A.csv')
...         _ = shutil.copy(p, d / 'B.csv')
...     coll = TrackingCollection.from_yolo3r_folder(str(d), fps=30)
>>> len(coll)
2

from_dlc_folder classmethod

from_dlc_folder(folder_path: str, *, fps: float, aspectratio_correction: float = 1.0, tracking_cls: type = Tracking) -> TrackingCollection

Convenience for from_folder using DLC loader.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         _ = shutil.copy(p, d / 'A.csv')
...         _ = shutil.copy(p, d / 'B.csv')
...     coll = TrackingCollection.from_dlc_folder(str(d), fps=30)
>>> set(coll.keys()) == {'A','B'}
True

from_dlcma_folder classmethod

from_dlcma_folder(folder_path: str, *, fps: float, aspectratio_correction: float = 1.0, tracking_cls: type = Tracking) -> TrackingCollection

Convenience for from_folder using DLCMA loader.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlcma_multi.csv') as p:
...         _ = shutil.copy(p, d / 'A.csv')
...         _ = shutil.copy(p, d / 'B.csv')
...     coll = TrackingCollection.from_dlcma_folder(str(d), fps=30)
>>> len(coll) == 2
True

add_tags_from_csv

add_tags_from_csv(csv_path: str) -> None

Adds tags to all Tracking objects in the collection from a csv file. csv_path: path to a csv file with first column: "handle" and other columns with tagnames as titles and tagvalues as values

Examples:

>>> import tempfile, shutil, pandas as pd
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     # build a small collection
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     # tags csv
...     tagcsv = d / 'tags.csv'
...     pd.DataFrame([{'handle':'A','group':'G1'},{'handle':'B','group':'G2'}]).to_csv(tagcsv, index=False)
...     coll.add_tags_from_csv(str(tagcsv))
>>> coll['A'].tags
{'group': 'G1'}
>>> coll['B'].tags
{'group': 'G2'}

stereo_triangulate

stereo_triangulate() -> TrackingCollection

Triangulate all TrackingMV objects and return a new TrackingCollection. The new collection will have the same grouping as the original.

Notes

This requires multi-view TrackingMV elements; typical Tracking elements do not support stereo triangulation.

Examples:

>>> import tempfile, shutil, json
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_mv import TrackingMV
>>> # Create a collection with a single multi-view recording
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d) / 'rec1'
...     d.mkdir(parents=True, exist_ok=True)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p_csv:
...         _ = shutil.copy(p_csv, d / 'left.csv')
...         _ = shutil.copy(p_csv, d / 'right.csv')
...     # write a minimal synthetic calibration.json
...     calib = {
...         'view_order': ['left', 'right'],
...         'views': {
...             'left':  {'K': [[1,0,0],[0,1,0],[0,0,1]], 'dist': [0,0,0,0,0]},
...             'right': {'K': [[1,0,0],[0,1,0],[0,0,1]], 'dist': [0,0,0,0,0]},
...         },
...         'relative_pose': {'R': [[1,0,0],[0,1,0],[0,0,1]], 'T': [0.1, 0.0, 0.0]},
...     }
...     (d / 'calibration.json').write_text(json.dumps(calib))
...     # Build collection by scanning the parent folder with TrackingMV
...     parent = str(d.parent)
...     coll_mv = TrackingCollection.from_dlc_folder(parent, tracking_cls=TrackingMV, fps=30)
...     coll_3d = coll_mv.stereo_triangulate()
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> isinstance(next(iter(coll_3d.values())), Tracking)
True
>>> next(iter(coll_3d.keys()))
'rec1'

plot

plot(*args, **kwargs)

Plot all elements in the collection (or per group if grouped).

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> _ = coll.plot(show=False)

add_usermeta

add_usermeta(usermeta: dict, overwrite: bool = False) -> BatchResult

Batch-mode wrapper for Tracking.add_usermeta across the collection.

adds or updates user-defined metadata

See Tracking.add_usermeta for examples.

add_tag

add_tag(tagname: str, tagvalue: str, overwrite: bool = False) -> BatchResult

Batch-mode wrapper for Tracking.add_tag across the collection.

adds or updates a tag

See Tracking.add_tag for examples.

save

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

Save this collection to a directory. Preserves grouping and delegates to leaf objects' save(dirpath, data_format, overwrite=True).

Examples:

>>> import tempfile, shutil, os
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     out = d / 'coll'
...     coll.save(str(out), overwrite=True, data_format='csv')
...     # collection-level manifest at top-level
...     assert os.path.exists(os.path.join(str(out), 'manifest.json'))
...     # element-level manifests under elements/<handle>/
...     assert os.path.exists(os.path.join(str(out), 'elements', 'A', 'manifest.json'))

strip_column_names

strip_column_names() -> BatchResult

Batch-mode wrapper for Tracking.strip_column_names across the collection.

strips out all column name string apart from last two sections delimited by dots

See Tracking.strip_column_names for examples.

time_as_expected

time_as_expected(mintime: float, maxtime: float) -> BatchResult

Batch-mode wrapper for Tracking.time_as_expected across the collection.

checks that the total length of the tracking data is between mintime seconds and maxtime seconds

See Tracking.time_as_expected for examples.

trim

trim(startframe: int | None = None, endframe: int | None = None) -> BatchResult

Batch-mode wrapper for Tracking.trim across the collection.

trims the tracking data object between startframe and endframe

See Tracking.trim for examples.

filter_likelihood

filter_likelihood(threshold: float) -> BatchResult

Batch-mode wrapper for Tracking.filter_likelihood across the collection.

sets all tracking position values with likelihood less than threshold to np.nan

See Tracking.filter_likelihood for examples.

distance_between

distance_between(point1: str, point2: str, dims=('x', 'y')) -> BatchResult

Batch-mode wrapper for Tracking.distance_between across the collection.

framewise distance between two points

See Tracking.distance_between for examples.

get_point_names

get_point_names() -> BatchResult

Batch-mode wrapper for Tracking.get_point_names across the collection.

list of tracked point names

See Tracking.get_point_names for examples.

rescale_by_known_distance

rescale_by_known_distance(point1: str, point2: str, distance_in_metres: float, dims=('x', 'y')) -> BatchResult

Batch-mode wrapper for Tracking.rescale_by_known_distance across the collection.

rescale all dims by known distance between two points

See Tracking.rescale_by_known_distance for examples.

generate_smoothdict

generate_smoothdict(pointslists: list, windows: list, smoothtypes: list) -> BatchResult

Batch-mode wrapper for Tracking.generate_smoothdict across the collection.

deprecated, use smooth_all instead

See Tracking.generate_smoothdict for examples.

smooth

smooth(smoothing_params: dict) -> BatchResult

Batch-mode wrapper for Tracking.smooth across the collection.

deprecated, use smooth_all instead

See Tracking.smooth for examples.

smooth_all

smooth_all(window: int | None = 3, method: str = 'mean', overrides: list[tuple[list[str] | tuple[str, ...] | str, str, int | None]] | None = None, dims: tuple[str, ...] = ('x', 'y'), strict: bool = False, inplace: bool = True, smoother=None, smoother_kwargs: dict | None = None) -> BatchResult

Batch-mode wrapper for Tracking.smooth_all across the collection.

Smooth all tracked points using a default method/window, with optional override groups.

See Tracking.smooth_all for examples.

interpolate

interpolate(method: str = 'linear', limit: int = 1, **kwargs) -> BatchResult

Batch-mode wrapper for Tracking.interpolate across the collection.

interpolates missing data in the tracking data, and sets likelihood to np.nan uses pandas.DataFrame.interpolate() with kwargs

See Tracking.interpolate for examples.

save_3d_tracking_video_multi_view

save_3d_tracking_video_multi_view(out_path: str, lines: list[tuple[str, str]] = None, point_size=40, line_width=2, point_color='b', line_color='k', dpi=150, writer='pillow', startframe=None, endframe=None, xlim=None, ylim=None, zlim=None, robust_percentile=1, invert_z=True) -> BatchResult

Batch-mode wrapper for Tracking.save_3d_tracking_video_multi_view across the collection.

Save a 3D animation of tracked points to a video file, with 4 subplots per frame: - azim=0, elev=0, ortho - azim=90, elev=0, ortho - azim=0, elev=90, ortho - azim=45, elev=30, persp Optionally, set axis limits manually or use robust percentiles to ignore outliers. Enforces equal aspect ratio for all axes.

See Tracking.save_3d_tracking_video_multi_view for examples.

values

values()

Values iterator (elements or sub-collections).

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> len(list(coll.values())) == 2
True

items

items()

Items iterator (handle, element).

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> sorted([h for h, _ in coll.items()])
['A', 'B']

keys

keys()

Keys iterator (handles or group keys).

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> list(sorted(coll.keys()))
['A', 'B']

from_list classmethod

from_list(objs)

Construct a collection from a list of items, using their .handle as the key. Raises a clear error if any item does not have a .handle attribute.

Examples:

>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking import Tracking
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...     t1 = Tracking.from_dlc(str(p), handle='A', fps=30)
...     t2 = Tracking.from_dlc(str(p), handle='B', fps=30)
>>> coll = TrackingCollection.from_list([t1, t2])
>>> list(sorted(coll.keys()))
['A', 'B']

groupby

groupby(tags)

Group the collection by one or more existing tag names. Returns a grouped view (this same collection type) whose values are sub-collections keyed by a tuple of tag values in the order provided.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('group','G1'); coll['B'].add_tag('group','G2')
>>> g = coll.groupby('group')
>>> g.is_grouped
True
>>> sorted(g.group_keys)
[('G1',), ('G2',)]

flatten

flatten()

Flatten a MultipleCollection to a flat Collection. If already flat, return self.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('group','G1'); coll['B'].add_tag('group','G1')
...     g = coll.groupby('group')
>>> flat = g.flatten()
>>> flat.is_grouped
False
>>> sorted(flat.keys())
['A', 'B']

get_group

get_group(key)

Get a sub-collection by group key from a grouped view.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('group','G1'); coll['B'].add_tag('group','G2')
>>> g = coll.groupby('group')
>>> sub = g.get_group(('G1',))
>>> list(sub.keys())
['A']

regroup

regroup()

Recompute the same grouping using the current tags and the original grouping tag order. If not grouped, returns self.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('group','G1'); coll['B'].add_tag('group','G1')
...     g = coll.groupby('group')
...     coll['B'].add_tag('group','G2', overwrite=True)  # change tag
>>> g2 = g.regroup()
>>> sorted(g2.group_keys)
[('G1',), ('G2',)]

tags_info

tags_info(*, include_value_counts: bool = False) -> pd.DataFrame

Summarize tag presence across the collection's leaf objects. Works for flat and grouped collections. If include_value_counts is True, include a column 'value_counts' with a dict of value->count for each tag. Returns a pandas.DataFrame with columns: ['tag', 'attached_to', 'missing_from', 'unique_values', ('value_counts')]

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     coll['A'].add_tag('genotype', 'WT')
...     coll['B'].add_tag('timepoint', 'T1')
>>> info = coll.tags_info(include_value_counts=True)
>>> int(info.loc['genotype','attached_to'])
1
>>> int(info.loc['genotype','missing_from'])
1
>>> int(info.loc['genotype','unique_values'])
1
>>> info.loc['genotype','value_counts']
{'WT': 1}
>>> int(info.loc['timepoint','attached_to'])
1

map_leaves

map_leaves(fn)

Apply a function to every leaf element and return a new collection of the same type. Preserves grouping shape and groupby metadata when grouped.

fn: callable(Element) -> ElementLike

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
>>> sub = coll.map_leaves(lambda t: t.loc[0:1])
>>> all(len(t.data) == 2 for t in sub.values())
True

load classmethod

load(dirpath: str)

Load a collection previously saved with save(). Uses the class's _element_type.load to reconstruct leaves.

Examples:

>>> import tempfile, shutil
>>> from pathlib import Path
>>> from py3r.behaviour.util.docdata import data_path
>>> from py3r.behaviour.tracking.tracking_collection import TrackingCollection
>>> with tempfile.TemporaryDirectory() as d:
...     d = Path(d)
...     with data_path('py3r.behaviour.tracking._data', 'dlc_single.csv') as p:
...         a = d / 'A.csv'; b = d / 'B.csv'
...         _ = shutil.copy(p, a); _ = shutil.copy(p, b)
...     coll = TrackingCollection.from_dlc({'A': str(a), 'B': str(b)}, fps=30)
...     out = d / 'coll'
...     coll.save(str(out), overwrite=True, data_format='csv')
...     coll2 = TrackingCollection.load(str(out))
>>> list(sorted(coll2.keys()))
['A', 'B']