Build: #3 was successful
Job: ManyLinux 2.28 was successful
Code commits
Casa6
-
Josh Marvil 6cf1ede958f01d0f3ed691911c29f0f5c2778eb7
CAS-14874: derive briggsbwtaper fracBW from output cube
-
Josh Marvil d27fff1705e9d9b7af956665dcd0a23eb5d5e692
CAS-14874: Make the Briggs cube weight density partition-invariant
The per-channel imaging-weight density that briggsbwtaper/perchanweightdensity
relies on is local to a channel: f2/d2[chan] are derived from that channel's
gridded-weight plane only. The quality of that plane nevertheless depended on
*how many* channels this process happens to own, which made the weights - and
therefore the PSF and flux scale - vary with the number of MPI processes:
- estimateSwingChanPad() scaled its extra margin by the sub-cube channel count
(extrapad = max(min(4, imNChan/10), 1)), so different sub-cubes got different
guard margins.
- estimateSwingChanPad() returned 0 for a homogeneous frame, i.e. no guard
margin at all, even though the FT machine still interpolates visibility
frequencies across neighbouring channel planes (edge truncation).
- init() padded its density template by a fixed +4/+2 channels while
fillImgWeightCol() used the data-derived swingpad, so the two passes could
disagree on the geometry.
- the default pad for the multi-field/multi-MS path was a bare 4.
- the scratch weight table key was (nrows, freqbeg, freqend, rmode, robust,
interp). All ranks chdir to the same working directory, so ranks that
produced the same key shared one IMAGING_WEIGHT_* table and raced on it
(reuse-if-nonzero-row-count, else delete-and-recreate) while it was being
filled and consumed through readWeightColumn(). The reuse checks in
initImgWeightCol()/init() keyed on (nx, ny, first-channel frequency) only and
could hand back a density built for a different sub-cube.
- initializeFTMachine() rebuilt grids_p[index] from the new template on every
call but sized f2_p/d2_p only on the first one, so a template that grew
between calls left f2_p/d2_p shorter than the grid and made
f2_p[index][pos(3)] read past the end of the vector.
Fix, in this file only:
- introduce minWgtDensityEdgePad = 4 (channels per edge) and use it everywhere
the guard margin was previously derived from the local channel count;
- return that floor instead of 0 when no frame swing is present;
- align init()'s template padding and the multi-field default with it;
- fold a spectral geometry token (nchan, channel reference pixel, first
channel frequency) into the scratch table name, and require it in the
initImgWeightCol() early return;
- pin the init() reuse on the cached density extent (f2_p) matching the
requested template channel count;
- grow f2_p/d2_p (and zero them) in initializeFTMachine() when the template
channel count exceeds the cached allocation, and bounds-check the channel
index in both weightUniform() and getWeightUniform() so a stale allocation
yields a zero weight instead of an out-of-bounds read.
Because the density itself is per-channel-local, making the geometry
rule partition-independent is enough to make parallel results agree with serial
for a single input MS, and it removes the shared-table race entirely. No
interface, XML or Python change.
Known remaining partition dependence (follow-up, needs the full-cube channel
count to be plumbed into this file):
- the inOneGo threshold in initImgWeightCol() still compares the swing pad
against templateimage.shape()[3]/10, so multi-MS inputs can still choose a
different processing path on a small sub-cube than serial does;
- estimateSwingChanPad() still derives freqbeg/freqend (and so the swing
estimate itself) from the local template rather than the full selection, so
the swing term remains weakly dependent on the sub-cube range;
- the scratch table stays in the shared working directory (a per-rank workdir
is not knowable here), so cross-run reuse of a same-tag, same-row-count table
remains possible, as before.
Validation: two standalone harnesses compile the changed logic against stubbed
casacore types - the first asserts geometry-key/cache-key behaviour (reuse only
for identical token/extent/nx/ny/freq) and the pad floor values, the second a
faithful Block<Vector<Float>> model asserts the grow-then-zero path and that a
stale shorter f2_p is rejected rather than read out of bounds. Brace/paren
balance preserved (110->112 braces, 794->849 parens, both sides equal). A full
casatools build plus serial-vs-parallel tests are still required before merge.