Skip to content

Commit 9ca6748

Browse files
committed
feat(pyargus): add interpolation method parameter for Signal construction
1 parent ad0e62e commit 9ca6748

File tree

3 files changed

+52
-21
lines changed

3 files changed

+52
-21
lines changed

pyargus/argus/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
from typing import List, Optional, Tuple, Type, Union
44

5-
from argus import _argus
6-
from argus._argus import dtype
7-
from argus.exprs import ConstBool, ConstFloat, ConstInt, ConstUInt, VarBool, VarFloat, VarInt, VarUInt
8-
from argus.signals import BoolSignal, FloatSignal, IntSignal, Signal, UnsignedIntSignal
5+
from . import _argus
6+
from ._argus import dtype
7+
from .exprs import ConstBool, ConstFloat, ConstInt, ConstUInt, VarBool, VarFloat, VarInt, VarUInt
8+
from .signals import BoolSignal, FloatSignal, IntSignal, Signal, UnsignedIntSignal
99

1010
try:
1111
__doc__ = _argus.__doc__

pyargus/argus/_argus.pyi

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import ClassVar, Protocol, final
1+
from typing import ClassVar, Literal, Protocol, TypeAlias, final
22

33
from typing_extensions import Self
44

@@ -146,36 +146,46 @@ class Signal:
146146
@final
147147
class BoolSignal(Signal):
148148
@classmethod
149-
def constant(cls, value: bool) -> Self: ...
149+
def constant(cls, value: bool, *, interpolation_method: _InterpolationMethod = "linear") -> Self: ...
150150
@classmethod
151-
def from_samples(cls, samples: list[tuple[float, bool]]) -> Self: ...
151+
def from_samples(
152+
cls, samples: list[tuple[float, bool]], *, interpolation_method: _InterpolationMethod = "linear"
153+
) -> Self: ...
152154
def push(self, time: float, value: bool) -> None: ...
153155
def at(self, time: float) -> bool | None: ...
154156

157+
_InterpolationMethod: TypeAlias = Literal["linear", "constant"]
158+
155159
@final
156160
class IntSignal(Signal):
157161
@classmethod
158-
def constant(cls, value: int) -> Self: ...
162+
def constant(cls, value: int, *, interpolation_method: _InterpolationMethod = "linear") -> Self: ...
159163
@classmethod
160-
def from_samples(cls, samples: list[tuple[float, int]]) -> Self: ...
164+
def from_samples(
165+
cls, samples: list[tuple[float, int]], *, interpolation_method: _InterpolationMethod = "linear"
166+
) -> Self: ...
161167
def push(self, time: float, value: int) -> None: ...
162168
def at(self, time: float) -> int | None: ...
163169

164170
@final
165171
class UnsignedIntSignal(Signal):
166172
@classmethod
167-
def constant(cls, value: int) -> Self: ...
173+
def constant(cls, value: int, *, interpolation_method: _InterpolationMethod = "linear") -> Self: ...
168174
@classmethod
169-
def from_samples(cls, samples: list[tuple[float, int]]) -> Self: ...
175+
def from_samples(
176+
cls, samples: list[tuple[float, int]], *, interpolation_method: _InterpolationMethod = "linear"
177+
) -> Self: ...
170178
def push(self, time: float, value: int) -> None: ...
171179
def at(self, time: float) -> int | None: ...
172180

173181
@final
174182
class FloatSignal(Signal):
175183
@classmethod
176-
def constant(cls, value: float) -> Self: ...
184+
def constant(cls, value: float, *, interpolation_method: _InterpolationMethod = "linear") -> Self: ...
177185
@classmethod
178-
def from_samples(cls, samples: list[tuple[float, float]]) -> Self: ...
186+
def from_samples(
187+
cls, samples: list[tuple[float, float]], *, interpolation_method: _InterpolationMethod = "linear"
188+
) -> Self: ...
179189
def push(self, time: float, value: float) -> None: ...
180190
def at(self, time: float) -> float | None: ...
181191

