Summary
The "streak" rate-fitting path is really the model for shift-and-stack measurements (shift each exposure by an assumed motion, coadd; the best rate pair focuses the flux into a PSF). Such a detection yields a joint estimate of position and rate from the same photons, so the two are correlated. layup currently weights the position and rate rows with a strictly diagonal weight matrix, which drops those correlations. This issue records the model and the interim guidance; a fuller treatment is future work.
Measurement model
Shift-and-stack fits θ(t) = θ₀ + ω·(t − t_ref) to the exposures, giving the focused-PSF position θ₀ at t_ref and the rate ω jointly — an intercept + slope estimate over the exposure epochs. Its covariance is the usual linear-fit one:
- Cov(θ₀, ω) = 0 iff
t_ref is the (SNR-weighted) time centroid of the exposures. Off-centroid, position and rate are correlated with scale ~(t_ref − t̄).
- σ_ω ≈ σ_θ / T_eff (T_eff = the baseline spread): the rate precision is set by the position precision and the time baseline — they are not independent inputs.
- σ_ω is really the curvature of the SNR-vs-rate ("focus") surface.
Current state in layup
- Forward model is already consistent: for a streak/shift-stack row, both the apparent position and the apparent rate are evaluated at the single epoch
this_det.epoch (light-time corrected, incl. the (1−q/c) rate factor). No model change needed as long as that epoch is the stack reference/centroid.
get_weight_matrix (orbit_fit.cpp) is diagonal: four independent weights from rmsRA/rmsDec (position) and rmsRArate/rmsDecrate (rate). It drops (a) the position↔rate cross-block, and (b) the within-blocks (RA–Dec, RARate–DecRate).
Observation::inverse_covariance (detection.cpp) is declared + pybind-exposed but unused — it's the natural home for a per-observation covariance block.
Interim guidance (no code change)
Instruct users to report the shift-and-stack position at the time centroid of the exposures, and to supply position/rate uncertainties derived at that reference. At the centroid the position–rate cross-covariance vanishes, so the current diagonal weighting is a good approximation and the correlations we don't yet fit are avoided. (Worth stating in the streak/shift-stack ingestion docs.)
Future work
- Ingest and use the joint (θ₀, ω) covariance (a 4×4, or position-at-centroid + rate + cross terms) via the existing
inverse_covariance slot, so off-centroid references and reported position–rate/RA–Dec/RARate–DecRate correlations are weighted correctly.
- Note the structural gap: a single epoch + four scalar σ's can't represent
σ_ω ≈ σ_θ/T_eff (the baseline tying them together isn't carried) — full covariance ingestion resolves this.
- Consider renaming the internal "streak" concept to reflect shift-and-stack (or document that it covers both trailed-source and shift-and-stack measurements, which share the (position, rate) model but differ in how the covariance arises).
From a modeling discussion with @matthewholman.
Summary
The "streak" rate-fitting path is really the model for shift-and-stack measurements (shift each exposure by an assumed motion, coadd; the best rate pair focuses the flux into a PSF). Such a detection yields a joint estimate of position and rate from the same photons, so the two are correlated. layup currently weights the position and rate rows with a strictly diagonal weight matrix, which drops those correlations. This issue records the model and the interim guidance; a fuller treatment is future work.
Measurement model
Shift-and-stack fits
θ(t) = θ₀ + ω·(t − t_ref)to the exposures, giving the focused-PSF positionθ₀att_refand the rateωjointly — an intercept + slope estimate over the exposure epochs. Its covariance is the usual linear-fit one:t_refis the (SNR-weighted) time centroid of the exposures. Off-centroid, position and rate are correlated with scale ~(t_ref − t̄).Current state in layup
this_det.epoch(light-time corrected, incl. the (1−q/c) rate factor). No model change needed as long as that epoch is the stack reference/centroid.get_weight_matrix(orbit_fit.cpp) is diagonal: four independent weights fromrmsRA/rmsDec(position) andrmsRArate/rmsDecrate(rate). It drops (a) the position↔rate cross-block, and (b) the within-blocks (RA–Dec, RARate–DecRate).Observation::inverse_covariance(detection.cpp) is declared + pybind-exposed but unused — it's the natural home for a per-observation covariance block.Interim guidance (no code change)
Instruct users to report the shift-and-stack position at the time centroid of the exposures, and to supply position/rate uncertainties derived at that reference. At the centroid the position–rate cross-covariance vanishes, so the current diagonal weighting is a good approximation and the correlations we don't yet fit are avoided. (Worth stating in the streak/shift-stack ingestion docs.)
Future work
inverse_covarianceslot, so off-centroid references and reported position–rate/RA–Dec/RARate–DecRate correlations are weighted correctly.σ_ω ≈ σ_θ/T_eff(the baseline tying them together isn't carried) — full covariance ingestion resolves this.From a modeling discussion with @matthewholman.