aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/DataFeatures.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/argaze/DataFeatures.py')
-rw-r--r--src/argaze/DataFeatures.py91
1 files changed, 52 insertions, 39 deletions
diff --git a/src/argaze/DataFeatures.py b/src/argaze/DataFeatures.py
index cf7566a..ac3000c 100644
--- a/src/argaze/DataFeatures.py
+++ b/src/argaze/DataFeatures.py
@@ -7,7 +7,7 @@ __credits__ = []
__copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)"
__license__ = "BSD"
-from typing import TypeVar, Tuple
+from typing import TypeVar, Tuple, Any
from dataclasses import dataclass, field
import importlib
from inspect import getmembers
@@ -103,13 +103,6 @@ class JsonEncoder(json.JSONEncoder):
return public_dict
-class DataDictionary(dict):
- """Enable dot.notation access to dictionary attributes"""
-
- __getattr__ = dict.get
- __setattr__ = dict.__setitem__
- __delattr__ = dict.__delitem__
-
class SharedObject():
"""Enable multiple threads sharing."""
@@ -180,37 +173,6 @@ class SharedObject():
self._token = token
self._lock.release()
-TimeStampedDataLoggerType = TypeVar('TimeStampedDataLogger', bound="TimeStampedDataLogger")
-# Type definition for type annotation convenience
-
-@dataclass
-class TimeStampedDataLogger():
- """Abstract class to define what should provide a timestamped data logger."""
-
- selector: str = field(default='data')
- """Code evaluated to select data. Default 'data' string means that all incoming data will be written."""
-
- @classmethod
- def from_dict(self, logger_module_path: str, logger_parameters: dict) -> TimeStampedDataLoggerType:
- """Load timestamped data logger from dictionary.
-
- Parameters:
- logger_module_path: class name to load
- logger_parameters: attributes to load
- """
-
- # Prepend argaze.DataLog path when a single name is provided
- if len(logger_module_path.split('.')) == 1:
- logger_module_path = f'argaze.DataLog.{logger_module_path}'
-
- logger_module = importlib.import_module(logger_module_path)
- return logger_module.TimeStampedDataLogger(**logger_parameters)
-
- def emit(self, timestamp: TimeStampType, data: DataDictionary):
- """Emit timestamped data dictionary to a specific log destination."""
-
- raise NotImplementedError('emit() method not implemented')
-
class TimeStampedBuffer(collections.OrderedDict):
"""Ordered dictionary to handle timestamped data.
```
@@ -458,3 +420,54 @@ class TimeStampedBuffer(collections.OrderedDict):
legend_patches.append(mpatches.Patch(color=color, label=name.upper()))
return legend_patches
+
+class DataDictionary(dict):
+ """Enable dot.notation access to dictionary attributes"""
+
+ __getattr__ = dict.get
+ __setattr__ = dict.__setitem__
+ __delattr__ = dict.__delitem__
+
+# Import libraries that can be used in selector or formatter codes
+from argaze import GazeFeatures
+
+TimeStampedDataLoggerType = TypeVar('TimeStampedDataLogger', bound="TimeStampedDataLogger")
+# Type definition for type annotation convenience
+
+@dataclass
+class TimeStampedDataLogger():
+ """Abstract class to define what should provide a timestamped data logger."""
+
+ selector: str = field(default='True')
+ """Code evaluated to select data under a condition. Default 'True' string means that all incoming data will be accepted."""
+
+ formatter: str|list = field(default='timestamp, data')
+ """Code (or list of codes) evaluated to format timestamp and data to emit. Default 'timestamp, data' string means that all incoming timestamp and data values will be emitted."""
+
+ @classmethod
+ def from_dict(self, logger_module_path: str, logger_parameters: dict) -> TimeStampedDataLoggerType:
+ """Load timestamped data logger from dictionary.
+
+ Parameters:
+ logger_module_path: class name to load
+ logger_parameters: attributes to load
+ """
+
+ # Prepend argaze.DataLog path when a single name is provided
+ if len(logger_module_path.split('.')) == 1:
+ logger_module_path = f'argaze.DataLog.{logger_module_path}'
+
+ logger_module = importlib.import_module(logger_module_path)
+ return logger_module.TimeStampedDataLogger(**logger_parameters)
+
+ def __call__(self, timestamp: TimeStampType, data: DataDictionary) -> Any:
+ """Apply selector code to decide if data have to be logged, then apply formatter code before to call specific logger emit method."""
+
+ if eval(self.selector):
+
+ return self.emit(eval(self.formatter))
+
+ def emit(self, formatted_log: any):
+ """Emit formatted log to a destination."""
+
+ raise NotImplementedError('handle() method not implemented')