Skip to content

Commit a1dc572

Browse files
authored
Add Periodogram.power (#529)
1 parent b43f74d commit a1dc572

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4141
- Allow non-numpy inputs and casting mismatched f32 arrays to f64 for the feature extractions with newly added
4242
`cast: bool = False` argument. We plan to change the default value to `True` in a future 0.x version.
4343
https://github.com/light-curve/light-curve-python/issues/509 https://github.com/light-curve/light-curve-python/pull/512
44+
- `Periodogram.power` method https://github.com/light-curve/light-curve-python/pull/529
4445

4546
### Changed
4647

light-curve/src/features.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,12 +1673,12 @@ impl Periodogram {
16731673
));
16741674
}
16751675
let step_candidate = freqs_f64[1] - freqs_f64[0];
1676-
// Check if representable as a linear grid
1677-
let freq_grid_f64 = if freqs_f64.iter().tuple_windows().all(|(x1, x2)| {
1676+
let is_linear = freqs_f64.iter().tuple_windows().all(|(x1, x2)| {
16781677
let dx = x2 - x1;
16791678
let rel_diff = f64::abs(dx / step_candidate - 1.0);
16801679
rel_diff < STEP_SIZE_TOLLERANCE
1681-
}) {
1680+
});
1681+
let freq_grid_f64 = if is_linear {
16821682
if first_zero && len_is_pow2_p1 {
16831683
let log2_size_m1 = (size - 1).ilog2();
16841684
FreqGrid::zero_based_pow2(step_candidate, log2_size_m1)
@@ -1726,6 +1726,23 @@ impl Periodogram {
17261726
Ok((eval_f32, eval_f64))
17271727
}
17281728

1729+
fn power_impl<'py, T>(
1730+
eval: &lcf::Periodogram<T, lcf::Feature<T>>,
1731+
py: Python<'py>,
1732+
t: Arr<T>,
1733+
m: Arr<T>,
1734+
) -> Res<Bound<'py, PyUntypedArray>>
1735+
where
1736+
T: Float + numpy::Element,
1737+
{
1738+
let t: DataSample<_> = t.as_array().into();
1739+
let m: DataSample<_> = m.as_array().into();
1740+
let mut ts = TimeSeries::new_without_weight(t, m);
1741+
let power = eval.power(&mut ts).map_err(lcf::EvaluatorError::from)?;
1742+
let power = PyArray1::from_vec(py, power);
1743+
Ok(power.as_untyped().clone())
1744+
}
1745+
17291746
fn freq_power_impl<'py, T>(
17301747
eval: &lcf::Periodogram<T, lcf::Feature<T>>,
17311748
py: Python<'py>,
@@ -1798,6 +1815,24 @@ impl Periodogram {
17981815
))
17991816
}
18001817

1818+
/// Periodogram values
1819+
#[pyo3(signature = (t, m, *, cast=false))]
1820+
fn power<'py>(
1821+
&self,
1822+
py: Python<'py>,
1823+
t: Bound<PyAny>,
1824+
m: Bound<PyAny>,
1825+
cast: bool,
1826+
) -> Res<Bound<'py, PyUntypedArray>> {
1827+
dtype_dispatch!(
1828+
|t, m| Self::power_impl(&self.eval_f32, py, t, m),
1829+
|t, m| Self::power_impl(&self.eval_f64, py, t, m),
1830+
t,
1831+
=m;
1832+
cast=cast
1833+
)
1834+
}
1835+
18011836
/// Angular frequencies and periodogram values
18021837
#[pyo3(signature = (t, m, *, cast=false))]
18031838
fn freq_power<'py>(
@@ -1859,7 +1894,7 @@ transform : None, optional
18591894
18601895
{common}
18611896
freq_power(t, m, *, cast=False)
1862-
Get periodogram
1897+
Get periodogram as a pair of frequencies and power values
18631898
18641899
Parameters
18651900
----------
@@ -1877,6 +1912,23 @@ freq_power(t, m, *, cast=False)
18771912
power : np.ndarray of np.float32 or np.float64
18781913
Periodogram power
18791914
1915+
power(t, m, *, cast=False)
1916+
Get periodogram power
1917+
1918+
Parameters
1919+
----------
1920+
t : np.ndarray of np.float32 or np.float64
1921+
Time array
1922+
m : np.ndarray of np.float32 or np.float64
1923+
Magnitude (flux) array
1924+
cast : bool, optional
1925+
Cast inputs to np.ndarray objects of the same dtype
1926+
1927+
Returns
1928+
-------
1929+
power : np.ndarray of np.float32 or np.float64
1930+
Periodogram power
1931+
18801932
Examples
18811933
--------
18821934
>>> import numpy as np

light-curve/tests/light_curve_ext/test_periodogram.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ def test_vs_lombscargle():
2323
for freqs in freq_grids:
2424
licu_freqs, licu_power = Periodogram(freqs=freqs, fast=False).freq_power(t, m)
2525
assert_allclose(licu_freqs, freqs)
26+
licu_power2 = Periodogram(freqs=freqs, fast=False).power(t, m)
27+
assert_allclose(licu_power2, licu_power)
2628
scipy_power = lombscargle(t, scipy_y, freqs=freqs, precenter=True, normalize=False)
2729
assert_allclose(scipy_power, licu_power)
2830

@@ -83,6 +85,8 @@ def test_different_freq_grids():
8385
for freqs in freq_grids:
8486
licu_freqs, licu_power = Periodogram(freqs=freqs, fast=False).freq_power(t, m)
8587
assert_allclose(licu_freqs, freqs)
88+
licu_power2 = Periodogram(freqs=freqs, fast=False).power(t, m)
89+
assert_allclose(licu_power2, licu_power)
8690
if base_power is None:
8791
base_power = licu_power
8892
else:

0 commit comments

Comments
 (0)