#!/usr/bin/env python """N-Gram module. """ __author__ = "Théo de la Hogue" __credits__ = [] __copyright__ = "Copyright 2023, Ecole Nationale de l'Aviation Civile (ENAC)" __license__ = "BSD" from typing import TypeVar, Tuple, Any from dataclasses import dataclass, field from argaze import GazeFeatures, DataFeatures @dataclass class AOIScanPathAnalyzer(GazeFeatures.AOIScanPathAnalyzer): """Implementation of N-Gram algorithm as proposed in: **Lounis C., Peysakhovich V., Causse M. (2021).** *Visual scanning strategies in the cockpit are modulated by pilots’ expertise: A flight simulator study.* PLoS ONE (16(2), 6). [https://doi.org/10.1371/journal.pone.0247061](https://doi.org/10.1371/journal.pone.0247061) """ n_min: int = field(default=2) """Minimal grams length to search.""" n_max: int = field(default=2) """Maximal grams length to search.""" def __post_init__(self): super().__init__() self.__ngrams_count = {} @DataFeatures.PipelineStep def analyze(self, aoi_scan_path: GazeFeatures.AOIScanPathType): assert(len(aoi_scan_path) > 1) sequence = aoi_scan_path.letter_sequence self.__ngrams_count = {} for n in range(self.n_min, self.n_max + 1): ngrams = zip(*[sequence[i:] for i in range(n)]) ngrams = [ngram for ngram in ngrams] self.__ngrams_count[n] = {tuple([aoi_scan_path.get_letter_aoi(l) for l in ngram]) : ngrams.count(ngram) for ngram in ngrams} @property def ngrams_count(self) -> dict: """N-Grams count.""" return self.__ngrams_count