From 9b9c18e030936f39da55e4033025ab3476f4a59d Mon Sep 17 00:00:00 2001 From: snisioi Date: Fri, 25 Oct 2024 11:55:32 +0300 Subject: [PATCH 1/3] :mushroom: events moved to gaze df --- src/pymovements/__init__.py | 9 ++++- src/pymovements/dataset/dataset.py | 19 ++------- src/pymovements/events/processing.py | 2 +- src/pymovements/gaze/gaze_dataframe.py | 54 ++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/pymovements/__init__.py b/src/pymovements/__init__.py index 8cf4f9387..fa3c26a89 100644 --- a/src/pymovements/__init__.py +++ b/src/pymovements/__init__.py @@ -18,6 +18,10 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Provides top-level access to submodules.""" + +import logging +import os + from pymovements import _version from pymovements import datasets from pymovements import events @@ -44,7 +48,6 @@ from pymovements.measure import SampleMeasureLibrary from pymovements.stimulus import text - __all__ = [ 'Dataset', 'DatasetDefinition', @@ -79,3 +82,7 @@ ] __version__ = _version.get_versions()['version'] + +LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO") +LOG_CONFIG = "[%(levelname)s] %(asctime)s %(name)s:%(lineno)d - %(message)s" +logging.basicConfig(level=LOG_LEVEL, format=LOG_CONFIG) diff --git a/src/pymovements/dataset/dataset.py b/src/pymovements/dataset/dataset.py index 9c851341d..ff1122a3e 100644 --- a/src/pymovements/dataset/dataset.py +++ b/src/pymovements/dataset/dataset.py @@ -713,7 +713,7 @@ def compute_event_properties( name: str | None Process only events that match the name. (default: None) verbose : bool - If ``True``, show progress bar. (default: True) + If ``True``, show more info. (default: True) Raises ------ @@ -728,22 +728,9 @@ def compute_event_properties( Dataset Returns self, useful for method cascading. """ - processor = EventGazeProcessor(event_properties) - - identifier_columns = [ - column - for column in self.fileinfo['gaze'].columns - if column != 'filepath' - ] - disable_progressbar = not verbose - for events, gaze in tqdm(zip(self.events, self.gaze), disable=disable_progressbar): - new_properties = processor.process( - events, gaze, identifiers=identifier_columns, name=name, - ) - join_on = identifier_columns + ['name', 'onset', 'offset'] - events.add_event_properties(new_properties, join_on=join_on) - + for gaze in tqdm(self.gaze, disable=disable_progressbar): + gaze.compute_event_properties(event_properties, name=name, verbose=verbose) return self def compute_properties( diff --git a/src/pymovements/events/processing.py b/src/pymovements/events/processing.py index 517765558..1cc4f2fb6 100644 --- a/src/pymovements/events/processing.py +++ b/src/pymovements/events/processing.py @@ -137,7 +137,7 @@ def process( events: EventDataFrame Event data to process event properties from. gaze: pm.GazeDataFrame - Gaze data to process event properties from. + Raw gaze data to process event properties from. identifiers: str | list[str] Column names to join on events and gaze dataframes. name: str | None diff --git a/src/pymovements/gaze/gaze_dataframe.py b/src/pymovements/gaze/gaze_dataframe.py index 10f3e8bca..6d9fcceae 100644 --- a/src/pymovements/gaze/gaze_dataframe.py +++ b/src/pymovements/gaze/gaze_dataframe.py @@ -20,6 +20,7 @@ """Module for the GazeDataFrame.""" from __future__ import annotations +import logging import inspect import warnings from collections.abc import Callable @@ -28,14 +29,19 @@ import numpy as np import polars as pl +from tqdm import tqdm import pymovements as pm # pylint: disable=cyclic-import +from pymovements.events.processing import EventGazeProcessor from pymovements.gaze import transforms from pymovements.gaze.experiment import Experiment from pymovements.utils import checks from pymovements.utils.aois import get_aoi +logger = logging.getLogger(__name__) + + class GazeDataFrame: """A DataFrame for gaze time series data. @@ -547,6 +553,7 @@ def deg2pix( pixel_origin: str = 'upper left', position_column: str = 'position', pixel_column: str = 'pixel', + verbose: bool = False, ) -> None: """Compute gaze positions in pixel position coordinates from degrees of visual angle. @@ -883,6 +890,53 @@ def detect( how='diagonal', ) + def compute_event_properties( + self, + event_properties: str | tuple[str, dict[str, Any]] + | list[str | tuple[str, dict[str, Any]]], + name: str | None = None, + verbose: bool = True, + ) -> pm.EventDataFrame: + """Calculate an event property for and add it as a column to the event dataframe. + + Parameters + ---------- + event_properties: str | tuple[str, dict[str, Any]] | list[str | tuple[str, dict[str, Any]]] + The event properties to compute. + name: str | None + Process only events that match the name. (default: None) + verbose: bool + If ``True``, print information about the progress. (default: True) + Raises + ------ + InvalidProperty + If ``property_name`` is not a valid property. See + :py:mod:`pymovements.events.event_properties` for an overview of supported properties. + RuntimeError + If specified event name ``name`` is missing from ``events``. + If no events are available to compute event properties. Consider calling detect before. + + Returns + ------- + pm.EventDataFrame + Returns self, useful for method cascading. + """ + if self.events is None: + raise RuntimeError('No events available to compute event properties. ' + 'Consider calling detect before.') + + if verbose is True: + logger.debug(f'Processing events {event_properties} matching {name} \ +for \n{self.events.frame.head()}') + + processor = EventGazeProcessor(event_properties) + new_properties = processor.process( + self.events, self, identifiers=self.trial_columns, name=name, + ) + join_on = self.trial_columns + ['name', 'onset', 'offset'] + self.events.add_event_properties(new_properties, join_on=join_on) + return self + def measure_samples( self, method: str | Callable[..., pl.Expr], From 8982b9d1a85a383d20d2ff6db23d03c65495b221 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 09:01:03 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pymovements/__init__.py | 5 ++--- src/pymovements/dataset/dataset.py | 1 - src/pymovements/gaze/gaze_dataframe.py | 9 +++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/pymovements/__init__.py b/src/pymovements/__init__.py index fa3c26a89..a2b2c6578 100644 --- a/src/pymovements/__init__.py +++ b/src/pymovements/__init__.py @@ -18,7 +18,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Provides top-level access to submodules.""" - import logging import os @@ -83,6 +82,6 @@ __version__ = _version.get_versions()['version'] -LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO") -LOG_CONFIG = "[%(levelname)s] %(asctime)s %(name)s:%(lineno)d - %(message)s" +LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO') +LOG_CONFIG = '[%(levelname)s] %(asctime)s %(name)s:%(lineno)d - %(message)s' logging.basicConfig(level=LOG_LEVEL, format=LOG_CONFIG) diff --git a/src/pymovements/dataset/dataset.py b/src/pymovements/dataset/dataset.py index ff1122a3e..f0aa44161 100644 --- a/src/pymovements/dataset/dataset.py +++ b/src/pymovements/dataset/dataset.py @@ -35,7 +35,6 @@ from pymovements.dataset.dataset_paths import DatasetPaths from pymovements.events.frame import EventDataFrame from pymovements.events.precomputed import PrecomputedEventDataFrame -from pymovements.events.processing import EventGazeProcessor from pymovements.gaze import GazeDataFrame from pymovements.reading_measures.frame import ReadingMeasures diff --git a/src/pymovements/gaze/gaze_dataframe.py b/src/pymovements/gaze/gaze_dataframe.py index 6d9fcceae..fecb16cbd 100644 --- a/src/pymovements/gaze/gaze_dataframe.py +++ b/src/pymovements/gaze/gaze_dataframe.py @@ -20,8 +20,8 @@ """Module for the GazeDataFrame.""" from __future__ import annotations -import logging import inspect +import logging import warnings from collections.abc import Callable from copy import deepcopy @@ -29,7 +29,6 @@ import numpy as np import polars as pl -from tqdm import tqdm import pymovements as pm # pylint: disable=cyclic-import from pymovements.events.processing import EventGazeProcessor @@ -922,8 +921,10 @@ def compute_event_properties( Returns self, useful for method cascading. """ if self.events is None: - raise RuntimeError('No events available to compute event properties. ' - 'Consider calling detect before.') + raise RuntimeError( + 'No events available to compute event properties. ' + 'Consider calling detect before.', + ) if verbose is True: logger.debug(f'Processing events {event_properties} matching {name} \ From b7e8a6856899ddb3f81586c52abb2b62d54c0ac5 Mon Sep 17 00:00:00 2001 From: snisioi Date: Sat, 9 Nov 2024 17:59:24 +0200 Subject: [PATCH 3/3] keep inconsistencies consistent --- src/pymovements/gaze/gaze_dataframe.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pymovements/gaze/gaze_dataframe.py b/src/pymovements/gaze/gaze_dataframe.py index fecb16cbd..a8d8f6290 100644 --- a/src/pymovements/gaze/gaze_dataframe.py +++ b/src/pymovements/gaze/gaze_dataframe.py @@ -895,7 +895,7 @@ def compute_event_properties( | list[str | tuple[str, dict[str, Any]]], name: str | None = None, verbose: bool = True, - ) -> pm.EventDataFrame: + ) -> None: """Calculate an event property for and add it as a column to the event dataframe. Parameters @@ -936,7 +936,6 @@ def compute_event_properties( ) join_on = self.trial_columns + ['name', 'onset', 'offset'] self.events.add_event_properties(new_properties, join_on=join_on) - return self def measure_samples( self,