From 38631ef8d20cfe3e1f39601d797f3f38d29bc168 Mon Sep 17 00:00:00 2001 From: Guillaume Viejo Date: Mon, 30 Oct 2023 15:34:06 -0400 Subject: [PATCH 1/3] Update get --- pynapple/core/time_series.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/pynapple/core/time_series.py b/pynapple/core/time_series.py index 0812fa9c..de8b011e 100644 --- a/pynapple/core/time_series.py +++ b/pynapple/core/time_series.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # @Author: gviejo # @Date: 2022-01-27 18:33:31 -# @Last Modified by: gviejo -# @Last Modified time: 2023-10-27 14:26:55 +# @Last Modified by: Guillaume Viejo +# @Last Modified time: 2023-10-30 15:33:46 """ @@ -754,7 +754,7 @@ def find_support(self, min_gap, time_units="s"): return IntervalSet(start=starts, end=ends) - def get(self, start, end, time_units="s"): + def get(self, start, end=None, time_units="s"): """Slice the time series from start to end such that all the timestamps satisfy start<=t<=end. By default, the time support doesn't change. If you want to change the @@ -765,16 +765,21 @@ def get(self, start, end, time_units="s"): The start end : float or int The end - """ + """ assert isinstance(start, Number), "start should be a float or int" - assert isinstance(end, Number), "end should be a float or int" - assert start < end, "Start should not precede end" - start, end = TsIndex.format_timestamps(np.array([start, end]), time_units) time_array = self.index.values - idx_start = np.searchsorted(time_array, start) - idx_end = np.searchsorted(time_array, end, side="right") - return self[idx_start:idx_end] + if isinstance(end, Number): + assert isinstance(end, Number), "end should be a float or int" + assert start < end, "Start should not precede end" + start, end = TsIndex.format_timestamps(np.array([start, end]), time_units) + idx_start = np.searchsorted(time_array, start) + idx_end = np.searchsorted(time_array, end, side="right") + return self[idx_start:idx_end] + else: + start = TsIndex.format_timestamps(np.array([start]), time_units)[0] + idx_start = np.searchsorted(time_array, start) + return self[idx_start] class TsdTensor(NDArrayOperatorsMixin, _AbstractTsd): """ From e9d9d544be4f1b0db64685d846bd42fa6152800b Mon Sep 17 00:00:00 2001 From: Guillaume Viejo Date: Mon, 30 Oct 2023 16:45:22 -0400 Subject: [PATCH 2/3] Implementing full get for fastplotlib demo --- pynapple/core/time_series.py | 28 +++++++++++++++++++--------- tests/test_time_series.py | 15 ++++++++++++--- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/pynapple/core/time_series.py b/pynapple/core/time_series.py index de8b011e..f15c9b10 100644 --- a/pynapple/core/time_series.py +++ b/pynapple/core/time_series.py @@ -2,7 +2,7 @@ # @Author: gviejo # @Date: 2022-01-27 18:33:31 # @Last Modified by: Guillaume Viejo -# @Last Modified time: 2023-10-30 15:33:46 +# @Last Modified time: 2023-10-30 16:43:22 """ @@ -756,8 +756,9 @@ def find_support(self, min_gap, time_units="s"): def get(self, start, end=None, time_units="s"): """Slice the time series from start to end such that all the timestamps satisfy start<=t<=end. + If end is None, only the timepoint closest to start is returned. - By default, the time support doesn't change. If you want to change the + By default, the time support doesn't change. If you want to change the time support, use the restrict function. Parameters ---------- @@ -765,21 +766,30 @@ def get(self, start, end=None, time_units="s"): The start end : float or int The end - """ + """ assert isinstance(start, Number), "start should be a float or int" time_array = self.index.values - if isinstance(end, Number): + if end is None: + start = TsIndex.format_timestamps(np.array([start]), time_units)[0] + idx = np.searchsorted(time_array, start) + if idx == 0: + return self[idx] + elif idx >= self.shape[0]: + return self[-1] + else: + if start - time_array[idx - 1] < time_array[idx] - start: + return self[idx - 1] + else: + return self[idx] + else: assert isinstance(end, Number), "end should be a float or int" assert start < end, "Start should not precede end" start, end = TsIndex.format_timestamps(np.array([start, end]), time_units) idx_start = np.searchsorted(time_array, start) idx_end = np.searchsorted(time_array, end, side="right") - return self[idx_start:idx_end] - else: - start = TsIndex.format_timestamps(np.array([start]), time_units)[0] - idx_start = np.searchsorted(time_array, start) - return self[idx_start] + return self[idx_start:idx_end] + class TsdTensor(NDArrayOperatorsMixin, _AbstractTsd): """ diff --git a/tests/test_time_series.py b/tests/test_time_series.py index 36e81e39..608a2f09 100755 --- a/tests/test_time_series.py +++ b/tests/test_time_series.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # @Author: gviejo # @Date: 2022-04-01 09:57:55 -# @Last Modified by: gviejo -# @Last Modified time: 2023-10-29 16:19:01 +# @Last Modified by: Guillaume Viejo +# @Last Modified time: 2023-10-30 16:39:56 #!/usr/bin/env python """Tests of time series for `pynapple` package.""" @@ -367,7 +367,7 @@ def test_restrict_inherit_time_support(self, tsd): np.testing.assert_approx_equal(tsd2.time_support.start[0], ep.start[0]) np.testing.assert_approx_equal(tsd2.time_support.end[0], ep.end[0]) - def test_get(self, tsd): + def test_get_interval(self, tsd): tsd2 = tsd.get(10, 20) assert len(tsd2) == 11 np.testing.assert_array_equal(tsd2.index.values, tsd.index.values[10:21]) @@ -383,6 +383,15 @@ def test_get(self, tsd): with pytest.raises(Exception): tsd.get([10], 20) + def test_get_timepoint(self, tsd): + if not isinstance(tsd, nap.Ts): + np.testing.assert_array_equal(tsd.get(-1), tsd[0]) + np.testing.assert_array_equal(tsd.get(0), tsd[0]) + np.testing.assert_array_equal(tsd.get(0.1), tsd[0]) + np.testing.assert_array_equal(tsd.get(0.5), tsd[1]) + np.testing.assert_array_equal(tsd.get(0.6), tsd[1]) + np.testing.assert_array_equal(tsd.get(1), tsd[1]) + np.testing.assert_array_equal(tsd.get(1000), tsd[-1]) #################################################### # Test for tsd From c2976b5e6b01b1539f03f9e29f8ed55c3d70b50e Mon Sep 17 00:00:00 2001 From: Guillaume Viejo Date: Mon, 30 Oct 2023 16:51:35 -0400 Subject: [PATCH 3/3] Bumping 0.4.1 --- docs/HISTORY.md | 13 +++++++++++++ pynapple/__init__.py | 2 +- pynapple/core/time_series.py | 4 ++-- pyproject.toml | 2 +- setup.py | 4 ++-- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/HISTORY.md b/docs/HISTORY.md index 0c71e3bf..0602c708 100644 --- a/docs/HISTORY.md +++ b/docs/HISTORY.md @@ -8,6 +8,19 @@ Around 2016-2017, Luke Sjulson started *TSToolbox2*, still in Matlab and which i In 2018, Francesco started neuroseries, a Python package built on Pandas. It was quickly adopted in Adrien's lab, especially by Guillaume Viejo, a postdoc in the lab. Gradually, the majority of the lab was using it and new functions were constantly added. In 2021, Guillaume and other trainees in Adrien's lab decided to fork from neuroseries and started *pynapple*. The core of pynapple is largely built upon neuroseries. Some of the original changes to TSToolbox made by Luke were included in this package, especially the *time_support* property of all ts/tsd objects. +0.4.1 (2023-10-30) +------------------ + +- Implementing `get` method that return both an interval or the closest timepoint + + +0.4.0 (2023-10-11) +------------------ + +- Implementing the numpy array container approach within pynapple +- TsdTensor for objects larger than 2 dimensions is now available + + 0.3.6 (2023-09-11) ------------------ diff --git a/pynapple/__init__.py b/pynapple/__init__.py index a746c4a2..ed30dc54 100644 --- a/pynapple/__init__.py +++ b/pynapple/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.4.0" +__version__ = "0.4.1" from .core import * from .io import * from .process import * diff --git a/pynapple/core/time_series.py b/pynapple/core/time_series.py index f15c9b10..05d3603b 100644 --- a/pynapple/core/time_series.py +++ b/pynapple/core/time_series.py @@ -782,13 +782,13 @@ def get(self, start, end=None, time_units="s"): return self[idx - 1] else: return self[idx] - else: + else: assert isinstance(end, Number), "end should be a float or int" assert start < end, "Start should not precede end" start, end = TsIndex.format_timestamps(np.array([start, end]), time_units) idx_start = np.searchsorted(time_array, start) idx_end = np.searchsorted(time_array, end, side="right") - return self[idx_start:idx_end] + return self[idx_start:idx_end] class TsdTensor(NDArrayOperatorsMixin, _AbstractTsd): diff --git a/pyproject.toml b/pyproject.toml index b7bc66ba..e1ef8f38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pynapple" -version = "0.4.0" +version = "0.4.1" description = "PYthon Neural Analysis Package Pour Laboratoires d’Excellence" readme = "README.md" authors = [{ name = "Guillaume Viejo", email = "guillaume.viejo@gmail.com" }] diff --git a/setup.py b/setup.py index 620d3239..18a3771c 100644 --- a/setup.py +++ b/setup.py @@ -61,8 +61,8 @@ test_suite='tests', tests_require=test_requirements, url='https://github.com/pynapple-org/pynapple', - version='v0.4.0', + version='v0.4.1', zip_safe=False, long_description_content_type='text/markdown', - download_url='https://github.com/pynapple-org/pynapple/archive/refs/tags/v0.4.0.tar.gz' + download_url='https://github.com/pynapple-org/pynapple/archive/refs/tags/v0.4.1.tar.gz' )