Skip to content

Centre the PSF-star box on a KDE peak of the FWHM preselection - #934

Open
cailmdaley wants to merge 3 commits into
developfrom
fix/stable-fwhm-mode
Open

cailmdaley wants to merge 3 commits into
developfrom
fix/stable-fwhm-mode

Conversation

@cailmdaley

@cailmdaley cailmdaley commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #928

What changes. The PSF-star box is now mode ± 3·locus_width, measured on each CCD's preselected FWHM_IMAGE. It replaces a fixed ±0.2 px box around a histogram-zoom mode.

  • stellar_locus() in str_handler.py returns two numbers. The mode is the peak of a Gaussian KDE with a 0.1 px bandwidth. The locus width is the peak's half-maximum width converted to a Gaussian σ, with the kernel removed in quadrature.
  • Below 20 objects it returns the median and the normalised MAD. With no objects it returns −1, which selects nothing.
  • The stat block logs the locus width.

Why.

  • The old mode estimator moved with the preselection's edges (PSF-star FWHM mode is noise-dominated and moves with the preselection #928).
  • The ±0.2 px constant dates from the first SETools config (2019). Neither that config nor Guinot+22 ("within 0.04 arcsec of the mode") gives a reason for it.
  • The locus width varies from 0.06 to 0.26 px per CCD, with seeing and focal-plane position. A fixed box cuts broad loci and is loose on sharp ones.
  • Broad loci are mostly FWHM gradients across the CCD. On 2114045p CCD 35, FWHM changes by 0.69 px from top to bottom, and the fixed box keeps stars only from the upper half, so PSFEx extrapolates into the lower half.

Evidence. SExtractor on the 80 CCDs of 2114045p (0.53″ seeing) and 2254826p (0.69″). The truth set is the size-independent MU_MAX−MAG_AUTO star sequence at 18–20.5 mag, on 79 CCDs.

±0.2 px (KDE centre) ±3σ̂
locus stars kept, 0.53″ / 0.69″ 95.6 / 80.9% 98.9 / 89.1%
non-stars in the box, 18–20.5 mag 1.7 / 3.0% 2.7 / 5.6%
bright locus stars kept, 2114045p CCD 35 (corner) 39/63 63/63
bootstrap half-width of the box edges, median 0.010 / 0.012 px 0.030 / 0.049 px
stars selected (sum) 2801 / 2220 3112 / 2967
  • Choice of k = 3. At k = 3 the next half-σ shell stops adding mostly stars: of the objects added between 3σ and 3.5σ at 0.53″, 28% are stars.
  • Bandwidth. It stays at 0.1 px, close to the median σ̂ (0.08 / 0.10 px). Tying it to each CCD's σ̂ lets galaxies pull the peak and the width on poor-seeing CCDs, moving the box edges by up to 4.5 px.
  • KDE vs histogram zoom. The KDE centre cuts the bootstrap spread from 0.04 to 0.01 px and the shift from edge objects from 0.2 to 0.003 px.
  • Checks. The real SETools run matches the study replica on all 80 CCDs, and no CCD falls below the 22-star gate.

Still open.

  • Fainter than 21 mag, FWHM no longer separates stars from galaxies at 0.69″. Most of the contamination that k = 3 adds is there: 4–10 galaxies per CCD at 0.69″, against 1–2 at 0.53″. A faint limit for PSF stars is Faint limit for PSF stars: FWHM stops separating stars from galaxies past ~21 mag #935.
  • Where galaxies capture the peak (2254826p CCD 35), no box recovers the stars. The logged locus width flags it: 0.32 px, against at most 0.26 px elsewhere.

Record and tests.

  • star_selection_box adds locus_scaled_box (default) beside Guinot+22's mode_centred_box, and pins LOCUS_BANDWIDTH, LOCUS_WIDTH_FLOOR and LOCUS_MIN_SIZE.
  • tests/unit/test_str_mode.py (95 tests) covers width recovery from 0.05 to 0.2 px, box proportionality, robustness to a galaxy tail, the guard against an adjacent bump, and the committed setools expression. Each of 8 injected bugs fails at least one test.
  • Gate: 896 passed, 1 skipped. astra validate passes. A cross-family review (GPT) found no defects.
  • The rationale and the setools Min/Max stat lines overlap Pixel scale from the WCS: ngmix prior and PSF star preselection #927, so whichever PR lands second resolves two small conflicts.

