gpimg 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gpimg-0.1.0/LICENSE +21 -0
- gpimg-0.1.0/MANIFEST.in +6 -0
- gpimg-0.1.0/PKG-INFO +162 -0
- gpimg-0.1.0/README.md +126 -0
- gpimg-0.1.0/c/CMakeLists.txt +55 -0
- gpimg-0.1.0/c/Makefile +81 -0
- gpimg-0.1.0/c/examples/example.c +68 -0
- gpimg-0.1.0/c/include/gpimg.h +113 -0
- gpimg-0.1.0/c/src/gpimg.c +1485 -0
- gpimg-0.1.0/c/tests/test_gpimg.c +334 -0
- gpimg-0.1.0/pyproject.toml +46 -0
- gpimg-0.1.0/setup.cfg +4 -0
- gpimg-0.1.0/setup.py +88 -0
- gpimg-0.1.0/src/gpimg/__init__.py +23 -0
- gpimg-0.1.0/src/gpimg/_api.py +765 -0
- gpimg-0.1.0/src/gpimg/_core.c +518 -0
- gpimg-0.1.0/src/gpimg/_gpimg_avx2.c +12 -0
- gpimg-0.1.0/src/gpimg/py.typed +0 -0
- gpimg-0.1.0/src/gpimg.egg-info/PKG-INFO +162 -0
- gpimg-0.1.0/src/gpimg.egg-info/SOURCES.txt +22 -0
- gpimg-0.1.0/src/gpimg.egg-info/dependency_links.txt +1 -0
- gpimg-0.1.0/src/gpimg.egg-info/requires.txt +16 -0
- gpimg-0.1.0/src/gpimg.egg-info/top_level.txt +1 -0
- gpimg-0.1.0/tests/test_gpimg.py +385 -0
gpimg-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Francisco Förster
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
gpimg-0.1.0/MANIFEST.in
ADDED
gpimg-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gpimg
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Exact O(n) two-dimensional Gaussian-process fits and images of multi-band light curves
|
|
5
|
+
Author-email: Francisco Förster <francisco.forster@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/fforster/gpimg
|
|
8
|
+
Project-URL: Documentation, https://gpimg.readthedocs.io
|
|
9
|
+
Project-URL: Source, https://github.com/fforster/gpimg
|
|
10
|
+
Keywords: gaussian process,light curves,state space,kalman filter,astronomy,LSST,transients
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: C
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=1.23
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
25
|
+
Requires-Dist: scipy>=1.9; extra == "test"
|
|
26
|
+
Provides-Extra: docs
|
|
27
|
+
Requires-Dist: sphinx>=7; extra == "docs"
|
|
28
|
+
Requires-Dist: furo>=2024.1; extra == "docs"
|
|
29
|
+
Requires-Dist: numpydoc>=1.6; extra == "docs"
|
|
30
|
+
Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
|
|
31
|
+
Requires-Dist: matplotlib>=3.7; extra == "docs"
|
|
32
|
+
Requires-Dist: myst-parser>=2; extra == "docs"
|
|
33
|
+
Provides-Extra: plot
|
|
34
|
+
Requires-Dist: matplotlib>=3.7; extra == "plot"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# gpimg
|
|
38
|
+
|
|
39
|
+
**Exact O(n) two-dimensional Gaussian processes for multi-band light curves.**
|
|
40
|
+
|
|
41
|
+
gpimg fits a Gaussian process jointly in time and wavelength to a multi-band light curve and returns the posterior
|
|
42
|
+
flux on any time × wavelength grid. The kernel is a Matérn-3/2 in time times a squared exponential in ln λ:
|
|
43
|
+
|
|
44
|
+
k((t,λ),(t',λ')) = A² (1 + √3|t−t'|/ℓt) exp(−√3|t−t'|/ℓt) · exp(−(ln λ − ln λ')² / 2ℓλ²)
|
|
45
|
+
|
|
46
|
+
Because the time kernel is a linear stochastic differential equation and the kernel is separable, a light curve
|
|
47
|
+
observed in up to six bands is *exactly* a small linear Gaussian state-space model. gpimg evaluates the likelihood,
|
|
48
|
+
its analytic gradient, maximum-likelihood fits and posterior images with Kalman filters and smoothers in **O(n)**,
|
|
49
|
+
with no approximation.
|
|
50
|
+
|
|
51
|
+
- Exact: likelihoods agree with a dense Cholesky GP to ~1e-11 (relative).
|
|
52
|
+
- Fast: one likelihood + gradient of an 18 668-point light curve in 4.7 ms on one core; a fit of a typical
|
|
53
|
+
deep-drilling LSST light curve (~660 points) in ~19 ms with five starts — 279× faster than PISCOLA's GP fit, and
|
|
54
|
+
1 100× faster for wide-fast-deep light curves (~64 points).
|
|
55
|
+
- Compiled C core, no JIT and no warm-up; AVX2 + FMA code selected at run time; OpenMP batches.
|
|
56
|
+
- Posteriors at any wavelength, smoothed or causal (real time), with an optional numerically stable
|
|
57
|
+
Rauch–Tung–Striebel smoother, and exact band–band covariances for colors.
|
|
58
|
+
- Optional fitted jitter for scatter the quoted errors do not describe; off by default, and off costs nothing.
|
|
59
|
+
- Python package and plain C library (Makefile, CMake, pkg-config).
|
|
60
|
+
|
|
61
|
+
Documentation: the Sphinx sources under `docs/` (guide, Python API, C API, theory). A hosted build is not up yet.
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```console
|
|
66
|
+
$ pip install gpimg
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
gpimg ships as a source distribution, so this compiles the C core for your machine: you need a C compiler (gcc or
|
|
70
|
+
clang). OpenMP is optional — without it `gpimg.batch` runs serially and everything else is unaffected. An AVX2 +
|
|
71
|
+
FMA copy is built alongside the portable one and chosen at import when the CPU supports it.
|
|
72
|
+
|
|
73
|
+
From a source checkout, which also gets you the plain C library:
|
|
74
|
+
|
|
75
|
+
```console
|
|
76
|
+
$ pip install . # the Python package
|
|
77
|
+
$ pytest # optional: pip install ".[test]" first
|
|
78
|
+
$ make -C c && make -C c test # the C library: build/libgpimg.so, build/libgpimg.a
|
|
79
|
+
$ sudo make -C c install # or: cmake -S c -B build && cmake --build build
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Python quick start
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import numpy as np
|
|
86
|
+
import gpimg
|
|
87
|
+
|
|
88
|
+
# t [days], band ('u','g','r','i','z','y' or 0..5; LSST by default), flux and flux_err in any flux unit
|
|
89
|
+
gp = gpimg.GP(t, band, flux, flux_err)
|
|
90
|
+
res = gp.fit() # maximum likelihood, 5 starting points
|
|
91
|
+
print(res.amplitude, res.length_time, res.length_wave, res.message)
|
|
92
|
+
res = gp.fit(jitter=True) # + a white jitter for extra scatter; res.jitter
|
|
93
|
+
|
|
94
|
+
img = gp.predict(np.linspace(-30, 120, 300), # times [d]
|
|
95
|
+
np.geomspace(3200, 10200, 200)) # wavelengths [Å]
|
|
96
|
+
img.mean.shape, img.std.shape # (200, 300): wavelengths x times
|
|
97
|
+
|
|
98
|
+
curves = gp.predict_bands(np.linspace(-30, 120, 300)) # {'u': (mean, std), ...}
|
|
99
|
+
curves, covs = gp.predict_bands(t_grid, cov=True) # + {('g','r'): cov, ...} for color errors
|
|
100
|
+
live = gp.predict(t_grid, causal=True) # filtered: data up to each time only
|
|
101
|
+
stable = gp.predict(t_grid, wave_grid, smoother="rts") # numerically stable smoother
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Many light curves from one long table (pandas, astropy, dict of arrays), fitted and imaged in parallel:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
lcs = gpimg.LightCurves.from_table(table, id="oid", t="t", band="band", flux="flux", flux_err="flux_err")
|
|
108
|
+
res = gpimg.batch(lcs, np.linspace(-30, 120, 300), np.geomspace(3200, 10200, 200))
|
|
109
|
+
res.mean.shape # (n_objects, 200, 300), float32
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Other surveys: `gpimg.GP(t, band, flux, err, wavelengths={"g": 4800.0, "r": 6400.0, "i": 7900.0})`.
|
|
113
|
+
|
|
114
|
+
Runnable examples are in `examples/` (`quickstart.py`, `batch_table.py`, `causal_vs_smoothed.py`,
|
|
115
|
+
`other_survey.py`).
|
|
116
|
+
|
|
117
|
+
## C quick start
|
|
118
|
+
|
|
119
|
+
```c
|
|
120
|
+
#include "gpimg.h"
|
|
121
|
+
|
|
122
|
+
double lnwave[6]; /* ln of the band wavelengths */
|
|
123
|
+
gp_fit_opts opts;
|
|
124
|
+
gp_fit_default_opts(&opts);
|
|
125
|
+
opts.nstart = 5;
|
|
126
|
+
gp_fit_result res;
|
|
127
|
+
gp_fit(n, t, band, y, err, lnwave, theta0, &opts, &res); /* res.theta = (ln A, ln lt, ln ll) */
|
|
128
|
+
gp_image(n, t, band, y, err, 6, lnwave, res.theta, nt, tg, nl, lng, mean, var, GPIMG_SMOOTH(GPIMG_RTS));
|
|
129
|
+
/* gp_image_cov(...) additionally fills cov[npair][nt] for pairs (pa[p], pb[p]) of grid wavelengths */
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
See `c/examples/example.c` and the C API reference in `docs/c_api.rst`.
|
|
133
|
+
|
|
134
|
+
## Performance and accuracy
|
|
135
|
+
|
|
136
|
+
Single core, Intel Core Ultra 7 255U; simulated LSST light curves (details in `docs/guide/performance.rst` and
|
|
137
|
+
`docs/guide/accuracy.rst`).
|
|
138
|
+
|
|
139
|
+
| likelihood + gradient | gpimg | dense GP (tinygp, warm) | smolgp, same model (warm) |
|
|
140
|
+
|---|---|---|---|
|
|
141
|
+
| 1 000 points | 0.20 ms | 165 ms | 12 ms |
|
|
142
|
+
| 12 000 points | 2.8 ms | 242 s | 0.27 s |
|
|
143
|
+
| 18 668 points | 4.7 ms | — | 0.41 s |
|
|
144
|
+
|
|
145
|
+
| median per fit | DDF (~660 points) | WFD (~64 points) |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| gpimg, 5 starts | 18.7 ms | 1.7 ms |
|
|
148
|
+
| PISCOLA as shipped | 4.95 s | 2.17 s |
|
|
149
|
+
|
|
150
|
+
Against a dense double-precision GP with the same hyperparameters: likelihood ≤ 3.5e-11, gradient ≤ 8.4e-9 and
|
|
151
|
+
posterior mean ≤ 1.1e-10 (relative). With `smoother="rts"` the posterior variance agrees with a 200-bit reference
|
|
152
|
+
to 7e-10 at the grid points where the default smoother is worst (4.8e-3).
|
|
153
|
+
|
|
154
|
+
## Citing
|
|
155
|
+
|
|
156
|
+
A paper describing gpimg is in preparation (ApJ Letters). Until then please cite the software and the works in the
|
|
157
|
+
references (`docs/references.rst`), in particular Hartikainen & Särkkä (2010) for
|
|
158
|
+
the state-space formulation of temporal Gaussian processes.
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
MIT — see [LICENSE](LICENSE).
|
gpimg-0.1.0/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# gpimg
|
|
2
|
+
|
|
3
|
+
**Exact O(n) two-dimensional Gaussian processes for multi-band light curves.**
|
|
4
|
+
|
|
5
|
+
gpimg fits a Gaussian process jointly in time and wavelength to a multi-band light curve and returns the posterior
|
|
6
|
+
flux on any time × wavelength grid. The kernel is a Matérn-3/2 in time times a squared exponential in ln λ:
|
|
7
|
+
|
|
8
|
+
k((t,λ),(t',λ')) = A² (1 + √3|t−t'|/ℓt) exp(−√3|t−t'|/ℓt) · exp(−(ln λ − ln λ')² / 2ℓλ²)
|
|
9
|
+
|
|
10
|
+
Because the time kernel is a linear stochastic differential equation and the kernel is separable, a light curve
|
|
11
|
+
observed in up to six bands is *exactly* a small linear Gaussian state-space model. gpimg evaluates the likelihood,
|
|
12
|
+
its analytic gradient, maximum-likelihood fits and posterior images with Kalman filters and smoothers in **O(n)**,
|
|
13
|
+
with no approximation.
|
|
14
|
+
|
|
15
|
+
- Exact: likelihoods agree with a dense Cholesky GP to ~1e-11 (relative).
|
|
16
|
+
- Fast: one likelihood + gradient of an 18 668-point light curve in 4.7 ms on one core; a fit of a typical
|
|
17
|
+
deep-drilling LSST light curve (~660 points) in ~19 ms with five starts — 279× faster than PISCOLA's GP fit, and
|
|
18
|
+
1 100× faster for wide-fast-deep light curves (~64 points).
|
|
19
|
+
- Compiled C core, no JIT and no warm-up; AVX2 + FMA code selected at run time; OpenMP batches.
|
|
20
|
+
- Posteriors at any wavelength, smoothed or causal (real time), with an optional numerically stable
|
|
21
|
+
Rauch–Tung–Striebel smoother, and exact band–band covariances for colors.
|
|
22
|
+
- Optional fitted jitter for scatter the quoted errors do not describe; off by default, and off costs nothing.
|
|
23
|
+
- Python package and plain C library (Makefile, CMake, pkg-config).
|
|
24
|
+
|
|
25
|
+
Documentation: the Sphinx sources under `docs/` (guide, Python API, C API, theory). A hosted build is not up yet.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```console
|
|
30
|
+
$ pip install gpimg
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
gpimg ships as a source distribution, so this compiles the C core for your machine: you need a C compiler (gcc or
|
|
34
|
+
clang). OpenMP is optional — without it `gpimg.batch` runs serially and everything else is unaffected. An AVX2 +
|
|
35
|
+
FMA copy is built alongside the portable one and chosen at import when the CPU supports it.
|
|
36
|
+
|
|
37
|
+
From a source checkout, which also gets you the plain C library:
|
|
38
|
+
|
|
39
|
+
```console
|
|
40
|
+
$ pip install . # the Python package
|
|
41
|
+
$ pytest # optional: pip install ".[test]" first
|
|
42
|
+
$ make -C c && make -C c test # the C library: build/libgpimg.so, build/libgpimg.a
|
|
43
|
+
$ sudo make -C c install # or: cmake -S c -B build && cmake --build build
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Python quick start
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import numpy as np
|
|
50
|
+
import gpimg
|
|
51
|
+
|
|
52
|
+
# t [days], band ('u','g','r','i','z','y' or 0..5; LSST by default), flux and flux_err in any flux unit
|
|
53
|
+
gp = gpimg.GP(t, band, flux, flux_err)
|
|
54
|
+
res = gp.fit() # maximum likelihood, 5 starting points
|
|
55
|
+
print(res.amplitude, res.length_time, res.length_wave, res.message)
|
|
56
|
+
res = gp.fit(jitter=True) # + a white jitter for extra scatter; res.jitter
|
|
57
|
+
|
|
58
|
+
img = gp.predict(np.linspace(-30, 120, 300), # times [d]
|
|
59
|
+
np.geomspace(3200, 10200, 200)) # wavelengths [Å]
|
|
60
|
+
img.mean.shape, img.std.shape # (200, 300): wavelengths x times
|
|
61
|
+
|
|
62
|
+
curves = gp.predict_bands(np.linspace(-30, 120, 300)) # {'u': (mean, std), ...}
|
|
63
|
+
curves, covs = gp.predict_bands(t_grid, cov=True) # + {('g','r'): cov, ...} for color errors
|
|
64
|
+
live = gp.predict(t_grid, causal=True) # filtered: data up to each time only
|
|
65
|
+
stable = gp.predict(t_grid, wave_grid, smoother="rts") # numerically stable smoother
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Many light curves from one long table (pandas, astropy, dict of arrays), fitted and imaged in parallel:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
lcs = gpimg.LightCurves.from_table(table, id="oid", t="t", band="band", flux="flux", flux_err="flux_err")
|
|
72
|
+
res = gpimg.batch(lcs, np.linspace(-30, 120, 300), np.geomspace(3200, 10200, 200))
|
|
73
|
+
res.mean.shape # (n_objects, 200, 300), float32
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Other surveys: `gpimg.GP(t, band, flux, err, wavelengths={"g": 4800.0, "r": 6400.0, "i": 7900.0})`.
|
|
77
|
+
|
|
78
|
+
Runnable examples are in `examples/` (`quickstart.py`, `batch_table.py`, `causal_vs_smoothed.py`,
|
|
79
|
+
`other_survey.py`).
|
|
80
|
+
|
|
81
|
+
## C quick start
|
|
82
|
+
|
|
83
|
+
```c
|
|
84
|
+
#include "gpimg.h"
|
|
85
|
+
|
|
86
|
+
double lnwave[6]; /* ln of the band wavelengths */
|
|
87
|
+
gp_fit_opts opts;
|
|
88
|
+
gp_fit_default_opts(&opts);
|
|
89
|
+
opts.nstart = 5;
|
|
90
|
+
gp_fit_result res;
|
|
91
|
+
gp_fit(n, t, band, y, err, lnwave, theta0, &opts, &res); /* res.theta = (ln A, ln lt, ln ll) */
|
|
92
|
+
gp_image(n, t, band, y, err, 6, lnwave, res.theta, nt, tg, nl, lng, mean, var, GPIMG_SMOOTH(GPIMG_RTS));
|
|
93
|
+
/* gp_image_cov(...) additionally fills cov[npair][nt] for pairs (pa[p], pb[p]) of grid wavelengths */
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
See `c/examples/example.c` and the C API reference in `docs/c_api.rst`.
|
|
97
|
+
|
|
98
|
+
## Performance and accuracy
|
|
99
|
+
|
|
100
|
+
Single core, Intel Core Ultra 7 255U; simulated LSST light curves (details in `docs/guide/performance.rst` and
|
|
101
|
+
`docs/guide/accuracy.rst`).
|
|
102
|
+
|
|
103
|
+
| likelihood + gradient | gpimg | dense GP (tinygp, warm) | smolgp, same model (warm) |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| 1 000 points | 0.20 ms | 165 ms | 12 ms |
|
|
106
|
+
| 12 000 points | 2.8 ms | 242 s | 0.27 s |
|
|
107
|
+
| 18 668 points | 4.7 ms | — | 0.41 s |
|
|
108
|
+
|
|
109
|
+
| median per fit | DDF (~660 points) | WFD (~64 points) |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| gpimg, 5 starts | 18.7 ms | 1.7 ms |
|
|
112
|
+
| PISCOLA as shipped | 4.95 s | 2.17 s |
|
|
113
|
+
|
|
114
|
+
Against a dense double-precision GP with the same hyperparameters: likelihood ≤ 3.5e-11, gradient ≤ 8.4e-9 and
|
|
115
|
+
posterior mean ≤ 1.1e-10 (relative). With `smoother="rts"` the posterior variance agrees with a 200-bit reference
|
|
116
|
+
to 7e-10 at the grid points where the default smoother is worst (4.8e-3).
|
|
117
|
+
|
|
118
|
+
## Citing
|
|
119
|
+
|
|
120
|
+
A paper describing gpimg is in preparation (ApJ Letters). Until then please cite the software and the works in the
|
|
121
|
+
references (`docs/references.rst`), in particular Hartikainen & Särkkä (2010) for
|
|
122
|
+
the state-space formulation of temporal Gaussian processes.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(gpimg VERSION 0.1.0 LANGUAGES C)
|
|
3
|
+
|
|
4
|
+
# gpimg C library. Usage:
|
|
5
|
+
# cmake -S c -B build -DCMAKE_BUILD_TYPE=Release [-DGPIMG_NATIVE=ON] && cmake --build build && ctest --test-dir build
|
|
6
|
+
# In another CMake project: add_subdirectory(gpimg/c) or find_package(gpimg) after installation, then
|
|
7
|
+
# target_link_libraries(myapp PRIVATE gpimg::gpimg)
|
|
8
|
+
|
|
9
|
+
option(GPIMG_OPENMP "Parallel gp_batch with OpenMP" ON)
|
|
10
|
+
option(GPIMG_NATIVE "Optimise for the build machine (-march=native)" OFF)
|
|
11
|
+
option(BUILD_SHARED_LIBS "Build a shared library" ON)
|
|
12
|
+
|
|
13
|
+
set(CMAKE_C_STANDARD 11)
|
|
14
|
+
set(CMAKE_C_EXTENSIONS ON)
|
|
15
|
+
if(NOT CMAKE_BUILD_TYPE)
|
|
16
|
+
set(CMAKE_BUILD_TYPE Release)
|
|
17
|
+
endif()
|
|
18
|
+
|
|
19
|
+
add_library(gpimg src/gpimg.c)
|
|
20
|
+
add_library(gpimg::gpimg ALIAS gpimg)
|
|
21
|
+
target_include_directories(gpimg PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
22
|
+
$<INSTALL_INTERFACE:include>)
|
|
23
|
+
set_target_properties(gpimg PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 0 POSITION_INDEPENDENT_CODE ON)
|
|
24
|
+
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
|
|
25
|
+
# IEEE semantics are kept (no -ffast-math); FMA contraction is allowed
|
|
26
|
+
target_compile_options(gpimg PRIVATE -O3 -fno-math-errno -ffp-contract=fast -Wall -Wextra)
|
|
27
|
+
if(GPIMG_NATIVE)
|
|
28
|
+
target_compile_options(gpimg PRIVATE -march=native)
|
|
29
|
+
endif()
|
|
30
|
+
endif()
|
|
31
|
+
find_library(MATH_LIBRARY m)
|
|
32
|
+
if(MATH_LIBRARY)
|
|
33
|
+
target_link_libraries(gpimg PUBLIC ${MATH_LIBRARY})
|
|
34
|
+
endif()
|
|
35
|
+
if(GPIMG_OPENMP)
|
|
36
|
+
find_package(OpenMP COMPONENTS C)
|
|
37
|
+
if(OpenMP_C_FOUND)
|
|
38
|
+
target_link_libraries(gpimg PUBLIC OpenMP::OpenMP_C)
|
|
39
|
+
endif()
|
|
40
|
+
endif()
|
|
41
|
+
|
|
42
|
+
add_executable(gpimg_example examples/example.c)
|
|
43
|
+
target_link_libraries(gpimg_example PRIVATE gpimg)
|
|
44
|
+
|
|
45
|
+
enable_testing()
|
|
46
|
+
add_executable(test_gpimg tests/test_gpimg.c)
|
|
47
|
+
target_link_libraries(test_gpimg PRIVATE gpimg)
|
|
48
|
+
add_test(NAME test_gpimg COMMAND test_gpimg)
|
|
49
|
+
|
|
50
|
+
include(GNUInstallDirs)
|
|
51
|
+
install(TARGETS gpimg EXPORT gpimgTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
52
|
+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
53
|
+
install(FILES include/gpimg.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
|
54
|
+
install(EXPORT gpimgTargets NAMESPACE gpimg:: FILE gpimgConfig.cmake
|
|
55
|
+
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/gpimg)
|
gpimg-0.1.0/c/Makefile
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# gpimg C library: exact O(n) 2D Gaussian processes for multi-band light curves.
|
|
2
|
+
#
|
|
3
|
+
# make shared + static library in build/ (libgpimg.so / .dylib, libgpimg.a)
|
|
4
|
+
# make example build/example (fit + image of a synthetic light curve)
|
|
5
|
+
# make test build/test_gpimg, run it (likelihood vs dense Cholesky, gradients, smoothers)
|
|
6
|
+
# make install PREFIX=/usr/local by default: lib/, include/gpimg.h, lib/pkgconfig/gpimg.pc
|
|
7
|
+
#
|
|
8
|
+
# Variables: CC (default cc), ARCH (e.g. ARCH=-march=native for the fastest build on this machine),
|
|
9
|
+
# OPENMP=0 to build without OpenMP (gp_batch then runs serially), PREFIX, DESTDIR.
|
|
10
|
+
CC ?= cc
|
|
11
|
+
ARCH ?=
|
|
12
|
+
OPENMP ?= 1
|
|
13
|
+
PREFIX ?= /usr/local
|
|
14
|
+
VERSION := 0.1.0
|
|
15
|
+
|
|
16
|
+
UNAME := $(shell uname -s)
|
|
17
|
+
ifeq ($(UNAME),Darwin)
|
|
18
|
+
SHLIB := libgpimg.dylib
|
|
19
|
+
SHFLAGS := -dynamiclib -install_name $(PREFIX)/lib/$(SHLIB)
|
|
20
|
+
else
|
|
21
|
+
SHLIB := libgpimg.so
|
|
22
|
+
SHFLAGS := -shared -Wl,-soname,libgpimg.so.0
|
|
23
|
+
endif
|
|
24
|
+
|
|
25
|
+
# IEEE semantics are kept (no -ffast-math); FMA contraction is allowed.
|
|
26
|
+
CFLAGS_BASE := -O3 $(ARCH) -fno-math-errno -ffp-contract=fast -fPIC -std=gnu11 -Wall -Wextra -Iinclude
|
|
27
|
+
ifeq ($(OPENMP),1)
|
|
28
|
+
OMPFLAGS := -fopenmp
|
|
29
|
+
endif
|
|
30
|
+
CFLAGS_ALL := $(CFLAGS_BASE) $(OMPFLAGS) $(CFLAGS)
|
|
31
|
+
LDLIBS_ALL := $(OMPFLAGS) -lm
|
|
32
|
+
|
|
33
|
+
B := build
|
|
34
|
+
|
|
35
|
+
all: $(B)/$(SHLIB) $(B)/libgpimg.a
|
|
36
|
+
|
|
37
|
+
$(B):
|
|
38
|
+
mkdir -p $(B)
|
|
39
|
+
|
|
40
|
+
$(B)/gpimg.o: src/gpimg.c include/gpimg.h | $(B)
|
|
41
|
+
$(CC) $(CFLAGS_ALL) -c $< -o $@
|
|
42
|
+
|
|
43
|
+
$(B)/$(SHLIB): $(B)/gpimg.o
|
|
44
|
+
$(CC) $(SHFLAGS) $< -o $@ $(LDLIBS_ALL) $(LDFLAGS)
|
|
45
|
+
|
|
46
|
+
$(B)/libgpimg.a: $(B)/gpimg.o
|
|
47
|
+
$(AR) rcs $@ $<
|
|
48
|
+
|
|
49
|
+
$(B)/example: examples/example.c $(B)/libgpimg.a
|
|
50
|
+
$(CC) $(CFLAGS_ALL) $< $(B)/libgpimg.a -o $@ $(LDLIBS_ALL) $(LDFLAGS)
|
|
51
|
+
|
|
52
|
+
$(B)/test_gpimg: tests/test_gpimg.c $(B)/libgpimg.a
|
|
53
|
+
$(CC) $(CFLAGS_ALL) $< $(B)/libgpimg.a -o $@ $(LDLIBS_ALL) $(LDFLAGS)
|
|
54
|
+
|
|
55
|
+
example: $(B)/example
|
|
56
|
+
./$(B)/example
|
|
57
|
+
|
|
58
|
+
test: $(B)/test_gpimg
|
|
59
|
+
./$(B)/test_gpimg
|
|
60
|
+
|
|
61
|
+
$(B)/gpimg.pc: | $(B)
|
|
62
|
+
printf 'prefix=$(PREFIX)\nlibdir=$${prefix}/lib\nincludedir=$${prefix}/include\n\nName: gpimg\nDescription: Exact O(n) 2D Gaussian processes for multi-band light curves\nVersion: $(VERSION)\nLibs: -L$${libdir} -lgpimg\nLibs.private: $(OMPFLAGS) -lm\nCflags: -I$${includedir}\n' > $@
|
|
63
|
+
|
|
64
|
+
install: all $(B)/gpimg.pc
|
|
65
|
+
install -d $(DESTDIR)$(PREFIX)/lib $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib/pkgconfig
|
|
66
|
+
install -m 644 include/gpimg.h $(DESTDIR)$(PREFIX)/include/
|
|
67
|
+
install -m 755 $(B)/$(SHLIB) $(DESTDIR)$(PREFIX)/lib/
|
|
68
|
+
install -m 644 $(B)/libgpimg.a $(DESTDIR)$(PREFIX)/lib/
|
|
69
|
+
install -m 644 $(B)/gpimg.pc $(DESTDIR)$(PREFIX)/lib/pkgconfig/
|
|
70
|
+
ifneq ($(UNAME),Darwin)
|
|
71
|
+
ln -sf $(SHLIB) $(DESTDIR)$(PREFIX)/lib/libgpimg.so.0
|
|
72
|
+
endif
|
|
73
|
+
|
|
74
|
+
uninstall:
|
|
75
|
+
rm -f $(DESTDIR)$(PREFIX)/include/gpimg.h $(DESTDIR)$(PREFIX)/lib/$(SHLIB) $(DESTDIR)$(PREFIX)/lib/libgpimg.so.0 \
|
|
76
|
+
$(DESTDIR)$(PREFIX)/lib/libgpimg.a $(DESTDIR)$(PREFIX)/lib/pkgconfig/gpimg.pc
|
|
77
|
+
|
|
78
|
+
clean:
|
|
79
|
+
rm -rf $(B)
|
|
80
|
+
|
|
81
|
+
.PHONY: all example test install uninstall clean
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* example.c -- fit and image a synthetic six-band light curve with the gpimg C library.
|
|
2
|
+
*
|
|
3
|
+
* make -C c example (or: cc -O2 example.c -Iinclude -Lbuild -lgpimg -lm -fopenmp)
|
|
4
|
+
*
|
|
5
|
+
* Times in days, wavelengths in Angstrom (passed as natural logs), fluxes in any unit.
|
|
6
|
+
*/
|
|
7
|
+
#include <math.h>
|
|
8
|
+
#include <stdint.h>
|
|
9
|
+
#include <stdio.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
|
|
12
|
+
#include "gpimg.h"
|
|
13
|
+
|
|
14
|
+
int main(void)
|
|
15
|
+
{
|
|
16
|
+
/* LSST ugrizy effective wavelengths -> ln(lambda) */
|
|
17
|
+
const double wave[6] = {3671.0, 4827.0, 6223.0, 7546.0, 8691.0, 9712.0};
|
|
18
|
+
double lnwave[6];
|
|
19
|
+
for (int b = 0; b < 6; b++) lnwave[b] = log(wave[b]);
|
|
20
|
+
|
|
21
|
+
/* a synthetic transient: rise and decline, redder bands peak later, observed every ~3 days in one band */
|
|
22
|
+
enum { N = 120 };
|
|
23
|
+
double t[N], y[N], err[N];
|
|
24
|
+
int32_t band[N];
|
|
25
|
+
srand(1);
|
|
26
|
+
for (int i = 0; i < N; i++) {
|
|
27
|
+
t[i] = -20.0 + 1.0 * i + 0.5 * rand() / (double)RAND_MAX;
|
|
28
|
+
band[i] = i % 6;
|
|
29
|
+
const double tp = 1.0 * band[i], x = t[i] - tp; /* peak time: one day later per band */
|
|
30
|
+
const double f = 1000.0 * exp(-x / 25.0) / (1.0 + exp(-x / 3.0));
|
|
31
|
+
err[i] = 20.0;
|
|
32
|
+
y[i] = f + err[i] * (2.0 * rand() / (double)RAND_MAX - 1.0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* maximum-likelihood fit: theta = (ln A, ln l_t, ln l_lambda) */
|
|
36
|
+
gp_fit_opts opts;
|
|
37
|
+
gp_fit_default_opts(&opts);
|
|
38
|
+
opts.nstart = 5;
|
|
39
|
+
const double theta0[3] = {log(1000.0), log(20.0), log(0.8)};
|
|
40
|
+
gp_fit_result res;
|
|
41
|
+
gp_fit(N, t, band, y, err, lnwave, theta0, &opts, &res);
|
|
42
|
+
printf("fit: A = %.1f, l_t = %.2f d, l_lambda = %.3f (ln lambda); -ln L = %.3f; %d iterations, status %d\n",
|
|
43
|
+
exp(res.theta[0]), exp(res.theta[1]), exp(res.theta[2]), res.nll, res.nit, res.status);
|
|
44
|
+
|
|
45
|
+
/* likelihood and its analytic gradient at the optimum */
|
|
46
|
+
double grad[3];
|
|
47
|
+
const double nll = gp_nll_grad(N, t, band, y, err, lnwave, 3, res.theta, grad);
|
|
48
|
+
printf("-ln L = %.6f, gradient = (%.2e, %.2e, %.2e)\n", nll, grad[0], grad[1], grad[2]);
|
|
49
|
+
|
|
50
|
+
/* posterior image on 100 times x 50 wavelengths, smoothed (MBF) and with the stable RTS smoother */
|
|
51
|
+
enum { NT = 100, NL = 50 };
|
|
52
|
+
double tg[NT], lng[NL];
|
|
53
|
+
for (int g = 0; g < NT; g++) tg[g] = -30.0 + 130.0 * g / (NT - 1);
|
|
54
|
+
for (int l = 0; l < NL; l++) lng[l] = log(3200.0) + (log(10200.0) - log(3200.0)) * l / (NL - 1);
|
|
55
|
+
double *mean = malloc(sizeof(double) * NL * NT), *var = malloc(sizeof(double) * NL * NT);
|
|
56
|
+
const int rank = gp_image(N, t, band, y, err, 6, lnwave, 3, res.theta, NT, tg, NL, lng, mean, var,
|
|
57
|
+
GPIMG_SMOOTH(GPIMG_RTS));
|
|
58
|
+
const int l = NL / 2, g = NT / 2;
|
|
59
|
+
printf("image (rank %d): at t = %.1f d, lambda = %.0f A: flux = %.1f +- %.1f\n", rank, tg[g], exp(lng[l]),
|
|
60
|
+
mean[l * NT + g], sqrt(var[l * NT + g]));
|
|
61
|
+
|
|
62
|
+
/* the same column as known in real time: filtered (causal) posterior */
|
|
63
|
+
gp_image(N, t, band, y, err, 6, lnwave, 3, res.theta, NT, tg, NL, lng, mean, var, GPIMG_CAUSAL);
|
|
64
|
+
printf("causal image at the same point: flux = %.1f +- %.1f\n", mean[l * NT + g], sqrt(var[l * NT + g]));
|
|
65
|
+
free(mean);
|
|
66
|
+
free(var);
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* gpimg: exact O(n) two-dimensional Gaussian-process fits and images for multi-band light curves.
|
|
2
|
+
*
|
|
3
|
+
* Kernel
|
|
4
|
+
* k((t,x),(t',x')) = A^2 (1 + sqrt3|dt|/lt) exp(-sqrt3|dt|/lt) exp(-(x-x')^2 / (2 ll^2)), x = ln(lambda)
|
|
5
|
+
* zero mean, measurement variances err^2 on the diagonal. Hyperparameters theta = (ln A, ln lt, ln ll).
|
|
6
|
+
*
|
|
7
|
+
* Optional jitter. Every function taking theta also takes ntheta: 3 for the kernel above, or 4 to add a white
|
|
8
|
+
* jitter variance j^2 = exp(2 theta[3]) to every measurement variance -- extra scatter beyond the quoted errors,
|
|
9
|
+
* fitted like any other hyperparameter (analytic gradient, bounds opts->lo[3]/hi[3], opts->ntheta = 4). It is
|
|
10
|
+
* optional in the strict sense: ntheta = 3 never reads theta[3] and costs nothing -- the likelihood, its gradient
|
|
11
|
+
* and the whole image path are bit-identical to the three-parameter library (gp_fit lands on the same optimum to
|
|
12
|
+
* ~1e-8 in theta, far inside its own pgtol, since a BFGS iterate path is not bit-reproducible across builds).
|
|
13
|
+
* j is in the flux unit of y, so scale its bounds to your data.
|
|
14
|
+
*
|
|
15
|
+
* The Matern-3/2 time kernel is a 2-state linear SDE and the kernel is separable, so the GP observed in B <= 6
|
|
16
|
+
* bands is an exact 2B-state linear Gaussian state-space model: the Kalman filter gives the exact likelihood, a
|
|
17
|
+
* smoother the exact posterior, and any wavelength follows exactly from the band processes. No approximation is made.
|
|
18
|
+
*
|
|
19
|
+
* Inputs need not be time-sorted. band[i] in 0..nband_tot-1 indexes lnwave[]. Times in any unit consistent with
|
|
20
|
+
* lt (days in the Python package). All functions are re-entrant (no global state) and thread-safe.
|
|
21
|
+
*/
|
|
22
|
+
#ifndef GPIMG_H
|
|
23
|
+
#define GPIMG_H
|
|
24
|
+
#include <stdint.h>
|
|
25
|
+
|
|
26
|
+
#ifdef __cplusplus
|
|
27
|
+
extern "C" {
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#define GPIMG_VERSION "0.1.0"
|
|
31
|
+
#define GPIMG_MAXB 6
|
|
32
|
+
#define GPIMG_MAXTHETA 4 /* (ln A, ln lt, ln ll) and the optional ln jitter */
|
|
33
|
+
#define GPIMG_NINFO 6 /* per-object info: nll, nit, nfev, status, t_fit [s], t_image [s] */
|
|
34
|
+
|
|
35
|
+
/* image mode: GPIMG_CAUSAL (filtered posteriors) or a smoother, e.g. GPIMG_SMOOTH(GPIMG_RTS) */
|
|
36
|
+
#define GPIMG_CAUSAL 1
|
|
37
|
+
#define GPIMG_MBF 0 /* modified Bryson-Frazier: inversion-free, fastest (default) */
|
|
38
|
+
#define GPIMG_RTS 1 /* Rauch-Tung-Striebel, Joseph form: numerically stable */
|
|
39
|
+
#define GPIMG_RTS_PLAIN 2 /* Rauch-Tung-Striebel, textbook form */
|
|
40
|
+
#define GPIMG_SMOOTH(s) ((s) << 1)
|
|
41
|
+
#define GPIMG_SMOOTHER(mode) (((mode) >> 1) & 3)
|
|
42
|
+
|
|
43
|
+
/* negative log marginal likelihood (incl. 0.5 n ln 2pi) and, if grad != NULL, its gradient wrt theta */
|
|
44
|
+
double gp_nll_grad(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
45
|
+
const double *lnwave, int ntheta, const double *theta, double *grad);
|
|
46
|
+
|
|
47
|
+
/* testing: gradient by reverse mode (adjoint) and by forward mode; gnoise = sum_i err_i^2 dL/d(err_i^2) */
|
|
48
|
+
/* grad_fwd[3] (the jitter) is returned as NaN: the forward tangents cover the three kernel parameters. */
|
|
49
|
+
double gp_nll_grad_check(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
50
|
+
const double *lnwave, int ntheta, const double *theta, double *grad_adj,
|
|
51
|
+
double *grad_fwd, double *gnoise);
|
|
52
|
+
|
|
53
|
+
/* fit options / result */
|
|
54
|
+
typedef struct {
|
|
55
|
+
double lo[GPIMG_MAXTHETA], hi[GPIMG_MAXTHETA]; /* bounds on theta; [3] read only when ntheta = 4 */
|
|
56
|
+
double pgtol; /* stop when max |projected gradient| <= pgtol */
|
|
57
|
+
double ftol; /* stop when (f_old - f) <= ftol * max(|f|, 1) */
|
|
58
|
+
int maxiter;
|
|
59
|
+
int nstart; /* 1: start at theta0 only. k > 1: also the first k-1 points of a fixed design around
|
|
60
|
+
theta0 (GPIMG_NDESIGN max); keep the lowest -lnL (multimodal likelihoods) */
|
|
61
|
+
int ntheta; /* 3 (default) or 4: fit the jitter too. theta0 and res.theta have this many entries */
|
|
62
|
+
} gp_fit_opts;
|
|
63
|
+
|
|
64
|
+
#define GPIMG_NDESIGN 18
|
|
65
|
+
|
|
66
|
+
typedef struct {
|
|
67
|
+
double theta[GPIMG_MAXTHETA]; /* opts->ntheta entries are written */
|
|
68
|
+
double nll;
|
|
69
|
+
double pgnorm;
|
|
70
|
+
int nit, nfev, status; /* status: 0 pgtol, 1 ftol, 2 maxiter, 3 line search failed */
|
|
71
|
+
} gp_fit_result;
|
|
72
|
+
|
|
73
|
+
void gp_fit_default_opts(gp_fit_opts *o);
|
|
74
|
+
|
|
75
|
+
/* maximum-likelihood fit starting at theta0 (projected onto the bounds) */
|
|
76
|
+
void gp_fit(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
77
|
+
const double *lnwave, const double *theta0, const gp_fit_opts *opts, gp_fit_result *res);
|
|
78
|
+
|
|
79
|
+
/* posterior mean and variance of the noise-free flux on the grid tg[nt] x lng[nl] (ln lambda); tg must be sorted
|
|
80
|
+
* ascending. Out arrays are row-major [nl][nt] (wavelength rows, time columns). nband_tot: bands in lnwave (<= 6).
|
|
81
|
+
* mode: see GPIMG_CAUSAL / GPIMG_SMOOTH above (0 = smoothed, MBF). Returns the latent rank used. */
|
|
82
|
+
int gp_image(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
83
|
+
int nband_tot, const double *lnwave, int ntheta, const double *theta,
|
|
84
|
+
int nt, const double *tg, int nl, const double *lng, double *mean, double *var, int mode);
|
|
85
|
+
|
|
86
|
+
/* As gp_image, plus the same-time posterior covariance of pairs of grid wavelengths:
|
|
87
|
+
* cov[p * nt + g] = cov(f(tg[g], lng[pa[p]]), f(tg[g], lng[pb[p]])), p = 0..npair-1.
|
|
88
|
+
* pa/pb index lng[] and are NOT range-checked; pa[p] == pb[p] reproduces that wavelength's variance. cov is never
|
|
89
|
+
* clamped (a covariance may be negative). npair = 0 or cov = NULL behaves exactly like gp_image. Cost: O(npair nt)
|
|
90
|
+
* on top of the image, with no extra filter or smoother pass. */
|
|
91
|
+
int gp_image_cov(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
92
|
+
int nband_tot, const double *lnwave, int ntheta, const double *theta,
|
|
93
|
+
int nt, const double *tg, int nl, const double *lng, double *mean, double *var,
|
|
94
|
+
int npair, const int32_t *pa, const int32_t *pb, double *cov, int mode);
|
|
95
|
+
|
|
96
|
+
/* nll computed through the latent (image) model: cross-check of the two state-space formulations */
|
|
97
|
+
double gp_nll_latent(int n, const double *t, const int32_t *band, const double *y, const double *err,
|
|
98
|
+
int nband_tot, const double *lnwave, int ntheta, const double *theta);
|
|
99
|
+
|
|
100
|
+
/* batch: objects o = 0..nobj-1 own rows off[o]..off[o+1]-1. Fits (if fit != 0, starting at theta0[o]) and
|
|
101
|
+
* makes images for every object with OpenMP. theta0/theta_out are [nobj][opts->ntheta].
|
|
102
|
+
* Outputs float32 mean/var [nobj][nl][nt], theta_out [nobj][ntheta],
|
|
103
|
+
* info [nobj][GPIMG_NINFO] = (nll, nit, nfev, status, t_fit, t_image). nthreads <= 0: OpenMP default. */
|
|
104
|
+
void gp_batch(int nobj, const int64_t *off, const double *t, const int32_t *band, const double *y,
|
|
105
|
+
const double *err, int nband_tot, const double *lnwave, const double *theta0, int fit,
|
|
106
|
+
const gp_fit_opts *opts, int nt, const double *tg, int nl, const double *lng,
|
|
107
|
+
float *mean, float *var, double *theta_out, double *info, int mode, int nthreads);
|
|
108
|
+
|
|
109
|
+
#ifdef __cplusplus
|
|
110
|
+
}
|
|
111
|
+
#endif
|
|
112
|
+
|
|
113
|
+
#endif
|