Skip to content

Commit

Permalink
added more examples to get_info and set_info and tested with doctest.…
Browse files Browse the repository at this point in the history
… added initialization examples to intervalset
  • Loading branch information
sjvenditto committed Nov 15, 2024
1 parent 2904388 commit f6c4ed3
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 28 deletions.
88 changes: 69 additions & 19 deletions pynapple/core/interval_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,31 @@ class IntervalSet(NDArrayOperatorsMixin, _MetadataMixin):
>>> import pynapple as nap
>>> import numpy as np
>>> ep = nap.IntervalSet(start=[0, 10], end=[5,20])
start end
0 0 5
1 10 20
shape: (1, 2)
>>> ep
index start end
0 0 5
1 10 20
shape: (2, 2), time unit: sec.
>>> np.diff(ep, 1)
UserWarning: Converting IntervalSet to numpy.array
array([[ 5.],
[10.]])
UserWarning: Converting IntervalSet to numpy.array
array([[ 5.],
[10.]])
You can slice :
>>> ep[:,0]
array([ 0., 10.])
array([ 0., 10.])
>>> ep[0]
start end
0 0 5
shape: (1, 2)
start end
0 0 5
shape: (1, 2)
But modifying the `IntervalSet` with raise an error:
>>> ep[0,0] = 1
RuntimeError: IntervalSet is immutable. Starts and ends have been already sorted.
RuntimeError: IntervalSet is immutable. Starts and ends have been already sorted.
"""

Expand All @@ -89,20 +87,20 @@ def __init__(
metadata=None,
):
"""
`IntervalSet` object initializor.
If start and end are not aligned, meaning that:
1. len(start) != len(end)
2. end[i] > start[i]
3. start[i+1] > end[i]
4. start and end are not sorted,
IntervalSet will try to "fix" the data by eliminating some of the start and end data points.
Parameters
----------
start : numpy.ndarray or number or pandas.DataFrame or pandas.Series or iterable of (start, end) pairs
Beginning of intervals. Alternatively, the `end` argument can be left out and `start` can be one of the
following:
- IntervalSet
- pandas.DataFrame with columns ["start", "end"]
- iterable of (start, end) pairs
Expand All @@ -111,14 +109,66 @@ def __init__(
Ends of intervals.
time_units : str, optional
Time unit of the intervals ('us', 'ms', 's' [default])
metadata: pd.DataFrame or dict, optional
Metadata associated with each interval
metadata: pandas.DataFrame or dict, optional
Metadata associated with each interval. Metadata names are pulled from DataFrame columns or dictionary keys.
The length of the metadata should match the length of the intervals.
Raises
------
RuntimeError
If `start` and `end` arguments are of unknown type.
Examples
--------
>>> import pynapple as nap
>>> import numpy as np
Initialize an `IntervalSet` object with a list of start and end times:
>>> start = [0, 10, 20]
>>> end = [5, 12, 33]
>>> ep = nap.IntervalSet(start=start, end=end)
>>> ep
index start end
0 0 5
1 10 12
2 20 33
shape: (3, 2), time unit: sec.
Initialize an `IntervalSet` object with an array of start and end pairs:
>>> times = np.array([[0, 5], [10, 12], [20, 33]])
>>> ep = nap.IntervalSet(times)
>>> ep
index start end
0 0 5
1 10 12
2 20 33
shape: (3, 2), time unit: sec.
Initialize an `IntervalSet` object with metadata:
>>> start = [0, 10, 20]
>>> end = [5, 12, 33]
>>> metadata = {"label": ["a", "b", "c"]}
>>> ep = nap.IntervalSet(start=start, end=end, metadata=metadata)
index start end label
0 0 5 | a
1 10 12 | b
2 20 33 | c
shape: (3, 2), time unit: sec.
Initialize an `IntervalSet` object with a pandas DataFrame:
>>> import pandas as pd
>>> df = pd.DataFrame(data={"start": [0, 10, 20], "end": [5, 12, 33], "label": ["a", "b", "c"]})
>>> ep = nap.IntervalSet(df)
>>> ep
index start end label
0 0 5 | a
1 10 12 | b
2 20 33 | c
shape: (3, 2), time unit: sec.
"""
# set directly in __dict__ to avoid infinite recursion in __setattr__
self.__dict__["_initialized"] = False
Expand Down
87 changes: 78 additions & 9 deletions pynapple/core/metadata_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ def set_info(self, metadata=None, **kwargs):
"""
Add metadata information about the object. Metadata are saved as a pandas.DataFrame.
If the metadata name does not contain special nor overlaps with class attributes,
it can also be set using attribute assignment.
If the metadata name does not overlap with class-reserved keys,
it can also be set using key assignment.
Metadata entries (excluding "rate" for `TsGroup`) are mutable and can be overwritten.
Parameters
----------
metadata : pandas.DataFrame or dict or pandas.Series, optional
Expand Down Expand Up @@ -188,10 +196,10 @@ def set_info(self, metadata=None, **kwargs):
--------
>>> import pynapple as nap
>>> import numpy as np
>>> tmp = { 0:nap.Ts(t=np.arange(0,200), time_units='s'),
1:nap.Ts(t=np.arange(0,200,0.5), time_units='s'),
2:nap.Ts(t=np.arange(0,300,0.25), time_units='s'),
}
>>> tmp = {0:nap.Ts(t=np.arange(0,200), time_units='s'),
... 1:nap.Ts(t=np.arange(0,200,0.5), time_units='s'),
... 2:nap.Ts(t=np.arange(0,300,0.25), time_units='s'),
... }
>>> tsgroup = nap.TsGroup(tmp)
To add metadata with a pandas.DataFrame:
Expand Down Expand Up @@ -227,6 +235,37 @@ def set_info(self, metadata=None, **kwargs):
0 0.66722 pfc [0, 0] 0
1 1.33445 pfc [0, 1] 1
2 4.00334 ca1 [1, 0] 1
To add metadata as an attribute:
>>> tsgroup.label = ["a", "b", "c"]
>>> tsgroup
Index rate struct coords hd label
------- ------- -------- -------- ---- -------
0 0.66722 pfc [0, 0] 0 a
1 1.33445 pfc [0, 1] 1 b
2 4.00334 ca1 [1, 0] 1 c
To add metadata as a key:
>>> tsgroup["type"] = ["multi", "multi", "single"]
>>> tsgroup
Index rate struct coords hd label type
------- ------- -------- -------- ---- ------- ------
0 0.66722 pfc [0, 0] 0 a multi
1 1.33445 pfc [0, 1] 1 b multi
2 4.00334 ca1 [1, 0] 1 c single
Metadata can be overwritten:
>>> tsgroup.set_info(label=["x", "y", "z"])
>>> tsgroup
Index rate struct coords hd label type
------- ------- -------- -------- ---- ------- ------
0 0.66722 pfc [0, 0] 0 x multi
1 1.33445 pfc [0, 1] 1 y multi
2 4.00334 ca1 [1, 0] 1 z single
"""
# check for duplicate names and/or formatted names that cannot be accessed as attributes or keys
self._check_metadata_column_names(metadata, **kwargs)
Expand Down Expand Up @@ -287,6 +326,12 @@ def get_info(self, key):
"""
Returns metadata based on metadata column name or index.
If the metadata name does not contain special nor overlaps with class attributes,
it can also be accessed as an attribute.
If the metadata name does not overlap with class-reserved keys,
it can also be accessed as a key.
Parameters
----------
key :
Expand All @@ -310,10 +355,10 @@ def get_info(self, key):
--------
>>> import pynapple as nap
>>> import numpy as np
>>> tmp = { 0:nap.Ts(t=np.arange(0,200), time_units='s'),
1:nap.Ts(t=np.arange(0,200,0.5), time_units='s'),
2:nap.Ts(t=np.arange(0,300,0.25), time_units='s'),
}
>>> tmp = {0:nap.Ts(t=np.arange(0,200), time_units='s'),
... 1:nap.Ts(t=np.arange(0,200,0.5), time_units='s'),
... 2:nap.Ts(t=np.arange(0,300,0.25), time_units='s'),
... }
>>> metadata = {"l1": [1, 2, 3], "l2": ["x", "x", "y"]}
>>> tsgroup = nap.TsGroup(tmp,metadata=metadata)
Expand All @@ -328,7 +373,7 @@ def get_info(self, key):
To access multiple metadata columns:
>>> tsgroup.get_info(["l1", "l2"])
l1 l2
l1 l2
0 1 x
1 2 x
2 3 y
Expand All @@ -353,6 +398,30 @@ def get_info(self, key):
>>> tsgroup.get_info((0, "l1"))
np.int64(1)
To access metadata as an attribute:
>>> tsgroup.l1
0 1
1 2
2 3
Name: l1, dtype: int64
To access metadata as a key:
>>> tsgroup["l1"]
0 1
1 2
2 3
Name: l1, dtype: int64
Multiple metadata columns can be accessed as keys:
>>> tsgroup[["l1", "l2"]]
l1 l2
0 1 x
1 2 x
2 3 y
"""
# string indexing of one or more metadata columns
if isinstance(key, str) or (
Expand Down

0 comments on commit f6c4ed3

Please sign in to comment.