Skip to content

Pixel scale from the WCS: ngmix prior and PSF star preselection - #927

Merged
cailmdaley merged 5 commits into
developfrom
fix/pixel-scale-from-wcs
Oct 2, 2026
Merged

cailmdaley merged 5 commits into
developfrom
fix/pixel-scale-from-wcs

Conversation

@cailmdaley

@cailmdaley cailmdaley commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #134.

The pixel scale now comes from the image astrometry everywhere in the committed pipeline. No 0.186 or 0.187 is left in workflow/config/cfis/ or in the code paths it runs, and ngmix has no PIXEL_SCALE option.

  • ngmix. The centroid prior is one pixel wide, and each object uses its own pixel: sqrt|det J| of the per-epoch WCS Jacobians already built for the fit, averaged over the object's epochs. The prior is still built from the object's position-seeded RNG before the fit, so only its width changes. pixel_scale_from_wcs and its scan of the merged headers are removed. That scan raised AttributeError on real headers, and the PIXEL_SCALE = 0.186 pin had been hiding it.
  • Star selection. The 0.3–1.5″ preselection bounds were FWHM_IMAGE > 0.3 / 0.187. They are now FWHM_WORLD bounds in degrees, which SExtractor computes from the local WCS at each object. The ±0.2 px mode window is unchanged, since it is already in pixels. Diagnostics report arcsec via FWHM_WORLD*3600, and the stars/deg^2 stat, which was built from 0.187, is removed.
  • Record. fit_priors describes the per-object width and pins NGMIX_RUNNER.PIXEL_SCALE = absent. star_selection_box pins the angular bounds. CENTROID_SOURCE, METACAL_PSF and BKG_SUB are also pinned absent, so a template that sets one fails the decision check (seen to fail).

On real data (exposure 2114045p, 40 CCDs):

  • The mean scale is 0.1855″/px. Per position, sqrt|det J| runs from 0.1827″ to 0.1871″ (−1.5% to +0.8%, rms 0.5%). Within one CCD it varies by up to 1.3%, as much as between CCDs, so per position is the right granularity.
  • In 200 paired 2-epoch sims, changing the prior width by ±0.75% moves the median |Δg| by 7e-6 at S/N 20 and moves ⟨R11⟩ by less than 0.1%. At S/N ≥ 50 the changes are 1e-6 or smaller.
  • Star selection on four CCDs, same catalogue before and after: preselection grows by 0–4 objects per CCD. Selected stars are identical on CCDs 0 and 20, 67 → 68 on 39, and 74 → 66 on 10. The CCD-10 change comes from the mode estimator's sensitivity to edge objects, which Centre the PSF-star box on a KDE peak of the FWHM preselection #934 addresses.

Tests.

  • test_process_centroid_prior_is_each_objects_own_pixel_scale runs the process loop on objects with rotated and flipped epochs. It checks each prior width, and that the prior draws from the object's untouched position-seeded RNG.
  • test_stamp_pixel_scale_reads_a_rotated_flipped_wcs checks the scale from a rotated, flipped TAN WCS.
  • test_star_selection_preselects_on_angular_fwhm runs the committed .setools on synthetic stars and galaxies with per-object scales between 0.185 and 0.188.
  • Each test was seen to fail under injected bugs.
  • tests/unit and tests/module in the dev container: 804 passed, 1 skipped. astra validate passes. A cross-family review (GPT) found no correctness defects in the change.

Claude Opus 5.5 on behalf of Cail

🤖 Generated with Claude Code

cailmdaley and others added 2 commits September 30, 2026 04:22
pixel_scale_from_wcs skips merge_headers' TILE_ID entry and iterates the
object ndarrays split_exp writes, averaging both axes of every CCD WCS.
With that fallback working, the tile template drops its PIXEL_SCALE = 0.186
pin; PIXEL_SCALE remains an optional override. The fit_priors record
drops the resolved [LINT] and records the key as absent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 0.3-1.5 arcsec preselection bounds were FWHM_IMAGE cuts at a fixed
0.187 arcsec/px; they are now FWHM_WORLD cuts in degrees, which
SExtractor computes from each CCD's WCS. The mode window stays in pixels
(FWHM_IMAGE mode +- 0.2). Diagnostics report arcsec via FWHM_WORLD*3600
and the mode and cuts in pixels, as applied; the stars/deg^2 statistic,
which needed a hardcoded scale, is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
star_selection_box states that the mode-centred box moves with the
preselection (#928), and psfex_autoselect's excluded reason no longer
contradicts psfex_candidate_vetting. CENTROID_SOURCE and METACAL_PSF are
pinned absent under the [NGMIX_RUNNER] section tag, as is BKG_SUB, so a
committed template that sets them fails the decision check.
pixel_scale_from_wcs carries its fit_priors tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cailmdaley

Copy link
Copy Markdown
Contributor Author

can we use the correct per-CCD pixel scale?

cailmdaley and others added 2 commits October 1, 2026 03:34
The centroid prior is one pixel wide; that pixel is now sqrt|det J| of the
object's per-epoch WCS Jacobians (already built for the fit), averaged over
its epochs, instead of one mean over every CCD in the merged headers. The
prior is still built from the object's position-seeded RNG before the fit,
so only its width moves.

pixel_scale_from_wcs, the PIXEL_SCALE option and the unused get_noise go:
nothing else read a global scale.

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

Copy link
Copy Markdown
Contributor Author

Yes, and it now goes finer than per CCD. Each object's centroid-prior width is sqrt|det J| of its own epochs' WCS Jacobians, the same ones the fit already uses, averaged over those epochs. The global mean, the merged-header scan and the PIXEL_SCALE option are gone. On 2114045p the scale varies by up to 1.3% within a CCD, as much as between CCDs, so per position is the right granularity. Star preselection was already per position, through SExtractor's FWHM_WORLD. The effect on shear is negligible: a ±0.75% width change moves g by about 1e-5 at S/N 20, and the RNG stream is untouched.

Claude Opus 5.5 on behalf of Cail

@cailmdaley
cailmdaley merged commit d2968f0 into develop Oct 2, 2026
3 checks passed
cailmdaley added a commit that referenced this pull request Oct 2, 2026
The sextractor, match_catalogue, tile.smk, workflow README and params pin
conflicts are develop's squashed #933 against the same content here, so
they keep this branch's side: add_seg_vignet before match_catalogue, the
full-table relabel, the NUMBER guard and SExtractor's VIGNET centring.

ngmix: #927 replaces the PIXEL_SCALE option with each object's own
pixel scale from its epochs' Jacobians; develop's side is taken, and the
masked-pixels tests stop passing a pixel scale to Ngmix. #927's centroid
prior test sets the defect-fill attributes and epoch_cuts that process
reads on this branch.

The regenerated params pins are unchanged; the noisefill pin is
develop's params_pin.json byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017JQtu8oaZQEAqzbxZbPpWs
cailmdaley added a commit that referenced this pull request Oct 2, 2026
Follow #933: the tile VIGNET's -1e30 markers come from SExtractor alone;
the catalogue converter and its neighbour-marking decision are gone, and
the off-tile split tests cut SExtractor-style stamps from a segmentation
map directly. Follow #927: no PIXEL_SCALE option; the centroid prior uses
each object's own pixel scale. Tests that build Ngmix or drive process()
carry the epoch-cut settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JkM3cmXPuuSrNAf7vJde9e
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.

CFIS pixel scale

2 participants