Skip to content

Commit

Permalink
Merge pull request #22 from glotzerlab/feat/make_signal_deque
Browse files Browse the repository at this point in the history
Add deque for signal aggregation
  • Loading branch information
DomFijan authored Jul 19, 2024
2 parents ead4ad6 + f09dc6e commit 16b8953
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
9 changes: 6 additions & 3 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ Changelog
=========

Version 0.1.0
=============
-------------

[0.1.0] -- 2024-01-06
---------------------
* Added the possibility for the aggregator to have a constant signal length


Version 0.0.1 -- 2024-01-06
----------------------------

First official release.
4 changes: 4 additions & 0 deletions docs/citing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
How to cite **dupin**
=====================

Dupin paper was published in Computer Physics Communications and can be found `here
<https://www.sciencedirect.com/science/article/pii/S0010465524002200>`_. Arxiv pre-print
paper can be found `on this link <https://arxiv.org/abs/2312.15090>`_.

Please acknowledge the use of this software within the body of your publication for example by copying or adapting the following formulation:

*Event detection for this publication used the dupin library[1].*
Expand Down
24 changes: 20 additions & 4 deletions dupin/data/aggregate.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Helper module for generating/storing features accross an entire trajectory.
"""Helper module for generating/storing features across an entire trajectory.
This class provides the `SignalAggregator` class which takes a pipeline and
provides methods for storing the output across a trajectory.
"""

from collections import deque
from collections.abc import Iterator
from typing import Any, Optional

Expand All @@ -28,7 +29,10 @@ class SignalAggregator:
This class can be used to create appropriate data structures for use in
analyzing a whole trajectory with offline methods or iteratively
analyzing for online use. See the `compute` and `accumulate` methods for
usage.
usage. The signal is stored in a deque, which maintains a signal of
constant length by forgetting earlier values. This is useful for online
detection. Full signal length can be achieved by setting `max_deque_length`
to `None`.
Parameters
----------
Expand All @@ -37,7 +41,9 @@ class SignalAggregator:
multivariate signal of a trajectory.
logger : dupin.data.logging.Logger
A logger object to store information about the data processing of
the given pipeline. Defaults to ``None``.
max_deque_length : int, optional
The maximum length of the deque. If None, the deque will be of infinite
size (like a list) and whole signal will be stored.
Attributes
----------
Expand All @@ -51,9 +57,14 @@ def __init__(
self,
generator: base.GeneratorLike,
logger: Optional[logging.Logger] = None,
max_deque_length=None,
):
self.generator = generator
self.signals = []
self._max_deque_length = max_deque_length
if max_deque_length is not None:
self.signals = deque(maxlen=max_deque_length)
else:
self.signals = []
self.logger = logger

def compute(
Expand Down Expand Up @@ -205,6 +216,11 @@ def logger(self):
"""dupin.data.logging.Logger: Logger for the aggregator."""
return self._logger

@property
def max_deque_length(self):
"""int: The maximum length of the deque."""
return self._max_deque_length

@logger.setter
def logger(self, new_logger):
self._logger = new_logger
Expand Down
22 changes: 22 additions & 0 deletions tests/data/test_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,28 @@ def yield_for_generator():
assert all(k in dict_ for k in keys for dict_ in instance.signals)


@given(n_frames(), keys(), data())
def test_compute_no_args_deque(n_frames, keys, data):
"""Test compute works with correct iterator."""
schema = fixed_dictionaries({k: floats() for k in keys})

def generator():
return data.draw(schema)

deque_length = 5

instance = du.data.aggregate.SignalAggregator(
generator, max_deque_length=deque_length
)
for ii, _ in enumerate(range(n_frames)):
instance.accumulate()
if ii >= deque_length:
assert len(instance.signals) == deque_length
else:
assert len(instance.signals) == ii + 1
assert all(k in dict_ for k in keys for dict_ in instance.signals)


@given(n_frames(), keys(), data())
def test_compute_with_args(n_frames, keys, data):
"""Test compute works with correct iterator."""
Expand Down

0 comments on commit 16b8953

Please sign in to comment.