diff --git a/pyproject.toml b/pyproject.toml index 04479cd..9308219 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ classifiers = [ ] dependencies = [ "pandas", + "scipy", "StrEnum; python_version < '3.11'", ] diff --git a/src/mopipe/__about__.py b/src/mopipe/__about__.py index 17575d6..b505fea 100644 --- a/src/mopipe/__about__.py +++ b/src/mopipe/__about__.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: 2023-present zeyus # # SPDX-License-Identifier: MIT -__version__ = "0.1.1" +__version__ = "0.1.2" diff --git a/src/mopipe/core/analysis/__init__.py b/src/mopipe/core/analysis/__init__.py index e69de29..692dd6d 100644 --- a/src/mopipe/core/analysis/__init__.py +++ b/src/mopipe/core/analysis/__init__.py @@ -0,0 +1,2 @@ +from .pipeline import Pipeline # noqa: F401, TID252 +from .rqa import calc_rqa # noqa: F401, TID252 diff --git a/src/mopipe/core/analysis/pipeline.py b/src/mopipe/core/analysis/pipeline.py index c2c37a5..66635ee 100644 --- a/src/mopipe/core/analysis/pipeline.py +++ b/src/mopipe/core/analysis/pipeline.py @@ -28,7 +28,7 @@ def segments(self) -> t.MutableSequence[Segment]: def _check_kwargs(self, **kwargs) -> None: """Check the arguments for the pipeline.""" - if "input" not in kwargs: + if "x" not in kwargs: msg = "No input provided to pipeline." raise ValueError(msg) @@ -43,14 +43,13 @@ def add_segment(self, segment: Segment) -> int: def run(self, **kwargs) -> t.Any: """Run the pipeline.""" - output = None self._check_kwargs(**kwargs) for segment in self._segments: # most basic version here # we could also keep track of the output from each step # if that is useful, for now it's just I -> Segment -> O -> Segment -> O -> ... kwargs["x"] = segment(**kwargs) - return output + return kwargs["x"] def __repr__(self) -> str: return f"Pipeline(segments={self._segments})" @@ -75,3 +74,36 @@ def __reversed__(self) -> t.Iterator[Segment]: def __contains__(self, value: object) -> bool: return value in self._segments + + @t.overload + def __setitem__(self, index: int, value: Segment) -> None: ... + + @t.overload + def __setitem__(self, index: slice, value: t.Iterable[Segment]) -> None: ... + + def __setitem__(self, index: t.Union[int, slice], value: t.Union[Segment, t.Iterable[Segment]]) -> None: + if isinstance(index, int): + if not isinstance(value, Segment): + msg = "Single value must be a Segment." + raise ValueError(msg) + self._segments[index] = value + else: + if not isinstance(value, t.Iterable): + msg = "Value must be an iterable of Segments." + raise ValueError(msg) + if not all(isinstance(v, Segment) for v in value): + msg = "All values must be Segments." + raise ValueError(msg) + self._segments[index] = list(value) + + @t.overload + def __delitem__(self, index: int) -> None: ... + + @t.overload + def __delitem__(self, index: slice) -> None: ... + + def __delitem__(self, index: t.Union[int, slice]) -> None: + del self._segments[index] + + def insert(self, index: int, value: Segment) -> None: + self._segments.insert(index, value) diff --git a/src/mopipe/core/analysis/rqa.py b/src/mopipe/core/analysis/rqa.py new file mode 100644 index 0000000..2af5397 --- /dev/null +++ b/src/mopipe/core/analysis/rqa.py @@ -0,0 +1,65 @@ +import numpy as np +import scipy # type: ignore +from pandas.api.extensions import ExtensionArray + + +def calc_rqa( + x: ExtensionArray | np.ndarray, + y: ExtensionArray | np.ndarray, + dim: int = 1, + tau: int = 1, + threshold: float = 0.1, + lmin: int = 2, +) -> list[float]: + embed_data_x: list[np.ndarray] | np.ndarray = [] + embed_data_y: list[np.ndarray] | np.ndarray = [] + for i in range(dim): + embed_data_x.append(x[i * tau : x.shape[0] - (dim - i - 1) * tau]) # type: ignore + embed_data_y.append(y[i * tau : y.shape[0] - (dim - i - 1) * tau]) # type: ignore + embed_data_x, embed_data_y = np.array(embed_data_x), np.array(embed_data_y) + + distance_matrix = scipy.spatial.distance_matrix(embed_data_x.T, embed_data_y.T) + recurrence_matrix = distance_matrix < threshold + msize = recurrence_matrix.shape[0] + + d_line_dist = np.zeros(msize + 1) + for i in range(-msize + 1, msize): + cline = 0 + for e in np.diagonal(recurrence_matrix, i): + if e: + cline += 1 + else: + d_line_dist[cline] += 1 + cline = 0 + d_line_dist[cline] += 1 + + v_line_dist = np.zeros(msize + 1) + for i in range(msize): + cline = 0 + for e in recurrence_matrix[:, i]: + if e: + cline += 1 + else: + v_line_dist[cline] += 1 + cline = 0 + v_line_dist[cline] += 1 + + rr_sum = recurrence_matrix.sum() + rr = rr_sum / msize**2 + det = (d_line_dist[lmin:] * np.arange(msize + 1)[lmin:]).sum() / rr_sum if rr_sum > 0 else 0 + lam = (v_line_dist[lmin:] * np.arange(msize + 1)[lmin:]).sum() / rr_sum if rr_sum > 0 else 0 + + d_sum = d_line_dist[lmin:].sum() + avg_diag_length = (d_line_dist[lmin:] * np.arange(msize + 1)[lmin:]).sum() / d_sum if d_sum > 0 else 0 + v_sum = d_line_dist[lmin:].sum() + avg_vert_length = (v_line_dist[lmin:] * np.arange(msize + 1)[lmin:]).sum() / v_sum if v_sum > 0 else 0 + + d_probs = d_line_dist[lmin:][d_line_dist[lmin:] > 0] + d_probs /= d_probs.sum() + d_entropy = -(d_probs * np.log(d_probs)).sum() + + v_probs = v_line_dist[lmin:][v_line_dist[lmin:] > 0] + v_probs /= v_probs.sum() + v_entropy = -(v_probs * np.log(v_probs)).sum() + + return [rr, det, lam, avg_diag_length, avg_vert_length, d_entropy, v_entropy] diff --git a/src/mopipe/core/common/qtm.py b/src/mopipe/core/common/qtm.py index 2656fd8..d1f0d73 100644 --- a/src/mopipe/core/common/qtm.py +++ b/src/mopipe/core/common/qtm.py @@ -66,7 +66,7 @@ def parse_time_stamp(time_stamp: list[str]) -> tuple[datetime, float]: return ts, unk -def parse_event(event: list[str]) -> tuple[int, float]: +def parse_event(event: list[str]) -> list[tuple[str, int, float]]: """Parse the event data from a list of strings. Parameters @@ -76,12 +76,13 @@ def parse_event(event: list[str]) -> tuple[int, float]: Returns ------- - Tuple[float, float] - Tuple containing the index and elapsed time. + Tuple[str, float, float] + Tuple containing the event name, index and elapsed time. """ - index = int(event[0]) - elapsed_time = float(event[1]) - return index, elapsed_time + event_name = event[0] + index = int(event[1]) + elapsed_time = float(event[2]) + return [(event_name, index, elapsed_time)] def parse_marker_names(marker_names: list[str]) -> list[str]: diff --git a/src/mopipe/core/data/reader.py b/src/mopipe/core/data/reader.py index a83be9d..21db501 100644 --- a/src/mopipe/core/data/reader.py +++ b/src/mopipe/core/data/reader.py @@ -147,7 +147,11 @@ def _parse_metadata_row(self, key: str, values: list[t.Any]) -> None: The values of the metadata row. """ k, v = parse_metadata_row(key, values) - self._metadata[k] = v + if k not in self._metadata: + self._metadata[k] = v + else: + # Metadata entry for an existing key: append values to the list + self._metadata[k] += v def _extract_metadata_from_file(self, path: Path) -> None: """Extract the metadata from a file and return it as a dict. diff --git a/src/mopipe/segment.py b/src/mopipe/segment.py index b428138..78015d2 100644 --- a/src/mopipe/segment.py +++ b/src/mopipe/segment.py @@ -3,11 +3,12 @@ import numpy as np import pandas as pd +from mopipe.core.analysis import calc_rqa from mopipe.core.common.util import int_or_str_slice -from mopipe.core.segments.inputs import AnySeriesInput, MultivariateSeriesInput -from mopipe.core.segments.outputs import SingleNumericValueOutput, UnivariateSeriesOutput +from mopipe.core.segments.inputs import AnySeriesInput, MultivariateSeriesInput, UnivariateSeriesInput +from mopipe.core.segments.outputs import MultivariateSeriesOutput, SingleNumericValueOutput, UnivariateSeriesOutput from mopipe.core.segments.seg import Segment -from mopipe.core.segments.segmenttypes import SummaryType +from mopipe.core.segments.segmenttypes import AnalysisType, SummaryType, TransformType class Mean(SummaryType, AnySeriesInput, SingleNumericValueOutput, Segment): @@ -20,7 +21,10 @@ def process(self, x: t.Union[pd.Series, pd.DataFrame], **kwargs) -> float: # no class ColMeans(SummaryType, MultivariateSeriesInput, UnivariateSeriesOutput, Segment): def process( - self, x: pd.DataFrame, col: t.Union[str, int, slice, None] = None, **kwargs # noqa: ARG002 + self, + x: pd.DataFrame, + col: t.Union[str, int, slice, None] = None, + **kwargs, # noqa: ARG002 ) -> pd.Series: slice_type = None if x.empty: @@ -35,3 +39,138 @@ def process( return x.select_dtypes(include="number").mean() msg = f"Invalid col type {type(col)} provided, Must be None, int, str, or a slice." raise ValueError(msg) + + +class CalcShift(TransformType, MultivariateSeriesInput, MultivariateSeriesOutput, Segment): + def process( + self, + x: pd.DataFrame, + cols: pd.Index | None = None, + shift: int = 1, + **kwargs, # noqa: ARG002 + ) -> pd.DataFrame: + if cols is None: + cols = x.columns + for col_name in cols: + col_data = x[col_name].values + new_col_name = col_name + "_shift" + new_col_data = np.concatenate((np.zeros(shift), col_data[shift:] - col_data[:-shift])) + x[new_col_name] = new_col_data + return x + + +class SimpleGapFilling(TransformType, MultivariateSeriesInput, MultivariateSeriesOutput, Segment): + def process( + self, + x: pd.DataFrame, + **kwargs, # noqa: ARG002 + ) -> pd.DataFrame: + return x.interpolate(method="linear") + + +class RQAStats(AnalysisType, UnivariateSeriesInput, MultivariateSeriesOutput, Segment): + def process( + self, + x: pd.Series, + dim: int = 1, + tau: int = 1, + threshold: float = 0.1, + lmin: int = 2, + **kwargs, # noqa: ARG002 + ) -> pd.DataFrame: + out = pd.DataFrame( + columns=[ + "recurrence_rate", + "determinism", + "laminarity", + "avg_diag_length", + "avg_vert_length", + "d_entropy", + "v_entropy", + ] + ) + if x.empty: + return out + + xv = x.values + out.loc[len(out)] = calc_rqa(xv, xv, dim, tau, threshold, lmin) + return out + + +class CrossRQAStats(AnalysisType, MultivariateSeriesInput, MultivariateSeriesOutput, Segment): + def process( + self, + x: pd.DataFrame, + col_a: t.Union[str, int] = 0, + col_b: t.Union[str, int] = 0, + dim: int = 1, + tau: int = 1, + threshold: float = 0.1, + lmin: int = 2, + **kwargs, # noqa: ARG002 + ) -> pd.DataFrame: + out = pd.DataFrame( + columns=[ + "recurrence_rate", + "determinism", + "laminarity", + "avg_diag_length", + "avg_vert_length", + "d_entropy", + "v_entropy", + ] + ) + if x.empty: + return out + if isinstance(col_a, int): + xa = x.iloc[:, col_a].values + if isinstance(col_a, str): + xa = x.loc[:, col_a].values + if isinstance(col_b, int): + xb = x.iloc[:, col_b].values + if isinstance(col_b, str): + xb = x.loc[:, col_b].values + + out.loc[len(out)] = calc_rqa(xa, xb, dim, tau, threshold, lmin) + return out + + +class WindowedCrossRQAStats(AnalysisType, MultivariateSeriesInput, MultivariateSeriesOutput, Segment): + def process( + self, + x: pd.DataFrame, + col_a: t.Union[str, int] = 0, + col_b: t.Union[str, int] = 0, + dim: int = 1, + tau: int = 1, + threshold: float = 0.1, + lmin: int = 2, + window: int = 100, + step: int = 10, + **kwargs, # noqa: ARG002 + ) -> pd.DataFrame: + out = pd.DataFrame( + columns=[ + "recurrence_rate", + "determinism", + "laminarity", + "avg_diag_length", + "avg_vert_length", + "d_entropy", + "v_entropy", + ] + ) + if x.empty: + return out + if isinstance(col_a, int): + xa = x.iloc[:, col_a].values + if isinstance(col_a, str): + xa = x.loc[:, col_a].values + if isinstance(col_b, int): + xb = x.iloc[:, col_b].values + if isinstance(col_b, str): + xb = x.loc[:, col_b].values + + for w in range(0, xa.shape[0] - window + 1, step): + out.loc[len(out)] = calc_rqa(xa[w : w + window], xb[w : w + window], dim, tau, threshold, lmin) + return out diff --git a/tests/core/analysis/test_pipeline.py b/tests/core/analysis/test_pipeline.py new file mode 100644 index 0000000..26caa2d --- /dev/null +++ b/tests/core/analysis/test_pipeline.py @@ -0,0 +1,30 @@ +from mopipe.core.analysis import Pipeline + + +class TestPipeline: + def test_run_with_no_segments(self): + pipeline = Pipeline([]) + output = pipeline.run(x=None) + assert output is None + + def test_run_with_single_segment(self): + segment = MockSegment() + pipeline = Pipeline([segment]) + output = pipeline.run(x=1) + assert output == segment.process_output + + def test_run_with_multiple_segments(self): + segment1 = MockSegment() + segment2 = MockSegment() + pipeline = Pipeline([segment1, segment2]) + output = pipeline.run(x=1) + assert output == segment2.process_output + + +class MockSegment: + def __init__(self): + self.process_output = None + + def __call__(self, **kwargs): + self.process_output = kwargs["x"] + 1 + return self.process_output diff --git a/tests/core/data/test_reader.py b/tests/core/data/test_reader.py index 8af6351..18bd066 100644 --- a/tests/core/data/test_reader.py +++ b/tests/core/data/test_reader.py @@ -36,3 +36,13 @@ def test_reader(): # number of markers * 3 (x,y,z) + 1 (time) # frame number becomes the index assert len(timeseries.data.columns) == metadata[MocapMetadataEntries["marker_count"]] * 3 + 1 + + +def test_reading_events(): + reader = MocapReader( + source=Path("tests/fixtures/sample_dance_with_header_and_events.tsv"), + name="test", + ) + metadata = reader.metadata + assert metadata["event"] is not None + assert len(metadata["event"]) == 3 diff --git a/tests/fixtures/sample_dance_with_header_and_events.tsv b/tests/fixtures/sample_dance_with_header_and_events.tsv new file mode 100644 index 0000000..b09a93c --- /dev/null +++ b/tests/fixtures/sample_dance_with_header_and_events.tsv @@ -0,0 +1,45 @@ +NO_OF_FRAMES 30 +NO_OF_CAMERAS 9 +NO_OF_MARKERS 31 +FREQUENCY 300 +NO_OF_ANALOG 0 +ANALOG_FREQUENCY 0 +DESCRIPTION -- +TIME_STAMP 2022-11-19, 17:00:37.668 20040.25825930 +DATA_INCLUDED 3D +EVENT playback_start 2 11.0 +EVENT tick 10 12.0 +EVENT tick 21 12.0 +MARKER_NAMES Follow_back Follow_left_shoulder Follow_right_shoulder Follow_head_middle Follow_head_front Follow_left_elbow Follow_right_elbow Follow_left_wrist Follow_right_wrist Follow_left_hip Follow_right_hip Follow_left_knee Follow_right_knee Follow_left_foot Follow_right_foot Lead_back Lead_left_shoulder Lead_right_shoulder Lead_head_middle Lead_head_front Lead_left_elbow Lead_right_elbow Lead_left_wrist Lead_right_wrist Lead_left_hip Lead_right_hip Lead_left_knee Lead_right_knee Lead_left_foot Lead_right_foot Lead_role_marker +TRAJECTORY_TYPES Mixed Measured Measured Measured Mixed Mixed Mixed Mixed Measured Measured Mixed Mixed Mixed Mixed Mixed Mixed Measured Measured Measured Measured Mixed Measured Mixed Mixed Measured Mixed Mixed Measured Mixed Mixed Measured +Frame Time Follow_back X Follow_back Y Follow_back Z Follow_left_shoulder X Follow_left_shoulder Y Follow_left_shoulder Z Follow_right_shoulder X Follow_right_shoulder Y Follow_right_shoulder Z Follow_head_middle X Follow_head_middle Y Follow_head_middle Z Follow_head_front X Follow_head_front Y Follow_head_front Z Follow_left_elbow X Follow_left_elbow Y Follow_left_elbow Z Follow_right_elbow X Follow_right_elbow Y Follow_right_elbow Z Follow_left_wrist X Follow_left_wrist Y Follow_left_wrist Z Follow_right_wrist X Follow_right_wrist Y Follow_right_wrist Z Follow_left_hip X Follow_left_hip Y Follow_left_hip Z Follow_right_hip X Follow_right_hip Y Follow_right_hip Z Follow_left_knee X Follow_left_knee Y Follow_left_knee Z Follow_right_knee X Follow_right_knee Y Follow_right_knee Z Follow_left_foot X Follow_left_foot Y Follow_left_foot Z Follow_right_foot X Follow_right_foot Y Follow_right_foot Z Lead_back X Lead_back Y Lead_back Z Lead_left_shoulder X Lead_left_shoulder Y Lead_left_shoulder Z Lead_right_shoulder X Lead_right_shoulder Y Lead_right_shoulder Z Lead_head_middle X Lead_head_middle Y Lead_head_middle Z Lead_head_front X Lead_head_front Y Lead_head_front Z Lead_left_elbow X Lead_left_elbow Y Lead_left_elbow Z Lead_right_elbow X Lead_right_elbow Y Lead_right_elbow Z Lead_left_wrist X Lead_left_wrist Y Lead_left_wrist Z Lead_right_wrist X Lead_right_wrist Y Lead_right_wrist Z Lead_left_hip X Lead_left_hip Y Lead_left_hip Z Lead_right_hip X Lead_right_hip Y Lead_right_hip Z Lead_left_knee X Lead_left_knee Y Lead_left_knee Z Lead_right_knee X Lead_right_knee Y Lead_right_knee Z Lead_left_foot X Lead_left_foot Y Lead_left_foot Z Lead_right_foot X Lead_right_foot Y Lead_right_foot Z Lead_role_marker X Lead_role_marker Y Lead_role_marker Z +1 0.00000 554.153 711.691 1216.154 613.929 810.295 1370.057 643.733 594.940 1359.095 702.676 718.777 1642.936 767.978 732.601 1629.844 614.954 927.127 1083.250 646.048 528.965 1054.140 747.368 993.438 851.324 734.559 403.248 822.609 657.272 882.426 948.539 665.979 543.097 966.746 742.181 827.488 499.342 771.419 596.092 495.041 806.936 901.495 65.329 806.069 531.647 60.286 1784.028 752.087 1375.628 1616.522 607.310 1507.444 1651.344 907.740 1511.270 1553.689 757.837 1785.922 1493.731 775.498 1778.117 1635.621 479.253 1200.868 1727.462 1040.377 1193.545 1525.563 475.281 934.585 1604.503 1086.434 945.503 1580.916 600.364 1019.019 1579.846 959.722 1039.433 1541.206 633.606 568.211 1559.368 896.829 573.563 1474.946 566.745 67.092 1497.700 977.395 69.907 1609.003 740.488 1791.389 +2 0.00333 554.173 711.948 1216.086 614.128 810.440 1370.002 643.634 595.018 1358.971 703.032 718.834 1642.859 768.250 732.615 1629.720 615.234 927.416 1083.232 645.873 529.163 1053.965 747.753 993.539 851.252 734.457 403.362 822.492 657.331 882.532 948.430 665.930 543.185 966.747 741.883 827.378 499.151 772.022 595.879 495.091 806.907 901.473 65.360 806.086 531.651 60.259 1784.038 752.088 1375.611 1616.535 607.297 1507.443 1651.361 907.729 1511.289 1553.579 757.821 1785.906 1493.768 775.423 1778.046 1635.588 479.261 1200.840 1727.459 1040.397 1193.549 1525.353 475.389 934.645 1604.238 1086.408 945.603 1580.886 600.354 1019.021 1579.835 959.721 1039.423 1541.164 633.597 568.213 1559.340 896.837 573.556 1474.939 566.724 67.102 1497.706 977.405 69.909 1608.916 740.463 1791.404 +3 0.00667 554.270 712.235 1215.968 614.327 810.563 1369.963 643.541 595.105 1358.840 703.425 718.916 1642.795 768.575 732.627 1629.569 615.561 927.746 1083.176 645.679 529.372 1053.809 748.270 993.779 851.258 734.356 403.508 822.351 657.323 882.640 948.360 665.877 543.274 966.727 741.669 827.257 498.981 772.606 595.711 495.130 806.889 901.477 65.368 806.126 531.644 60.210 1784.078 752.087 1375.613 1616.553 607.286 1507.424 1651.400 907.731 1511.284 1553.515 757.804 1785.869 1493.701 775.393 1778.001 1635.578 479.251 1200.836 1727.468 1040.419 1193.552 1525.137 475.502 934.703 1604.008 1086.383 945.710 1580.864 600.348 1019.026 1579.807 959.735 1039.423 1541.127 633.610 568.206 1559.295 896.848 573.546 1474.947 566.709 67.087 1497.700 977.393 69.909 1608.803 740.437 1791.399 +4 0.01000 554.295 712.517 1215.898 614.570 810.730 1369.914 643.450 595.210 1358.702 703.738 719.002 1642.765 768.868 732.663 1629.446 615.943 928.060 1083.143 645.530 529.539 1053.624 748.746 994.011 851.279 734.283 403.612 822.235 657.319 882.731 948.267 665.808 543.356 966.729 741.588 827.159 498.833 773.197 595.550 495.193 806.887 901.486 65.388 806.151 531.633 60.186 1784.072 752.100 1375.586 1616.595 607.261 1507.409 1651.398 907.708 1511.281 1553.402 757.750 1785.844 1493.601 775.364 1777.960 1634.634 478.296 1200.276 1727.556 1040.187 1193.626 1524.942 475.598 934.749 1603.761 1086.388 945.822 1580.862 600.358 1019.029 1579.782 959.729 1039.425 1541.082 633.616 568.205 1559.247 896.863 573.546 1474.956 566.722 67.090 1497.694 977.396 69.893 1608.724 740.408 1791.392 +5 0.01333 554.348 712.819 1215.734 614.555 810.742 1369.902 643.356 595.347 1358.583 703.618 718.782 1642.854 768.879 732.502 1629.391 616.278 928.382 1083.047 645.265 529.767 1053.433 749.513 994.662 851.559 734.438 403.824 822.149 657.082 882.640 948.256 665.739 543.435 966.743 741.593 827.061 498.700 773.695 595.406 495.207 806.899 901.310 65.489 806.161 531.652 60.155 1784.072 752.100 1375.586 1616.527 607.264 1507.347 1651.245 907.708 1511.138 1553.217 757.689 1785.758 1493.451 775.304 1777.821 1634.599 478.276 1200.243 1727.666 1039.883 1193.646 1524.719 475.526 934.826 1603.500 1086.327 945.879 1581.164 600.727 1019.019 1579.724 959.934 1039.425 1541.017 633.609 568.169 1559.149 896.873 573.419 1474.929 566.721 67.092 1497.610 977.307 69.827 1608.572 740.358 1791.340 +6 0.01667 554.373 713.070 1215.692 614.854 811.013 1369.909 643.041 595.336 1358.667 704.159 719.038 1642.802 769.426 732.709 1629.291 616.677 928.670 1083.078 645.130 529.961 1053.269 749.414 994.208 851.205 734.321 403.785 822.210 657.215 882.787 948.190 665.656 543.526 966.772 741.753 827.073 498.529 774.023 595.424 495.221 806.854 901.388 65.419 806.186 531.637 60.130 1784.103 752.089 1375.571 1616.562 607.273 1507.331 1651.364 907.699 1511.216 1553.152 757.707 1785.761 1493.401 775.270 1777.826 1635.644 478.087 1200.801 1727.590 1040.031 1193.772 1525.081 475.637 934.830 1603.162 1086.345 946.036 1581.070 600.461 1018.946 1579.812 959.781 1039.456 1541.264 633.469 568.077 1558.680 896.810 572.992 1474.936 566.747 67.067 1497.546 977.497 70.131 1608.504 740.356 1791.347 +7 0.02000 554.444 713.338 1215.603 615.085 811.197 1369.888 642.959 595.410 1358.579 704.490 719.155 1642.813 769.761 732.762 1629.215 617.062 929.023 1083.040 644.958 530.144 1053.100 749.774 994.323 851.188 734.236 403.886 822.095 657.174 882.833 948.179 665.618 543.599 966.749 741.941 827.034 498.423 774.510 595.283 495.273 806.865 901.384 65.428 806.196 531.623 60.106 1784.097 752.101 1375.542 1616.573 607.267 1507.300 1651.385 907.704 1511.204 1553.071 757.681 1785.725 1493.367 775.191 1777.779 1635.767 478.145 1200.834 1727.588 1040.037 1193.788 1524.985 475.772 934.864 1602.938 1086.315 946.132 1581.056 600.460 1018.941 1579.793 959.770 1039.472 1541.245 633.479 568.067 1558.616 896.802 572.969 1474.917 566.754 67.066 1497.556 977.533 70.182 1608.421 740.336 1791.341 +8 0.02333 554.549 713.607 1215.503 615.255 811.343 1369.911 642.887 595.501 1358.493 704.841 719.255 1642.782 770.035 732.770 1629.150 617.436 929.316 1083.016 644.705 530.373 1052.928 750.231 994.474 851.152 733.765 403.858 821.815 657.092 882.866 948.182 665.549 543.675 966.778 742.162 826.987 498.405 775.263 594.934 495.337 806.872 901.371 65.404 806.227 531.628 60.078 1784.098 752.101 1375.541 1616.585 607.264 1507.284 1651.382 907.690 1511.218 1552.978 757.644 1785.692 1493.275 775.135 1777.733 1635.063 478.840 1200.415 1727.639 1040.085 1193.604 1524.402 476.320 934.991 1602.916 1086.293 946.242 1580.719 600.601 1019.104 1579.606 959.831 1039.434 1541.054 633.640 568.160 1559.184 896.875 573.677 1474.918 566.745 67.075 1497.543 977.538 70.208 1608.357 740.313 1791.331 +9 0.02667 554.611 713.906 1215.443 615.506 811.534 1369.890 642.777 595.604 1358.424 705.174 719.314 1642.777 770.289 732.786 1629.076 617.832 929.596 1083.035 644.581 530.566 1052.721 750.694 994.665 851.164 733.666 403.952 821.707 656.998 882.894 948.168 665.547 543.699 966.754 742.509 827.006 498.389 775.750 594.812 495.384 806.876 901.369 65.403 806.251 531.616 60.055 1784.102 752.101 1375.533 1616.593 607.253 1507.269 1651.393 907.689 1511.204 1552.902 757.603 1785.678 1493.231 775.087 1777.697 1635.016 478.890 1200.375 1727.648 1040.103 1193.599 1524.255 476.428 935.027 1602.747 1086.287 946.330 1580.676 600.614 1019.129 1579.564 959.843 1039.446 1541.011 633.649 568.166 1559.204 896.895 573.729 1474.917 566.757 67.066 1497.547 977.554 70.221 1608.296 740.283 1791.317 +10 0.03000 554.679 714.180 1215.400 615.722 811.704 1369.896 642.707 595.712 1358.346 705.466 719.354 1642.785 770.581 732.844 1629.035 618.261 929.954 1083.095 644.357 530.799 1052.583 751.162 994.827 851.140 733.590 404.062 821.614 656.868 882.919 948.192 665.525 543.737 966.745 742.889 826.963 498.355 776.226 594.740 495.412 806.902 901.372 65.399 806.262 531.602 60.031 1784.107 752.101 1375.524 1616.594 607.263 1507.248 1651.406 907.677 1511.222 1552.854 757.566 1785.647 1493.128 775.039 1777.659 1634.990 478.940 1200.345 1727.649 1040.107 1193.603 1524.110 476.529 935.057 1602.557 1086.306 946.413 1580.626 600.623 1019.130 1579.544 959.844 1039.442 1540.968 633.680 568.169 1559.198 896.917 573.735 1474.919 566.751 67.064 1497.524 977.557 70.229 1608.244 740.268 1791.300 +11 0.03333 554.680 714.413 1215.390 615.905 811.819 1369.954 642.647 595.832 1358.285 705.749 719.368 1642.780 770.880 732.864 1628.987 618.685 930.183 1083.071 644.160 530.984 1052.478 751.658 994.959 851.123 733.533 404.148 821.549 656.741 882.913 948.226 665.519 543.742 966.711 743.412 826.945 498.368 776.631 594.693 495.440 806.904 901.335 65.392 806.287 531.591 60.007 1784.107 752.101 1375.524 1616.606 607.256 1507.241 1651.418 907.665 1511.227 1552.781 757.513 1785.629 1493.086 774.984 1777.629 1634.961 478.954 1200.322 1727.651 1040.148 1193.600 1523.986 476.614 935.077 1602.365 1086.312 946.510 1580.595 600.663 1019.135 1579.519 959.862 1039.444 1540.931 633.685 568.160 1559.193 896.921 573.733 1474.929 566.753 67.064 1497.529 977.549 70.210 1608.200 740.248 1791.300 +12 0.03667 554.708 714.653 1215.407 616.125 811.965 1369.998 642.585 595.927 1358.242 706.036 719.414 1642.796 771.208 732.889 1628.937 619.100 930.463 1083.044 644.040 531.207 1052.343 752.131 995.151 851.141 733.490 404.229 821.493 656.589 882.884 948.253 665.556 543.759 966.695 743.960 826.977 498.352 777.040 594.631 495.495 806.931 901.314 65.392 806.293 531.608 60.003 1784.111 752.102 1375.515 1616.622 607.251 1507.215 1651.397 907.648 1511.219 1552.759 757.493 1785.623 1493.008 774.931 1777.613 1634.938 478.978 1200.298 1727.657 1040.163 1193.608 1523.879 476.712 935.109 1602.159 1086.348 946.602 1580.553 600.662 1019.147 1579.478 959.874 1039.452 1540.892 633.703 568.165 1559.187 896.942 573.726 1474.915 566.764 67.058 1497.544 977.562 70.237 1608.174 740.212 1791.297 +13 0.04000 554.785 714.904 1215.403 616.316 812.078 1370.084 642.561 596.022 1358.214 706.357 719.491 1642.805 771.511 732.899 1628.887 619.599 930.755 1082.992 643.833 531.449 1052.229 752.584 995.279 851.153 733.425 404.296 821.478 656.405 882.845 948.303 665.546 543.738 966.675 744.498 826.989 498.322 777.377 594.642 495.532 806.939 901.333 65.379 806.335 531.600 59.952 1784.099 752.114 1375.498 1616.606 607.246 1507.190 1651.412 907.659 1511.226 1552.729 757.458 1785.607 1492.966 774.882 1777.579 1634.926 478.998 1200.276 1727.660 1040.182 1193.625 1523.777 476.773 935.122 1601.981 1086.378 946.705 1580.520 600.675 1019.152 1579.455 959.865 1039.454 1540.863 633.689 568.161 1559.163 896.971 573.735 1474.937 566.763 67.045 1497.556 977.566 70.225 1608.129 740.170 1791.292 +14 0.04333 554.829 715.148 1215.430 616.623 812.287 1370.177 642.546 596.133 1358.192 706.688 719.564 1642.836 771.785 732.890 1628.838 619.964 931.072 1083.155 643.630 531.695 1052.093 753.055 995.447 851.204 733.382 404.397 821.470 656.204 882.800 948.355 665.558 543.703 966.664 745.080 827.052 498.340 777.723 594.663 495.583 806.943 901.313 65.379 806.320 531.596 59.953 1784.099 752.114 1375.498 1616.609 607.232 1507.179 1651.414 907.641 1511.238 1552.716 757.422 1785.596 1492.904 774.819 1777.564 1634.912 479.007 1200.254 1727.658 1040.212 1193.635 1523.709 476.843 935.136 1601.823 1086.378 946.775 1580.494 600.693 1019.141 1579.443 959.879 1039.444 1540.823 633.700 568.158 1559.163 896.970 573.700 1474.904 566.772 67.059 1497.538 977.555 70.239 1608.123 740.146 1791.286 +15 0.04667 554.900 715.403 1215.475 616.872 812.475 1370.264 642.495 596.273 1358.198 706.972 719.582 1642.867 772.073 732.885 1628.809 620.421 931.372 1083.185 643.544 531.898 1051.912 753.475 995.575 851.273 733.337 404.489 821.474 655.976 882.717 948.452 665.612 543.667 966.637 745.669 827.095 498.340 778.049 594.637 495.639 806.965 901.304 65.375 806.346 531.586 59.929 1784.088 752.102 1375.480 1616.607 607.241 1507.155 1651.415 907.643 1511.250 1552.739 757.369 1785.591 1492.871 774.778 1777.564 1634.902 479.017 1200.237 1727.651 1040.234 1193.639 1523.640 476.894 935.147 1601.689 1086.399 946.837 1580.467 600.695 1019.139 1579.416 959.896 1039.449 1540.790 633.715 568.159 1559.137 897.005 573.706 1474.923 566.766 67.070 1497.533 977.567 70.230 1608.087 740.106 1791.282 +16 0.05000 554.889 715.594 1215.608 617.014 812.586 1370.356 642.469 596.366 1358.220 707.210 719.596 1642.902 772.369 732.903 1628.802 620.915 931.530 1083.213 643.366 532.138 1051.824 753.950 995.780 851.401 733.278 404.576 821.488 655.709 882.641 948.539 665.672 543.588 966.612 746.337 827.201 498.368 778.339 594.681 495.713 806.972 901.304 65.360 806.362 531.589 59.902 1784.072 752.116 1375.469 1616.603 607.237 1507.143 1651.400 907.631 1511.243 1552.757 757.326 1785.595 1492.859 774.735 1777.550 1634.893 479.026 1200.218 1727.652 1040.267 1193.652 1523.585 476.939 935.145 1601.560 1086.407 946.895 1580.422 600.725 1019.147 1579.400 959.895 1039.442 1540.764 633.713 568.155 1559.124 897.034 573.673 1474.923 566.747 67.078 1497.527 977.559 70.229 1608.108 740.075 1791.271 +17 0.05333 554.898 715.774 1215.749 617.207 812.716 1370.445 642.487 596.438 1358.246 707.408 719.630 1642.946 772.661 732.876 1628.798 621.342 931.780 1083.335 643.230 532.402 1051.761 754.384 995.930 851.462 733.239 404.675 821.532 655.454 882.553 948.617 665.749 543.502 966.550 746.955 827.277 498.363 778.621 594.747 495.758 806.989 901.312 65.354 806.362 531.589 59.902 1784.072 752.115 1375.469 1616.609 607.223 1507.135 1651.410 907.625 1511.254 1552.788 757.289 1785.583 1492.862 774.690 1777.560 1634.881 479.044 1200.191 1727.642 1040.288 1193.672 1523.549 476.975 935.143 1601.435 1086.441 946.960 1580.392 600.726 1019.155 1579.364 959.902 1039.441 1540.739 633.717 568.155 1559.116 897.043 573.650 1474.921 566.758 67.045 1497.522 977.570 70.219 1608.122 740.025 1791.271 +18 0.05667 554.877 715.948 1215.948 617.405 812.834 1370.586 642.521 596.503 1358.284 707.666 719.675 1642.989 772.930 732.917 1628.791 621.777 932.079 1083.446 643.124 532.589 1051.756 754.815 996.085 851.570 733.195 404.774 821.587 655.128 882.470 948.764 665.815 543.428 966.524 747.681 827.454 498.388 778.866 594.804 495.798 806.988 901.299 65.346 806.404 531.577 59.895 1784.067 752.114 1375.478 1616.592 607.228 1507.105 1651.394 907.612 1511.261 1552.808 757.236 1785.583 1492.874 774.638 1777.569 1634.866 479.053 1200.175 1727.643 1040.315 1193.685 1523.522 477.004 935.127 1601.290 1086.487 947.027 1580.364 600.743 1019.138 1579.348 959.910 1039.438 1540.699 633.735 568.154 1559.114 897.068 573.619 1474.916 566.764 67.060 1497.525 977.556 70.226 1608.143 739.998 1791.251 +19 0.06000 554.911 716.165 1216.156 617.647 812.981 1370.713 642.573 596.562 1358.321 708.007 719.699 1643.039 773.131 732.931 1628.806 622.222 932.299 1083.492 642.981 532.826 1051.753 755.269 996.241 851.679 733.159 404.854 821.658 654.875 882.368 948.835 665.909 543.321 966.473 748.417 827.641 498.438 779.096 594.859 495.844 806.993 901.309 65.347 806.386 531.579 59.878 1784.072 752.114 1375.470 1616.593 607.231 1507.101 1651.388 907.613 1511.267 1552.843 757.188 1785.588 1492.898 774.563 1777.581 1634.870 479.063 1200.161 1727.637 1040.349 1193.695 1523.519 477.034 935.122 1601.159 1086.533 947.084 1580.318 600.737 1019.142 1579.321 959.914 1039.444 1540.678 633.739 568.153 1559.111 897.084 573.600 1474.921 566.753 67.068 1497.529 977.566 70.229 1608.212 739.946 1791.254 +20 0.06333 554.948 716.324 1216.344 617.872 813.184 1370.853 642.602 596.647 1358.398 708.292 719.732 1643.096 773.387 732.976 1628.799 622.693 932.447 1083.613 642.784 533.047 1051.801 755.686 996.339 851.785 733.110 404.960 821.745 654.623 882.257 948.916 665.986 543.232 966.423 749.112 827.750 498.456 779.280 594.926 495.877 807.010 901.299 65.312 806.411 531.599 59.847 1784.056 752.127 1375.459 1616.548 607.217 1507.077 1651.391 907.607 1511.261 1552.892 757.146 1785.578 1492.966 774.505 1777.596 1634.858 479.067 1200.144 1727.629 1040.369 1193.706 1523.509 477.046 935.103 1601.033 1086.571 947.148 1580.296 600.760 1019.151 1579.293 959.912 1039.429 1540.631 633.741 568.153 1559.100 897.112 573.583 1474.931 566.772 67.059 1497.538 977.563 70.218 1608.241 739.894 1791.242 +21 0.06667 554.944 716.506 1216.527 618.096 813.270 1370.983 642.632 596.771 1358.490 708.608 719.804 1643.149 773.603 732.997 1628.836 623.138 932.739 1083.853 642.596 533.251 1051.871 756.152 996.483 851.928 733.089 405.018 821.841 654.385 882.164 949.001 666.021 543.179 966.434 749.809 827.912 498.511 779.453 595.026 495.907 807.031 901.293 65.308 806.404 531.581 59.852 1784.019 752.127 1375.448 1616.545 607.220 1507.077 1651.387 907.597 1511.285 1552.928 757.103 1785.580 1492.994 774.463 1777.627 1634.855 479.088 1200.123 1727.618 1040.411 1193.720 1523.519 477.071 935.080 1600.924 1086.592 947.195 1580.246 600.769 1019.147 1579.287 959.914 1039.441 1540.605 633.741 568.152 1559.085 897.130 573.560 1474.914 566.770 67.050 1497.541 977.566 70.210 1608.309 739.856 1791.222 +22 0.07000 554.931 716.654 1216.739 618.263 813.323 1371.129 642.745 596.905 1358.597 708.780 719.807 1643.191 773.845 733.023 1628.863 623.531 932.953 1083.973 642.403 533.471 1051.973 756.578 996.600 852.074 733.069 405.107 821.949 654.093 882.012 949.112 666.065 543.088 966.421 750.491 828.074 498.519 779.587 595.114 495.932 807.050 901.292 65.286 806.422 531.585 59.824 1783.983 752.127 1375.438 1616.529 607.217 1507.052 1651.379 907.597 1511.293 1552.976 757.060 1785.581 1493.057 774.368 1777.656 1634.838 479.070 1200.110 1727.608 1040.427 1193.733 1523.539 477.075 935.044 1600.814 1086.645 947.247 1580.217 600.778 1019.150 1579.257 959.933 1039.419 1540.576 633.746 568.148 1559.079 897.146 573.545 1474.914 566.770 67.050 1497.544 977.573 70.223 1608.376 739.819 1791.214 +23 0.07333 554.911 716.798 1216.968 618.439 813.442 1371.312 642.846 597.037 1358.707 708.972 719.778 1643.217 774.086 732.984 1628.916 623.977 933.119 1084.065 642.253 533.627 1052.052 757.009 996.675 852.206 733.051 405.194 822.085 653.797 881.874 949.212 666.100 543.035 966.432 751.233 828.303 498.512 779.713 595.235 495.959 807.080 901.278 65.262 806.444 531.601 59.838 1783.963 752.117 1375.436 1616.496 607.208 1507.028 1651.352 907.587 1511.286 1553.051 757.008 1785.591 1493.126 774.316 1777.704 1634.842 479.086 1200.088 1727.600 1040.455 1193.747 1523.581 477.079 935.013 1600.718 1086.687 947.299 1580.179 600.794 1019.144 1579.231 959.944 1039.424 1540.549 633.765 568.141 1559.058 897.173 573.527 1474.929 566.761 67.048 1497.543 977.571 70.218 1608.444 739.773 1791.190 +24 0.07667 554.909 716.936 1217.254 618.623 813.566 1371.514 642.954 597.148 1358.826 709.166 719.781 1643.252 774.281 732.992 1628.966 624.426 933.346 1084.299 642.098 533.807 1052.122 757.443 996.773 852.390 733.025 405.292 822.209 653.549 881.750 949.293 666.153 542.972 966.416 751.971 828.565 498.505 779.799 595.340 496.000 807.083 901.286 65.238 806.445 531.569 59.844 1783.958 752.117 1375.444 1616.463 607.213 1507.012 1651.332 907.580 1511.289 1553.129 756.965 1785.595 1493.232 774.240 1777.735 1634.833 479.112 1200.073 1727.577 1040.519 1193.756 1523.622 477.098 934.953 1600.625 1086.725 947.325 1580.141 600.795 1019.130 1579.217 959.942 1039.429 1540.506 633.767 568.141 1559.060 897.182 573.493 1474.911 566.780 67.052 1497.523 977.558 70.229 1608.573 739.732 1791.177 +25 0.08000 554.936 717.074 1217.518 618.792 813.618 1371.660 643.070 597.271 1358.959 709.349 719.761 1643.292 774.481 733.007 1629.025 624.784 933.553 1084.530 641.885 534.012 1052.260 757.905 996.885 852.583 732.991 405.392 822.366 653.261 881.638 949.350 666.194 542.921 966.437 752.682 828.768 498.522 779.845 595.461 496.008 807.123 901.264 65.229 806.446 531.571 59.844 1783.937 752.127 1375.443 1616.448 607.210 1507.002 1651.322 907.575 1511.293 1553.223 756.909 1785.608 1493.344 774.170 1777.784 1634.836 479.126 1200.061 1727.575 1040.516 1193.772 1523.677 477.086 934.919 1600.562 1086.770 947.357 1580.104 600.822 1019.124 1579.191 959.958 1039.425 1540.481 633.771 568.141 1559.035 897.210 573.479 1474.925 566.771 67.050 1497.537 977.570 70.216 1608.704 739.662 1791.151 +26 0.08333 554.933 717.195 1217.777 619.002 813.733 1371.799 643.168 597.377 1359.079 709.508 719.747 1643.328 774.661 733.026 1629.072 625.223 933.694 1084.598 641.760 534.170 1052.369 758.305 996.958 852.753 732.979 405.460 822.534 652.959 881.554 949.394 666.224 542.866 966.436 753.374 828.998 498.552 779.869 595.594 496.017 807.142 901.279 65.190 806.469 531.591 59.813 1783.916 752.139 1375.441 1616.393 607.213 1506.991 1651.298 907.568 1511.301 1553.315 756.869 1785.612 1493.457 774.086 1777.841 1634.830 479.125 1200.036 1727.547 1040.541 1193.789 1523.749 477.078 934.864 1600.501 1086.816 947.380 1580.065 600.832 1019.135 1579.169 959.971 1039.423 1540.453 633.784 568.146 1559.028 897.232 573.443 1474.924 566.766 67.073 1497.520 977.569 70.219 1608.857 739.606 1791.129 +27 0.08667 554.909 717.283 1218.038 619.216 813.838 1371.974 643.281 597.475 1359.208 709.644 719.735 1643.390 774.857 733.040 1629.133 625.618 933.899 1084.823 641.600 534.311 1052.528 758.738 997.028 852.952 732.956 405.549 822.721 652.672 881.460 949.393 666.246 542.809 966.459 754.020 829.217 498.543 779.862 595.744 496.040 807.175 901.261 65.160 806.468 531.590 59.814 1783.863 752.128 1375.421 1616.355 607.212 1506.967 1651.263 907.568 1511.297 1553.475 756.775 1785.630 1493.592 774.018 1777.898 1634.819 479.138 1200.022 1727.520 1040.603 1193.797 1523.840 477.051 934.812 1600.445 1086.869 947.400 1580.027 600.839 1019.145 1579.158 959.986 1039.423 1540.417 633.796 568.135 1559.019 897.253 573.421 1474.922 566.776 67.040 1497.525 977.559 70.230 1608.998 739.568 1791.096 +28 0.09000 554.883 717.377 1218.278 619.379 813.932 1372.193 643.384 597.546 1359.367 709.818 719.758 1643.440 775.028 733.048 1629.176 626.025 934.143 1085.022 641.506 534.423 1052.639 759.198 997.093 853.122 732.964 405.588 822.907 652.424 881.405 949.382 666.224 542.770 966.499 754.754 829.546 498.533 779.824 595.896 496.050 807.214 901.277 65.121 806.463 531.573 59.817 1783.854 752.151 1375.439 1616.331 607.217 1506.948 1651.252 907.563 1511.304 1553.579 756.726 1785.647 1493.680 773.957 1777.956 1634.817 479.138 1200.000 1727.491 1040.669 1193.801 1523.936 477.027 934.743 1600.425 1086.918 947.395 1579.980 600.857 1019.149 1579.135 959.990 1039.420 1540.377 633.780 568.133 1559.004 897.277 573.393 1474.911 566.780 67.054 1497.530 977.568 70.233 1609.147 739.526 1791.051 +29 0.09333 554.911 717.457 1218.543 619.565 813.978 1372.374 643.567 597.548 1359.491 709.976 719.773 1643.498 775.177 733.048 1629.234 626.405 934.265 1085.181 641.348 534.544 1052.810 759.643 997.171 853.344 732.943 405.652 823.076 652.177 881.346 949.379 666.225 542.720 966.536 755.466 829.821 498.489 779.772 596.094 496.055 807.228 901.265 65.094 806.469 531.591 59.813 1783.812 752.128 1375.435 1616.293 607.212 1506.929 1651.251 907.562 1511.303 1553.707 756.657 1785.672 1493.877 773.833 1778.005 1634.807 479.170 1199.988 1727.452 1040.762 1193.818 1524.040 477.007 934.693 1600.394 1086.984 947.408 1579.946 600.854 1019.147 1579.121 959.988 1039.413 1540.350 633.795 568.140 1558.991 897.295 573.361 1474.915 566.771 67.052 1497.528 977.562 70.200 1609.278 739.508 1791.015 +30 0.09667 554.926 717.541 1218.838 619.736 814.030 1372.507 643.686 597.605 1359.646 710.194 719.810 1643.559 775.287 733.055 1629.273 626.780 934.427 1085.339 641.202 534.646 1052.970 760.046 997.246 853.547 732.948 405.679 823.270 651.932 881.275 949.369 666.222 542.695 966.550 756.120 830.033 498.503 779.661 596.231 496.074 807.262 901.247 65.053 806.462 531.604 59.810 1783.771 752.151 1375.434 1616.177 607.224 1506.910 1651.192 907.558 1511.304 1553.918 756.559 1785.705 1493.979 773.779 1778.097 1634.795 479.179 1199.970 1727.440 1040.723 1193.832 1524.153 476.972 934.633 1600.380 1087.033 947.401 1579.921 600.868 1019.136 1579.102 960.010 1039.413 1540.299 633.780 568.151 1558.989 897.341 573.322 1474.920 566.763 67.037 1497.543 977.570 70.216 1609.370 739.487 1790.957 diff --git a/tests/test_segments.py b/tests/test_segments.py index 4116332..e138460 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -3,7 +3,7 @@ import pytest # type: ignore from mopipe.core.segments.seg import Segment -from mopipe.segment import ColMeans, Mean +from mopipe.segment import CalcShift, ColMeans, CrossRQAStats, Mean, RQAStats, SimpleGapFilling, WindowedCrossRQAStats class TestMean: @@ -47,3 +47,75 @@ def test_process_with_invalid_col(self, segment: Segment) -> None: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]}) with pytest.raises(ValueError): segment.process(df, col=1.5) + + +class TestRQAStats: + @pytest.fixture + def segment(self) -> Segment: + return RQAStats("TestRQAStats") + + def test_recurrence_measures(self, segment: Segment) -> None: + x = pd.Series([1, 1, 2, 2]) + res = segment.process(x) + assert res.loc[0, "recurrence_rate"] == 0.5 + assert res.loc[0, "determinism"] == 0.5 + res = segment.process(x, lmin=5) + assert res.loc[0, "determinism"] == 0 + res = segment.process(x, threshold=2) + assert res.loc[0, "recurrence_rate"] == 1 + + +class TestCrossRQAStats: + @pytest.fixture + def segment(self) -> Segment: + return CrossRQAStats("TestCrossRQAStats") + + def test_cross_recurrence_measures(self, segment: Segment) -> None: + x = pd.DataFrame({"a": [1, 1, 2, 2, 1, 1, 2, 2], "b": [3, 3, 2, 2, 3, 3, 2, 2]}) + res = segment.process(x, col_a=0, col_b=1) + assert res.loc[0, "recurrence_rate"] == 0.25 + res = segment.process(x, col_a="a", col_b="b") + assert res.loc[0, "recurrence_rate"] == 0.25 + res = segment.process(x, col_a="a", col_b="a") + assert res.loc[0, "recurrence_rate"] == 0.5 + res = segment.process(x) + assert res.loc[0, "recurrence_rate"] == 0.5 + + +class TestWindowedCrossRQAStats: + @pytest.fixture + def segment(self) -> Segment: + return WindowedCrossRQAStats("TestWindowedCrossRQAStats") + + def test_cross_recurrence_measures(self, segment: Segment) -> None: + x = pd.DataFrame({"a": [1, 1, 2, 2, 1, 1, 1, 1], "b": [3, 3, 2, 2, 3, 3, 2, 2]}) + res = segment.process(x, col_a=0, col_b=1, window=4, step=2) + assert res.shape[0] == 3 + assert res.loc[0, "recurrence_rate"] == 0.25 + assert res.loc[1, "recurrence_rate"] == 0.25 + assert res.loc[2, "recurrence_rate"] == 0.0 + + +class TestCalcShift: + @pytest.fixture + def segment(self) -> Segment: + return CalcShift("TestCalcShift") + + def test_calc_shift(self, segment: Segment) -> None: + x = pd.DataFrame({"a": [1, 1, 2, 2, 1, 1, 1, 1], "b": [3, 3, 2, 2, 3, 3, 2, 2]}) + res = segment.process(x, cols=["a"], shift=2) + assert res.shape[1] == 3 + assert (res["a_shift"].values == [0, 0, 1, 1, -1, -1, 0, 0]).mean() == 1.0 + + +class TestSimpleGapFilling: + @pytest.fixture + def segment(self) -> Segment: + return SimpleGapFilling("TestGapFilling") + + def test_gap_filling(self, segment: Segment) -> None: + x = pd.DataFrame({"a": [1, 1, 2, np.nan, 1, 1, 1, 1], "b": [3, 3, 2, 2, np.nan, np.nan, 2, 2]}) + res = segment.process(x) + assert res["a"][3] == 1.5 + assert res["b"][4] == 2 + assert res["b"][5] == 2