@@ -45,12 +45,14 @@ amplitudes = lc.Amplitude().many(light_curves)
4545print (f " Amplitude: mean = { np.mean(amplitudes):.3f } mag, std = { np.std(amplitudes):.3f } mag " )
4646```
4747
48- For conda, alternative package names, and platform-specific installation notes, see the [ Installation] ( #installation )
48+ For conda, alternative package names, and platform-specific installation notes, see
49+ the [ Installation] ( #installation )
4950section.
5051
5152## Feature extractors
5253
53- Most classes implement feature extractors useful for astrophysical source classification and characterization based
54+ Most classes implement feature extractors useful for astrophysical source classification and characterization
55+ based
5456on light curves.
5557
5658To list all available feature extractors:
@@ -86,7 +88,8 @@ The Flux/magnitude column indicates whether a feature should be used with flux l
8688magnitude light curves only, or either.
8789
8890The ` transform=True ` column shows the default transformation applied to the output when ` transform=True `
89- is passed to the extractor constructor (default is ` transform=None ` , which does not apply any transformations).
91+ is passed to the extractor constructor (default is ` transform=None ` , which does not apply any
92+ transformations).
9093Transformations are monotonic functions intended to reduce dynamic range and improve the suitability of
9194raw feature values for machine learning.
9295You can also select a transformation by name string (e.g. ` transform="lg" ` ) for supported features;
@@ -457,20 +460,24 @@ Meta-features accept other feature extractors and apply them to pre-processed da
457460#### Periodogram
458461
459462This feature transforms time-series data into the Lomb-Scargle periodogram, providing an estimate of the power
460- spectrum. The ` peaks ` argument specifies how many of the most significant spectral density peaks to return. For
463+ spectrum. The ` peaks ` argument specifies how many of the most significant spectral density peaks to return.
464+ For
461465each peak, its period and signal-to-noise ratio are returned:
462466
463467$$
464468\text{signal to noise of peak} \equiv \frac{P(\omega_\mathrm{peak}) - \langle P(\omega) \rangle}{\sigma\_{P(\omega)}}
465469$$
466470
467- The optional ` features ` argument accepts a list of additional feature extractors, which are applied to the power
468- spectrum: frequency is passed as "time," power spectrum is passed as "magnitude," and no uncertainties are set.
471+ The optional ` features ` argument accepts a list of additional feature extractors, which are applied to the
472+ power
473+ spectrum: frequency is passed as "time," power spectrum is passed as "magnitude," and no uncertainties are
474+ set.
469475
470476#### Bins
471477
472478Bins the time series into windows of width $\mathrm{window}$ with respect to some $\mathrm{offset}$.
473- The $j$-th bin spans $[ j \cdot \mathrm{window} + \mathrm{offset},\ (j + 1) \cdot \mathrm{window} + \mathrm{offset}] $.
479+ The $j$-th bin
480+ spans $[ j \cdot \mathrm{window} + \mathrm{offset},\ (j + 1) \cdot \mathrm{window} + \mathrm{offset}] $.
474481
475482The binned time series is defined by
476483$$ t_j^* = (j + \frac12) \cdot \mathrm{window} + \mathrm{offset}, $$
@@ -501,7 +508,8 @@ gives the best balance of robustness and final accuracy.
501508
502509By default, initial parameter values and bounds are estimated from the data. Override them with the
503510` init ` and ` bounds ` arguments (supported by MCMC-based algorithms only), each a list of values or
504- ` None ` s to keep data-derived defaults for individual parameters. ` BazinFit ` has 5 parameters, ` LinexpFit ` has 4,
511+ ` None ` s to keep data-derived defaults for individual parameters. ` BazinFit ` has 5 parameters, ` LinexpFit ` has
512+ 4,
505513` VillarFit ` has 7; run ` help() ` on the respective class for the parameter order.
506514
507515The ` ln_prior ` argument sets the MCMC prior. It accepts ` None ` / ` "no" ` (flat prior, the default),
@@ -511,7 +519,8 @@ distributions (see `help(light_curve.ln_prior)` for the available distribution t
511519encodes supernova physics constraints; it assumes time values are in days.
512520
513521Pass ` transform=True ` to convert the raw fit parameters to a magnitude-like representation: the
514- amplitude becomes a magnitude (assuming input flux in janskys), the baseline is normalized by the amplitude, the
522+ amplitude becomes a magnitude (assuming input flux in janskys), the baseline is normalized by the amplitude,
523+ the
515524reference time is
516525dropped, and the reduced chi^2 is log-scaled. Run ` help(lc.BazinFit) ` for the exact definition.
517526
@@ -539,9 +548,12 @@ print(values)
539548#### Rainbow Fit
540549
541550Rainbow ([ Russeil+23] ( https://arxiv.org/abs/2310.02916 ) ) is a black-body parametric model for transient light
542- curves. By default, it uses the Bazin function as a model for bolometric flux evolution and a logistic function
543- for temperature evolution. The user may customize the model by providing their own functions for bolometric flux
544- and temperature evolution. This example demonstrates the reconstruction of a synthetic light curve with this model.
551+ curves. By default, it uses the Bazin function as a model for bolometric flux evolution and a logistic
552+ function
553+ for temperature evolution. The user may customize the model by providing their own functions for bolometric
554+ flux
555+ and temperature evolution. This example demonstrates the reconstruction of a synthetic light curve with this
556+ model.
545557` RainbowFit ` requires the ` iminuit ` package.
546558
547559<!-- name: test_rainbow_fit_example -->
@@ -594,13 +606,15 @@ print(dict(zip(feature.names, values)))
594606print (f " Goodness of fit: { values[- 1 ]} " )
595607```
596608
597- Note that while the data generation above uses approximate physical constant values, ` RainbowFit ` uses CODATA 2018
609+ Note that while the data generation above uses approximate physical constant values, ` RainbowFit ` uses CODATA
610+ 2018
598611values internally.
599612
600613### Experimental extractors
601614
602615The package consists of two parts: a wrapper for the
603- [ ` light-curve-feature ` Rust crate] ( https://crates.io/crates/light-curve-feature ) (` light_curve_ext ` sub-package)
616+ [ ` light-curve-feature ` Rust crate] ( https://crates.io/crates/light-curve-feature ) (` light_curve_ext `
617+ sub-package)
604618and a pure-Python sub-package ` light_curve_py ` .
605619We use the Python implementation to test the Rust implementation and to develop new experimental extractors.
606620The Python implementation is significantly slower for most extractors and does not provide the same full
@@ -631,12 +645,15 @@ This should print a warning about the experimental status of the Python class.
631645
632646## Performance
633647
634- The package is designed for high throughput. The following techniques help extract features with minimal overhead.
648+ The package is designed for high throughput. The following techniques help extract features with minimal
649+ overhead.
635650
636651### ` sorted ` and ` check ` parameters
637652
638- The ` sorted=True ` argument tells the extractor that ` t ` is already sorted in ascending order, and ` check=False `
639- disables validation of NaN/inf values. The defaults are ` sorted=None ` (the array will be validated and an error raised
653+ The ` sorted=True ` argument tells the extractor that ` t ` is already sorted in ascending order, and
654+ ` check=False `
655+ disables validation of NaN/inf values. The defaults are ` sorted=None ` (the array will be validated and an
656+ error raised
640657if unsorted) and
641658` check=True ` . Passing invalid inputs without validation can cause incorrect results or crashes.
642659
@@ -780,7 +797,8 @@ Run all benchmarks from the Python project folder with
780797` python3 -mpytest --benchmark-enable tests/test_w_bench.py ` , or with slow benchmarks disabled:
781798` python3 -mpytest -m "not (nobs or multi)" --benchmark-enable tests/test_w_bench.py ` .
782799
783- Below we benchmark the Rust implementation (` rust ` ) against the [ ` feets ` ] ( https://feets.readthedocs.io/en/latest/ )
800+ Below we benchmark the Rust implementation (` rust ` ) against the [
801+ ` feets ` ] ( https://feets.readthedocs.io/en/latest/ )
784802package and our own Python implementation (` lc_py ` ) for a light curve with n=1000 observations.
785803
786804![ Benchmarks, Rust is much faster] ( https://github.com/light-curve/light-curve-python/raw/main/light-curve/.readme/benchplot_v2.png )
@@ -792,17 +810,112 @@ but the typical extraction time including these features is 20–50 ms for a few
792810
793811![ Benchmark for different number of observations] ( https://github.com/light-curve/light-curve-python/raw/main/light-curve/.readme/nobs_bench_v2.png )
794812
795- Benchmark results for both the pure-Python and Rust implementations as a function of the number of observations.
813+ Benchmark results for both the pure-Python and Rust implementations as a function of the number of
814+ observations.
796815Both axes are on a logarithmic scale.
797816
798817![ Benchmark for multithreading and multiprocessing] ( https://github.com/light-curve/light-curve-python/raw/main/light-curve/.readme/multi_bench_v2.png )
799818
800- Processing time per light curve for the feature subset from the first benchmark, as a function of the number of
819+ Processing time per light curve for the feature subset from the first benchmark, as a function of the number
820+ of
801821CPU cores used. The dataset consists of 10,000 light curves with 1,000 observations each.
802822
803823See the benchmarks described in more detail in
804824[ "Performant feature extraction for photometric time series"] ( https://arxiv.org/abs/2302.10837 ) .
805825
826+ ## Light curve embeddings (` light_curve.embed ` )
827+
828+ The ` light_curve.embed ` submodule provides pretrained neural network models that map raw photometric
829+ time series to dense vector embeddings suitable for downstream machine learning tasks such as
830+ classification, anomaly detection, and similarity search.
831+ Models are loaded directly from HuggingFace (weights are cached locally after the first download)
832+ and require ` onnxruntime ` and ` huggingface-hub ` :
833+
834+ ```
835+ pip install onnxruntime huggingface_hub
836+ ```
837+
838+ See the [ onnxruntime install guide] ( https://onnxruntime.ai/docs/install/ ) for GPU and platform-specific
839+ packages (` onnxruntime-gpu ` , ` onnxruntime-directml ` , etc.).
840+ Hardware-specific options such as execution providers can be passed via ` ort_session_kwargs `
841+ (see [ onnxruntime Python API] ( https://onnxruntime.ai/docs/api/python/api_summary.html ) ).
842+
843+ ### Single-band models: Astromer
844+
845+ ` Astromer1 ` ([ Donoso-Oliva et al. 2023] ( https://ui.adsabs.harvard.edu/abs/2023A%26A...670A..54D/abstract ) )
846+ and ` Astromer2 ` ([ Donoso-Oliva et al. 2026] ( https://ui.adsabs.harvard.edu/abs/2026A%26A...707A.170D/abstract ) )
847+ are models pretrained on MACHO light curves.
848+ They accept irregularly-sampled ` (time, mag) ` pairs and return 256-dimensional embeddings.
849+
850+ <!-- name: test_embed_astromer -->
851+
852+ ``` python
853+ import numpy as np
854+ from light_curve.embed import Astromer2
855+
856+ model = Astromer2.from_hf(output = " mean" )
857+ # The default reduction splits long light curves into non-overlapping windows;
858+ # pass e.g. reduction="beginning" to always take the first 200 observations.
859+
860+ rng = np.random.default_rng(0 )
861+ time = np.sort(rng.uniform(0 , 500 , 120 )).astype(np.float64)
862+ mag = rng.normal(15 , 0.5 , 120 ).astype(np.float64)
863+
864+ # Returns shape (n_bands, n_subsamples, seq_size, embed_dim)
865+ embedding = model(time, mag)
866+ print (embedding.shape) # (1, 1, 1, 256)
867+ ```
868+
869+ Multi-band light curves can be embedded per-band by passing a list of band labels to the ` bands `
870+ constructor argument:
871+
872+ <!-- name: test_embed_astromer_multiband -->
873+
874+ ``` python
875+ import numpy as np
876+ from light_curve.embed import Astromer2
877+
878+ model = Astromer2.from_hf(output = " mean" , bands = [" g" , " r" ])
879+
880+ rng = np.random.default_rng(1 )
881+ n = 80
882+ time = np.sort(rng.uniform(0 , 300 , n)).astype(np.float64)
883+ mag = rng.normal(15 , 0.5 , n).astype(np.float64)
884+ band = np.array([" g" , " r" ] * (n // 2 ))
885+
886+ # n_bands=2: one embedding per band
887+ embedding = model(time, mag, band = band)
888+ print (embedding.shape) # (2, 1, 1, 256)
889+ ```
890+
891+ ### Multi-band model: ATCAT
892+
893+ ` ATCAT ` ([ Tung 2025] ( https://ui.adsabs.harvard.edu/abs/2025arXiv251100614T/abstract ) ) is a model
894+ trained on ELAsTiCC light curves. It processes all six LSST bands jointly and returns
895+ 384-dimensional embeddings. Inputs are flux, flux-error, time, and integer band indices (ugrizY → 012345):
896+
897+ <!-- name: test_embed_atcat -->
898+
899+ ``` python
900+ import numpy as np
901+ from light_curve.embed import ATCAT
902+
903+ model = ATCAT .from_hf(output = " last" )
904+
905+ rng = np.random.default_rng(2 )
906+ n = 120
907+ time = np.sort(rng.uniform(0 , 500 , n)).astype(np.float32)
908+ flux = rng.normal(100 , 10 , n).astype(np.float32)
909+ flux_err = np.full(n, 5.0 , dtype = np.float32)
910+ band = np.array([i % 6 for i in range (n)]) # ugrizY → 012345
911+
912+ embedding = model(time, flux, flux_err, band)
913+ print (embedding.shape) # (1, 1, 1, 384)
914+ ```
915+
916+ Input fluxes should be in AB units. The default zero-point is 31.4 (LSST nJy); set ` mag_zp=27.5 `
917+ for ELAsTiCC / SNANA FITS data or ` mag_zp=8.9 ` for Jy.
918+
806919## dm-dt map
807920
808921In addition to the feature extractors above, the package provides a separate dm–dt mapping tool.
@@ -856,12 +969,12 @@ On PyPI, we publish wheels for the stable CPython ABI, ensuring compatibility wi
856969
857970### Support matrix
858971
859- | Arch \ OS | Linux glibc 2.17+ | Linux musl 1.2+ | macOS | Windows |
860- | -------------| -------------------| --------------------------------| -----------------------| ---------------------------|
972+ | Arch \ OS | Linux glibc 2.17+ | Linux musl 1.2+ | macOS | Windows |
973+ | -------------| -------------------| --------------------------------| -----------------------| ----------------------------- |
861974| ** x86-64** | PyPI (MKL), conda | PyPI (MKL) | PyPI macOS 15+, conda | PyPI, conda (conda: no GSL) |
862- | ** i686** | src | src | — | not tested |
863- | ** aarch64** | PyPI | PyPI | PyPI macOS 14+, conda | not tested |
864- | ** ppc64le** | src | not tested (no Rust toolchain) | — | — |
975+ | ** i686** | src | src | — | not tested |
976+ | ** aarch64** | PyPI | PyPI | PyPI macOS 14+, conda | not tested |
977+ | ** ppc64le** | src | not tested (no Rust toolchain) | — | — |
865978
866979- ** PyPI / conda** : A binary wheel or package is available on pypi.org or anaconda.org.
867980 Local building is not required; the only prerequisite is a recent version of ` pip ` or ` conda ` .
@@ -921,7 +1034,8 @@ python -mpip install maturin
9211034maturin develop --group dev
9221035```
9231036
924- Run this command during initial setup. On subsequent runs, activate the environment with ` source venv/bin/activate `
1037+ Run this command during initial setup. On subsequent runs, activate the environment with
1038+ ` source venv/bin/activate `
9251039and rebuild Rust code with ` maturin develop ` . Python-only changes require no rebuild. The ` --group dev ` flag
9261040(run from the ` light-curve/ ` directory) is only needed once to install development dependencies.
9271041
@@ -953,7 +1067,8 @@ See the [Benchmarks](#benchmarks) section in [Performance](#performance) for mor
9531067#### Dependencies and Cargo features
9541068
9551069The package has a number of compile-time Cargo features, mostly controlling which C/C++ dependencies are used.
956- Pass the desired features to ` maturin ` with ` --features ` ; it is also recommended to use ` --no-default-features `
1070+ Pass the desired features to ` maturin ` with ` --features ` ; it is also recommended to use
1071+ ` --no-default-features `
9571072to avoid building unnecessary dependencies.
9581073
9591074Available features:
0 commit comments