Study, figures (star_box_width.png, faint_and_spatial.png) and scripts: candide:/n17data/cdaley/scratch/fwhm-mode/width/.

Claude Opus 5.5 on behalf of Cail

🤖 Generated with Claude Code

cailmdaley and others added 2 commits September 30, 2026 07:15
mode() now returns the peak of a Gaussian kernel density estimate with a
0.1 px bandwidth, about the stellar-locus width, instead of an iterative
histogram zoom whose bins depended on the sample's extremes and count.
On 80 CCDs of exposures 2114045p and 2254826p the box centre's bootstrap
spread drops from 0.03-0.04 px to 0.01 px, and adding or removing three
objects at the preselection edges moves it by at most 0.003 px (0.24 px
before). Small-N behaviour is unchanged: median below 20, -1 when empty.

Closes #928

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NsPvmF43rzKrb5eYPNR3Ki
@cailmdaley

Copy link
Copy Markdown
Contributor Author

We have no aspiration to byte for byte continuity with the public selection. we want to develop the most reasonable and a robust approach to creating the star box. so how is the original 0.2 pixel width set and why did we choose 0.1? and is there some way to choose this based on the data? please develop a reasonable approach to choosing the width (this is a decision for astra)

The star box was mode +- 0.2 px for every CCD, a constant from the
original 2019 SETools config (Guinot+22 quotes it as 0.04 arcsec). The
locus width varies 0.06-0.26 px per CCD with seeing and focal-plane
position, so the fixed box cut broad corner loci and was loose on sharp
ones.

stellar_locus() returns the KDE peak and the peak's half-maximum width
as a Gaussian sigma with the 0.1 px kernel removed in quadrature;
locus_width() exposes the width to SETools expressions. The box is now
mode +- 3 * locus_width. k = 3 is where the next half-sigma shell stops
adding mostly stars against the size-independent MU_MAX - MAG_AUTO star
sequence on 79 CCDs (0.53 and 0.69 arcsec seeing): 98.9% / 89.1% of
locus stars kept at 2.7% / 5.6% contamination, against 95.6% / 80.9%
and 1.7% / 3.0% for +-0.2 px. The bandwidth stays fixed: tying it to
each CCD's width lets galaxies pull peak and width away on poor-seeing
CCDs.

The star_selection_box decision gains the locus_scaled_box option as
default, with the Guinot+22 box kept as mode_centred_box, and pins the
bandwidth, floor and small-N threshold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ELqMATt4MWS8TiVFrSLFA
@cailmdaley

Copy link
Copy Markdown
Contributor Author

The box is now ±3σ̂, where σ̂ is each CCD's measured locus width. It's recorded in astra.yaml as a new option beside Guinot+22's fixed box.

  • Where ±0.2 px came from. Axel's first SETools config (Jan 2019) set it, and it was copied forward unchanged. Neither the commits nor Guinot+22 ("within 0.04 arcsec of the mode") give a reason, so it reads as a round number, about 3σ of a good-seeing locus.
  • Why 0.1 px for the KDE. It's about the locus width. Silverman's rule let galaxies pull the peak, and 0.05 px was noisy on broad corner loci. I kept the bandwidth fixed rather than tying it to each CCD's σ̂: that creates a feedback loop in poor seeing that moved the box edges by up to 4.5 px.
  • Data-driven width. σ̂ is the half-maximum width of the KDE peak with the kernel removed. It runs from 0.06 to 0.26 px across the focal plane. I chose k = 3 against the size-independent MU_MAX−MAG_AUTO star sequence: past 3σ, most of what the box adds in good seeing is galaxies. Against the fixed box, it keeps 98.9 / 89.1% of locus stars instead of 95.6 / 80.9% (0.53″ / 0.69″ seeing), at 2.7 / 5.6% contamination instead of 1.7 / 3.0%.
  • Why it matters. Broad loci are mostly real PSF gradients. On 2114045p CCD 35, FWHM changes by 0.69 px across the CCD, and the fixed box kept stars only from the upper half.

The extra contamination is mostly at 21–22 mag, where FWHM stops separating stars from galaxies even under the old box. I filed that as #935 (a faint limit for PSF stars) rather than shrinking k. The PR description has the full table.

Claude Opus 5.5 on behalf of Cail

This branch has not been deployed

No deployments
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.

PSF-star FWHM mode is noise-dominated and moves with the preselection

1 participant