Repository navigation
Line neighbour masks up with each exposure's own pixels - #985
Open
cailmdaley wants to merge 8 commits into
Open
cailmdaley wants to merge 8 commits into
cailmdaley wants to merge 8 commits into
Conversation
Sample full-tile labels through the independent WCSs at image INT_POS pixel centres. Store segmentation, neighbours and off-tile maps with each image epoch and consume them before ngmix masks, cuts and diagnostics. Keep native images unchanged and fail on missing categories. Preserve pre-join labels as SEG_LABEL and strip this bookkeeping from final catalogues. Define noisefill neighbours from full foreign segmentation footprints so category coverage does not depend on finite tile VIGNET markers. Cover independent astrometry, categorical sampling, joined labels, tile edges, the retained 188.307 example and a killed flip-only-overlay mutant. Record the convention in ASTRA and the workflow documentation.
Describe registered foreign footprints and the measured conditional shape sensitivity. Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Use mktemp for atomic WCS publication and exercise concurrent copies with identical container shell PIDs. Pin the intentional campaign-boundary prologue change. Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
A populated entry disproves all-empty; stop before reading the rest of each shared store in every chunk. Keep the all-empty product and guard ordering, open preflight stores read-only, and test both short circuits with poisoned later payloads. Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Exercise the real four-input runner with an all-sky segmentation FITS product, preserve empty catalogue schemas, and verify registered-store dtypes, shapes, empty ranges and publication. Document the zero-detection segmentation and zero-key store contracts. Co-Authored-By: Sol <noreply@openai.com>
cailmdaley
added a commit
to cailmdaley/shapepipe
that referenced
this pull request
Nov 1, 2026
cailmdaley
added a commit
to cailmdaley/shapepipe
that referenced
this pull request
Nov 1, 2026
cailmdaley
added a commit
that referenced
this pull request
Nov 6, 2026
Conflicts: only tests/workflow/params_pin.json and params_pin_noisefill.json, both generated digests. Took neither side: regenerated both with --update-params-pin on the merged tree. tile_vignets, tile_ngmix and tile_make_cat move from edge's values, the three rules whose prologue carries #985's mktemp WCS staging; every other rule keeps edge's digest, so #994's and #997's exposure and tile-store changes stand as they were. Everything else merged cleanly and needed no adaptation. #997's Snakefile tile_store_root bind and #985's tile_local() edit touch separate lines, and the vignetmaker configs #985 changed are not the exposure configs #994 changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JK7o9HXHK2JHphJN9p7BYu
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Line neighbour masks up with each exposure's own pixels
Closes #984.
The problem. ngmix fits every galaxy on each single-exposure stamp, at native exposure pixels. The masks it applies come from detection on the coadded tile: which pixels belong to a neighbour (UberSeg / noisefill), which fall off the tile, and which footprint belongs to the object itself. On develop those tile-grid masks are pasted onto the exposure stamp with only the MegaCam flip applied. The tile and exposure grids are offset and rotated relative to each other, so the pasted masks are misaligned. On tile 188.307 the shift is 0.56 px at the median, 1.1 px at P95, and more at stamp edges, with up to 1.8° of rotation:
That changes which pixels get masked: UberSeg masks differ in about half of all stamps. It also mis-assigns defects. In the example below, a bad column 2 px from the object centre lies inside its footprint, but the flip-only overlay puts it outside:
The fix. Vignetmaker looks up each exposure-stamp pixel in the full tile segmentation map through both WCSs (nearest tile pixel). It stores three per-epoch maps on the exposure stamp's own grid: segmentation, neighbour and off-tile. ngmix uses those instead of the overlay. The image, weights, flags and PSF are untouched; nothing is resampled.
What it does to shapes. On 188.307 every object was fitted both ways with identical seeds. For the 7,923 resolved, well-measured objects, the m-like shift is −0.19% ± 0.09%, and there is no detectable additive shift (≈ ±4×10⁻⁵). Both are well inside requirements (|m| < 1%, |c| < 5×10⁻⁴). Objects whose masks don't change reproduce bit for bit. So run 1 isn't invalidated; this is a correctness fix for run 2.
Cost and adoption. The image vignette store grows by about 1.9 GB per 120k epochs, and vignetmaker takes
segmentation.fitsas a fourth input. It lands at a campaign boundary: rerun from tile detection, and never mix old vignette stores with this contract (old stores fail loudly). A realsprun of 188.307 passed end to end within budget (tile_vignets 6m26s, 14.1 GiB). That run exposed two bugs, both fixed here: WCS staging files collided across containers, and a 15-min store scan ran per chunk.Contracts, frame handling, full shape study, validation, campaign notes
Design and product contract
For native stamp row/column indices, the exposure pixel coordinates are
(INT_POS[1] + col − half_width, INT_POS[0] + row − half_height); storedINT_POSis in [row,col] order.Both WCS calls use zero-based pixel centres.
Nearest tile cells are
floor(x+0.5)on each axis, including upward half-cell ties.OFFSETretains the image extractor's subpixel centroid remainder for the prior; adding it to these integer pixel-centre coordinates would shift categories away from the image grid.The native image, detector flag, weight, background and RMS stamps remain untouched.
Celestial-frame contract: an exposure identified as FK5 with equinox J2000 is treated as numerical ICRS only when its header's
ASTCATcontains a case-insensitivegaiatoken.The implementation casefolds
ASTCAT, splits it with[^a-z0-9]+, and requiresgaiaamong those tokens; the real header isASTCAT='test.gaia'.It deep-copies that exposure WCS, sets
radesys='ICRS'andequinox=NaN, and callswcs.set(); it does not transform the numerical sky coordinates or mutate the stored WCS/header.Every other exposure retains its declared frame.
After this normalisation,
tile_frame.is_equivalent_frame(epoch_frame)must hold, including equinox where applicable; any remaining mismatch raisesValueError.This is not a blanket FK5-to-ICRS conversion.
For 500 compact-object centroids in 188.307, the median residual is (+0.006,+0.003) px with common numerical coordinates, versus (−0.044,−0.010) px after FK5-to-ICRS conversion, supporting the measured-header interpretation in the #985 review.
SEG_LABEL, an int32 pre-join check-image label.The catalogue join retains it while relabelling
NUMBERand tileSEG_VIGNET.Vignetmaker uses it to relabel the full segmentation; sky is 0 and detections absent from the joined catalogue are −1.
segmentation.fitsas its fourth positional input, aftersexcat,log_exp_headersandexp_numbers.Each existing
image_vignetepoch entry gainsSEG_VIGNET(int32),NEIGHBOUR(bool), andOFF_TILE(bool) with the image stamp's shape and extraction grid.make_catdropsSEG_LABELwith the tile stamp fields under its normal stamp-removal setting.Full source support covers cells beyond the original tile VIGNET; a padded-with-sky 51×51 source would not.
Off-tile cells come from the full tile rectangle, not a rotated-row marker heuristic.
This provides full-tile categorical support without guessing unavailable markers or inflating tile vignette products.
On this retained tile, 29,751 of 2,468,504 foreign-footprint source pixels lack SExtractor's intensity marker, affecting 2,456 objects.
The paired UberSeg science comparison does not measure this additional noisefill change.
The tile
SEG_VIGNETstill supplies the catalogue-levelneighbour_flagand tile-label integrity diagnostic.Consumers touched are
Ngmix.prepare_postage_stamps,make_cat's stamp-field removal, production data/simulation vignetmaker configurations, the simulation example producer/consumer chain, and the two masked-pixel validation helpers.The sampling convention and footprint/blend descriptions are recorded in ASTRA and
universes/committed.yaml.What registration does to shapes
On tile 188.307, every object passing a
FLAGS=0,10≤SNR_WIN≤500proxy cut (16,655) was fitted twice, flip-only (develop5702688e) and registered (this branch). Inputs, settings and per-object RNG seeds are identical in both runs. 16,609 objects have all five metacal fits unflagged in both runs. All differences below are registered minus flip-only. Errors are paired object-bootstrap standard errors; they do not include field-to-field variation across tiles.On resolved, well-measured objects the effect is small: an m-like shift of about −0.2% and no detectable additive shift.
The whole proxy sample is dominated by fits that carry zero flags but are pathological, e.g. one object whose fitted T/T_PSF goes from 2431 to −0.26. It is a stress figure, not a bias estimate. The requirements are |m| < 10⁻² and |c| < 5×10⁻⁴.
Per object, the changes are mostly zero with a long tail: P95/P99 of |Δe| = 0.010/0.026, and 5% of pairs have |Δe| > 0.01. |Δe| tracks the change in central mask area (Spearman 0.91). All 5,506 objects whose masks don't change reproduce all five metacal shapes bit for bit.
Limits. These are real, unsheared stamps from one tile. They measure how much the shapes and responses move, not a calibrated multiplicative bias; that needs paired known-shear scenes with neighbours at sub-pixel mask offsets. If each run is allowed its own size/S/N selection, the 95% envelope on the additive-like shift reaches ~5×10⁻⁴. Selection effects through the cuts are therefore the term to watch. A 2,600-object enriched experiment, the influence checks and the per-object records are in the science report (Nibi
/scratch/cdaley/fix984/SCIENCE.md).Validation
The full retained exposure header includes
RADECSYS=FK5,EQUINOX=2000, andASTCAT=test.gaia; its numerical lookup remains identical, genuinely mixed FK5/ICRS inputs raise, and the ICRS control passes.Additional cases check Gaia token matching, other equinoxes/frames, equal FK5 frames, and the header-store ingestion path.
tests/mutations/flip_only_overlay.pyrestores the flip-only overlay in an isolated source tree: all three selected regressions fail, including missed off-tile rejection andimaflags_iso=0instead of 3 for the retained example.All 5,506 unchanged UberSeg/off-tile mask controls reproduce all five fitted metacal shapes bit-for-bit.
Eight fit/weight/response functions have identical executable ASTs apart from docstrings and diagnostic error messages.
Logs: Nibi
/scratch/cdaley/fix984/(science, first round) and/scratch/cdaley/fix985/(frame contract).Campaign boundary
Use this at a campaign boundary, including the matching calibration simulations.
Rerun tile detection/join to obtain
SEG_LABEL, then epoch vignette generation, ngmix, and final catalogue assembly; image stores without the registered fields fail loudly.The full segmentation check image must remain available to vignetmaker.
Native exposure images, WCSs, detector maps, backgrounds and PSF models can be reused when otherwise unchanged, but old image-vignette/category stores must not be mixed with this contract.
The same native-grid footprint feeds #973 and can feed #983's footprint-touch veto; this branch retains develop's fixed-radius central veto.
For 120,421 epochs of size 51×51 the three category arrays add about 1.9 GB of uncompressed payload to the image vignette store, plus small dictionary overhead, without adding another product file.
Real run through
spDR6 tile 188.307 was run privately through
workflow/bin/spin the campaign container, from tile detection totile_make_cat, in one 16-core allocation at3cec9076:tile_vignetstook 6m26s with a 14.1 GiB peak, against a 20 min / 32 GB budget. The vignette store carriesSEG_VIGNET(int32),NEIGHBOURandOFF_TILE(bool) at the stamp shape on all 120,421 object-epochs.4bf50f98). Each ngmix chunk scanned the whole vignette store before fitting, about 15 min on NFS; the scan now stops at the first populated entry (3cec9076). Both have regression tests that fail without the fix.Practice gaps closed
A cross-family audit against our scientific-software practice asked for the following. Each item has its own commit:
*-footprints.SEG_LABEL, a 3-input MULTI-EPOCH config, and missing, misshapen or non-boolean categories.SEG_VIGNETgate and theSEG_LABELwriter) are tagged and pinned inpreparation.categorical_registration, with tests showing that changing them fails.flip_only_overlayoption and the measured misregistration. It states the shape shift and notes that the noisefill footprint effect is unmeasured.The branch merges develop at
6060c6de(#981) with no conflict resolution. A separate commit (fb4755a2) adapts the zero-object tests to the 4-input vignetmaker: a zero-object tile still has a full-size, all-zero segmentation image carrying the tile WCS.Branch:
fix/seg-exposure-grid, headfb4755a2, containing develop6060c6de.Claude (Opus 5.5) on behalf of Cail; implemented and measured by GPT-6.1 Sol.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JK7o9EvVyXSSb8s7hMDX1H