Skip to content

Add sampled multiband template fitting (CUDA and Rust) - #8

Merged
mcoughlin merged 1 commit into
mainfrom
template-fit-sampled
Sep 18, 2026
Merged

mcoughlin merged 1 commit into
mainfrom
template-fit-sampled

Conversation

@zerozole

Copy link
Copy Markdown
Collaborator

Add sampled multiband template fitting (CUDA and Rust)

Adds TemplateFitSampled on both backends, reachable through the device API
like the other algorithms.

What it does

Fits a bank of physical templates to a multiband light curve at each of its own
trial periods and returns the single best (period, template, phase, amplitude). Not a periodogram: the candidate periods come from one, and this
chooses among them using a model of the class.

The model at trial period P, for band b:

mag_b(t) = offset_b + a * S[k, b](t/P - phi)

The offset is free per band and a is one amplitude shared across all bands,
so the band amplitude ratios are a constraint the fit has to respect and not a
free parameter each. Score is the fraction of variance unexplained, pooled over
bands.

Templates are samples on a phase grid; folding the light curve onto that same
grid makes every sum the score needs a circular correlation, so one transform
gives the score at all phase shifts at once.

Timing

Measured on one A100, each object fitted at ~200 trial periods over 512 phase
shifts. Cost is linear in bank size, about 0.11 ms per template per object:

templates per object
12 2.7 ms
27 3.0 ms
54 4.3 ms
107 10.5 ms
360 41.2 ms
820 92.6 ms

The Rust backend on 8 cores takes 3.53 s per object for the 820 template bank,
so the GPU is 38x faster on the same fit.

Accuracy

Rubin DP2, 613 objects with published periods from VSX and other catalogues,
each fitted against the bank of its own class only. The banks come from three
generators, none of them part of this library:

  • MESA-RSP, nonlinear radial pulsation models: RR Lyrae ab and c, Cepheid,
    Cepheid type-II, Delta Scuti.
  • phoebe-rs, Roche geometry eclipsing binary synthesis: EA, EB, EW.
  • starry-rust, spotted rotating stars: RS CVn.

Exact means within 2 per cent of the published period:

class n exact with harmonics median fvu
EW 107 96% 96% 0.052
EA 22 68% 86% 0.083
EB 3 100% 100% 0.088
Delta Scu 32 75% 75% 0.507
RR Lyrae c 123 59% 60% 0.175
RR Lyrae ab 150 51% 56% 0.117
Cepheid 11 45% 55% 0.328
Cepheid type-II 15 33% 33% 0.324
RS CVn 150 9% 12% 0.851

The harmonic column counts a factor of two or three as recovered. It matters
only for eclipsing binaries, where the light curve genuinely repeats at half
the orbital period, and EA goes from 68 to 86 per cent on that basis.

The same objects and the same banks, fitted with templates truncated to eleven
Fourier coefficients instead of sampled, give EA 55 per cent against 68 and
Delta Scu 69 against 75, with the smooth classes unchanged. That is the case
for holding templates as samples: it buys accuracy exactly where a truncated
series cannot represent the shape.

Double precision

f64 end to end. The score is an argmin over n_template * n_phase nearly tied
columns and folds a long baseline at short periods; in single precision a
different column wins.

That is also why dblatomic.cuh is new. atomicAdd on double is native only
from compute capability 6.0 and setup.py compiles from compute_50, so the
older targets need the documented compare-and-swap fallback. Accumulating in
float, as the existing kernels do, is not an option here.

Validation

The CPU and GPU backends were run on the same 22 light curves against an 820
template bank: identical period, template and phase shift on all 22, with fvu
agreeing to 7e-11. The Rust was separately checked against an independent numpy
implementation, also identical.

Tests: 8 Rust unit tests in tfs.rs, 7 pytest in
tests/test_template_fit_sampled.py. Both build templates analytically, so no
data files are added.

No bank ships

The kernel takes samples from the caller, so the library carries no template
data. docs/user-guide/template-banks.md documents the array contract, how to
build a bank, and how to choose the phase grid.

@mcoughlin mcoughlin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mcoughlin
mcoughlin merged commit 76a437d into main Sep 18, 2026
10 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants