healpix_resample.subset_for_parent_cell#

healpix_resample.subset_for_parent_cell(lon_deg, lat_deg, parent_cell_id, level_parent, level, *, nest=True, ellipsoid='WGS84', margin_rings=1, num_threads=0)[source]#

Restrict processing to one parent cell: which samples, which output cells.

This is the standalone helper for the “process one coarse cell at a time” workflow: it does not itself construct or call any resampler, and it does not take or return any value array (val) – it only prepares the two pieces every resampler’s constructor needs to do less work:

  1. Output side (cheap, exact, no new logic): the set of level -resolution cells contained in parent_cell_id, via healpix_geo.*.zoom_to. Pass this straight through as any resampler’s out_cell_ids= kwarg – see the “group_by resamplers” caveat below for the one place this doesn’t apply.

  2. Input side (the actual point of this helper): an integer index into the sample axis – not a filtered value array – selecting which samples could plausibly matter for cells inside parent_cell_id.

Why this returns an index rather than filtered arrays#

A single (lon_deg, lat_deg) grid is very commonly shared by many different value arrays (several variables, a time series of the same station network, …). Taking a val in and handing back a filtered val_sub would mean recomputing this exact same geometric membership test again for every one of those arrays, even though the answer – which samples are relevant to parent_cell_id – only depends on lon_deg/lat_deg and never changes. Instead, subset_for_parent_cell returns sample_idx, an integer array into the sample axis: compute it once per (lon_deg, lat_deg) grid and reuse it to index lon_deg, lat_deg, and as many value arrays as you have that share those same coordinates:

sample_idx, out_ids = subset_for_parent_cell(
    lon, lat, parent_cell_id=pid, level_parent=6, level=20,
)
lon_sub, lat_sub = lon[sample_idx], lat[sample_idx]
val_sub = val[..., sample_idx]           # any variable on the same grid
other_val_sub = other_val[..., sample_idx]

sample_idx indexes the last axis, so it applies uniformly whether a value array is (N,) or batched (B, N), and works the same way for plain NumPy arrays or PyTorch tensors (fancy-indexing a tensor with a NumPy integer array works out of the box).

Why input filtering needs a margin, not just “same parent cell id”#

A sample can sit just outside parent_cell_id’s boundary, in a sibling level_parent cell, while still being close enough in the fine-level kernel sense (sigma_m/threshold – see KNeighborsResampler) to legitimately contribute to a fine cell near the parent’s edge. Filtering input strictly to “same parent cell id” would silently starve edge cells of legitimate neighbours – a subtle correctness bug that only shows up as slightly-degraded results near parent-cell boundaries, not as an error.

margin_rings controls this, and is measured in fine-`level` HEALPix rings, not level_parent rings: samples are kept if their own level cell id is within margin_rings rings of any fine cell inside parent_cell_id (i.e. of out_cell_ids, expanded via healpix_geo.*.kth_neighbourhood at level). This matters because a fine cell is typically vastly smaller than a parent cell – buffering by whole parent-level rings instead (one ring already means “pull in every neighbouring parent cell in full”) would keep a hugely disproportionate number of irrelevant samples relative to the resampler’s actual kernel reach at level. This is a correctness guarantee, not just a performance knob: the margin must be wide enough that the resampler’s actual kernel reach (sigma_m and the effective radius implied by threshold) can never extend past it, but sized at the fine scale the kernel actually operates at. margin_rings=1 (the default) is very likely generous relative to a fine cell’s own width, but this scales with your sigma_m/threshold choice, not with this function’s defaults – if you shrink sigma_m or loosen threshold enough that the kernel reaches past a handful of fine cells, increase margin_rings accordingly. When in doubt, compare a fine cell’s angular width (roughly sqrt(4*pi/(12*4**level)) radians) against the kernel’s actual reach for your resampler and size the margin so the kernel cannot reach past it.

Resamplers using group_by=True (ConservativeResampler, GroupByResampler, CellPointResampler) ———————————————————————— These resamplers derive their cells purely from torch.unique over the (already margin-filtered) input subset – they have no KNN neighbourhood search and no out_cell_ids intersection logic to hook into: ConservativeResampler raises NotImplementedError if you pass out_cell_ids to it at all, and GroupByResampler/CellPointResampler silently store but never use it (no error, no effect). For these classes, use only sample_idx (piece 2) to slice lon_deg/lat_deg/ val and do not pass the returned out_cell_ids (piece 1) to their constructors – the set of cells they produce is whatever the filtered input actually hits, which will generally be a subset of (or, at the margin, extend slightly beyond) out_cell_ids and cannot be force-expanded to include empty parent-cell-interior cells the way KNN-mode resamplers can.

Parameters:
  • lon_deg, lat_deg (array-like, shape (N,)) – Full input sample coordinates in degrees.

  • parent_cell_id (int) – HEALPix cell id at level_parent to restrict processing to.

  • level_parent (int) – The coarse level parent_cell_id is expressed at (nside = 2**level_parent). Should be well below level.

  • level (int) – The target (fine) HEALPix level the eventual resampler will run at.

  • nest (bool) – HEALPix indexing scheme, must match what the resampler will be constructed with.

  • margin_rings (int) – Number of fine-`level` HEALPix rings around out_cell_ids to include when filtering input samples – see “Why input filtering needs a margin” above (note: this is rings at level, not level_parent). 0 disables the margin entirely (kept only to make the “margin matters” failure mode easy to demonstrate/test; not recommended for real use).

returns:
  • sample_idx (numpy.ndarray of int) – Integer index into the sample axis (lon_deg/lat_deg, and any value array sharing that same axis) selecting the samples relevant to parent_cell_id (its own cells plus the margin_rings-neighbour buffer at level). Apply it yourself: lon_deg[sample_idx], val[..., sample_idx], etc.

  • out_cell_ids (numpy.ndarray) – The level-resolution cells contained in parent_cell_id, ready to pass straight into a KNN-mode resampler’s out_cell_ids= kwarg (not for group_by=True resamplers – see above).