Smithsonian / Smithsonian/layup
Shift-and-stack: joint position+rate covariance weighting (interim: report at time centroid)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 10
- Forks
- 2
- Avg merge
- 1d 43m
- Merged PRs (30d)
- 58
Description
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_refis 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 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
- Ingest and use the joint (θ₀, ω) covariance (a 4×4, or position-at-centroid + rate + cross terms) via the existing
inverse_covarianceslot, 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the streak/shift-and-stack ingestion documentation and review the interim guidance in this issue. Document reporting the position at the exposure time centroid with position and rate uncertainties; done means the guidance is clearly stated without implementing covariance changes in orbit_fit.cpp or detection.cpp.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100