Skip to content
Merged
5 changes: 4 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,15 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: "pip"

# A PyMEOS-CFFI branch named as this one carries a matching CFFI change; otherwise the
# CFFI of the MEOS line the package version maps to: stable-X.Y on a released line,
# master on the next one.
- name: Fetch PyMEOS CFFI sources
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
run: |
git clone --branch ${{ env.BRANCH_NAME }} --depth 1 https://github.com/MobilityDB/PyMEOS-CFFI \
|| git clone --branch ${{ github.base_ref || 'master' }} --depth 1 https://github.com/MobilityDB/PyMEOS-CFFI
|| git clone --branch ${{ steps.meos_branch.outputs.meos_branch }} --depth 1 https://github.com/MobilityDB/PyMEOS-CFFI

- name: Install python dependencies
run: |
Expand Down
16 changes: 14 additions & 2 deletions pymeos/temporal/tsequenceset.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
from __future__ import annotations

from abc import ABC
from datetime import timedelta
from typing import TYPE_CHECKING, Any, TypeVar

from pymeos_cffi import *

from .temporal import Temporal, import_pandas
from .temporal import Temporal, TInterpolation, import_pandas

if TYPE_CHECKING:
import pandas as pd


TBase = TypeVar("TBase")
TG = TypeVar("TG", bound="Temporal[Any]")
TI = TypeVar("TI", bound="TInstant[Any]")
Expand Down Expand Up @@ -67,6 +67,18 @@ def from_sequences(
"""
return cls(sequence_list=sequence_list, normalize=normalize)

@classmethod
def from_instants_with_gaps(
cls,
instants: list[TI],
interpolation: TInterpolation,
max_time: timedelta = None,
max_distance: float = 0.0,
):
instant_inners = [x._inner for x in instants]
interval = timedelta_to_interval(max_time) if max_time is not None else None
return cls(_inner=tsequenceset_make_gaps(instant_inners, interpolation, interval, max_distance))

# ------------------------- Accessors -------------------------------------
def num_sequences(self) -> int:
"""
Expand Down
56 changes: 56 additions & 0 deletions tests/main/tbool_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import datetime, timedelta, timezone

import pytest
from pymeos_cffi import MeosException

from pymeos import (
TBool,
Expand Down Expand Up @@ -241,6 +242,61 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize,
assert str(tbs2) == expected
assert tbs2.interpolation() == interpolation

@pytest.mark.parametrize(
"params, result",
[
(
(
[
TBoolInst("True@2000-01-01"),
TBoolInst("False@2000-01-02"),
TBoolInst("False@2000-01-05"),
],
TInterpolation.STEPWISE,
None,
),
TBoolSeqSet("{[True@2000-01-01, False@2000-01-02, False@2000-01-05]}"),
),
(
(
[
TBoolInst("True@2000-01-01"),
TBoolInst("False@2000-01-02"),
TBoolInst("False@2000-01-05"),
],
TInterpolation.STEPWISE,
timedelta(days=2),
),
TBoolSeqSet("{[True@2000-01-01, False@2000-01-02], [False@2000-01-05]}"),
),
],
ids=["No Gaps", "With Gaps"],
)
def test_gaps_constructor(self, params, result):
assert TBoolSeqSet.from_instants_with_gaps(*params) == result

@pytest.mark.parametrize(
"params",
[
{"interpolation": TInterpolation.STEPWISE, "max_distance": 2},
{"interpolation": TInterpolation.LINEAR},
{"interpolation": TInterpolation.DISCRETE},
],
ids=[
"Max Distance",
"Linear Interpolation",
"Discrete Interpolation",
],
)
def test_gaps_constructor_with_invalid_parameters_raises(self, params):
instants = [
TBoolInst(value=True, timestamp="2000-01-01"),
TBoolInst(value=False, timestamp="2000-01-02"),
TBoolInst(value=False, timestamp="2000-01-03"),
]
with pytest.raises(MeosException):
TBoolSeqSet.from_instants_with_gaps(instants, **params)

@pytest.mark.parametrize(
"temporal",
[tbi, tbds, tbs, tbss],
Expand Down
138 changes: 137 additions & 1 deletion tests/main/tfloat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from operator import not_

import pytest
from pymeos_cffi import MeosInvalidArgValueError
from pymeos_cffi import MeosException, MeosInvalidArgValueError

from pymeos import (
FloatSet,
Expand Down Expand Up @@ -249,6 +249,142 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize,
assert str(tfs2) == expected
assert tfs2.interpolation() == interpolation

@pytest.mark.parametrize(
"params, result",
[
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.STEPWISE,
None,
),
TFloatSeqSet("Interp=Step;{[1@2000-01-01, 5@2000-01-02, 6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.STEPWISE,
None,
2.0,
),
TFloatSeqSet("Interp=Step;{[1@2000-01-01], [5@2000-01-02, 6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.STEPWISE,
timedelta(days=2),
),
TFloatSeqSet("Interp=Step;{[1@2000-01-01, 5@2000-01-02], [6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.STEPWISE,
timedelta(days=2),
2.0,
),
TFloatSeqSet("Interp=Step;{[1@2000-01-01], [5@2000-01-02], [6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.LINEAR,
None,
),
TFloatSeqSet("{[1@2000-01-01, 5@2000-01-02, 6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.LINEAR,
None,
2.0,
),
TFloatSeqSet("{[1@2000-01-01], [5@2000-01-02, 6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.LINEAR,
timedelta(days=2),
),
TFloatSeqSet("{[1@2000-01-01, 5@2000-01-02], [6@2000-01-05]}"),
),
(
(
[
TFloatInst("1@2000-01-01"),
TFloatInst("5@2000-01-02"),
TFloatInst("6@2000-01-05"),
],
TInterpolation.LINEAR,
timedelta(days=2),
2.0,
),
TFloatSeqSet("{[1@2000-01-01], [5@2000-01-02], [6@2000-01-05]}"),
),
],
ids=[
"No Gaps Stepwise",
"Value Gaps Stepwise",
"Time Gaps Stepwise",
"Value and Time Gaps Stepwise",
"No Gaps Linear",
"Value Gaps Linear",
"Time Gaps Linear",
"Value and Time Gaps Linear",
],
)
def test_gaps_constructor(self, params, result):
assert TFloatSeqSet.from_instants_with_gaps(*params) == result

@pytest.mark.parametrize(
"params",
[
{"interpolation": TInterpolation.DISCRETE},
],
ids=[
"Discrete Interpolation",
],
)
def test_gaps_constructor_with_invalid_parameters_raises(self, params):
instants = [
TFloatInst(value=1, timestamp="2000-01-01"),
TFloatInst(value=5, timestamp="2000-01-02"),
TFloatInst(value=6, timestamp="2000-01-03"),
]
with pytest.raises(MeosException):
TFloatSeqSet.from_instants_with_gaps(instants, **params)

@pytest.mark.parametrize(
"temporal",
[tfi, tfds, tfs, tfss, tfsts, tfstss],
Expand Down
Loading
Loading