pyargus/src/signals.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use argus::signals::interpolation::Linear;
1+
use argus::signals::interpolation::{Constant, Linear};
22
use argus::signals::Signal;
3+
use pyo3::exceptions::PyValueError;
34
use pyo3::prelude::*;
45
use pyo3::types::PyType;
56

@@ -10,6 +11,7 @@ use crate::{DType, PyArgusError};
1011
pub enum PyInterp {
1112
#[default]
1213
Linear,
14+
Constant,
1315
}
1416

1517
#[derive(Debug, Clone, derive_more::From, derive_more::TryInto)]
@@ -122,31 +124,49 @@ macro_rules! impl_signals {
122124
impl [<$ty_name Signal>] {
123125
/// Create a new empty signal
124126
#[new]
125-
#[pyo3(signature = ())]
126-
fn new() -> (Self, PySignal) {
127-
(Self, PySignal::new(Signal::<$ty>::new(), PyInterp::Linear))
127+
#[pyo3(signature = (*, interpolation_method = "linear"))]
128+
fn new(interpolation_method: &str) -> PyResult<(Self, PySignal)> {
129+
let interp = match interpolation_method {
130+
"linear" => PyInterp::Linear,
131+
"constant" => PyInterp::Constant,
132+
_ => return Err(PyValueError::new_err(format!("unsupported interpolation method `{}`", interpolation_method))),
133+
};
134+
Ok((Self, PySignal::new(Signal::<$ty>::new(), interp)))
128135
}
129136

130137
/// Create a new signal with constant value
131138
#[classmethod]
132-
fn constant(_: &PyType, py: Python<'_>, value: $ty) -> PyResult<Py<Self>> {
139+
#[pyo3(signature = (value, *, interpolation_method = "linear"))]
140+
fn constant(_: &PyType, py: Python<'_>, value: $ty, interpolation_method: &str) -> PyResult<Py<Self>> {
141+
let interp = match interpolation_method {
142+
"linear" => PyInterp::Linear,
143+
"constant" => PyInterp::Constant,
144+
_ => return Err(PyValueError::new_err(format!("unsupported interpolation method `{}`", interpolation_method))),
145+
};
133146
Py::new(
134147
py,
135-
(Self, PySignal::new(Signal::constant(value), PyInterp::Linear))
148+
(Self, PySignal::new(Signal::constant(value), interp))
136149
)
137150
}
138151

139152
/// Create a new signal from some finite number of samples
140153
#[classmethod]
141-
fn from_samples(_: &PyType, samples: Vec<(f64, $ty)>) -> PyResult<Py<Self>> {
154+
#[pyo3(signature = (samples, *, interpolation_method = "linear"))]
155+
fn from_samples(_: &PyType, samples: Vec<(f64, $ty)>, interpolation_method: &str) -> PyResult<Py<Self>> {
142156
let ret: Signal::<$ty> = Signal::<$ty>::try_from_iter(samples
143157
.into_iter()
144158
.map(|(t, v)| (core::time::Duration::try_from_secs_f64(t).unwrap_or_else(|err| panic!("Value = {}, {}", t, err)), v))
145159
).map_err(PyArgusError::from)?;
160+
161+
let interp = match interpolation_method {
162+
"linear" => PyInterp::Linear,
163+
"constant" => PyInterp::Constant,
164+
_ => return Err(PyValueError::new_err(format!("unsupported interpolation method `{}`", interpolation_method))),
165+
};
146166
Python::with_gil(|py| {
147167
Py::new(
148168
py,
149-
(Self, PySignal::new(ret, PyInterp::Linear))
169+
(Self, PySignal::new(ret, interp))
150170
)
151171
})
152172
}
@@ -171,6 +191,7 @@ macro_rules! impl_signals {
171191
let time = core::time::Duration::from_secs_f64(time);
172192
match super_.interpolation {
173193
PyInterp::Linear => signal.interpolate_at::<Linear>(time),
194+
PyInterp::Constant => signal.interpolate_at::<Constant>(time),
174195
}
175196
}
176197

0 commit comments

Comments
 (0)