specsr.data.augment

Augmentation of paired spectra, with explicit provenance.

Each galaxy is expanded into one original plus n_aug stochastic realizations: a small Gaussian redshift offset, and flux perturbations scaled to the local flux. The intent is to teach robustness to line-position variability and to noise, rather than to add information.

Provenance is not optional

Every emitted row records parent_id, the index of the galaxy it came from. The original products did not: their id column was a running row index, so after augmentation there was no way to tell which rows shared a parent. Splitting then had to be reconstructed from (ra, dec, field), and any split drawn over rows put ~16 near-duplicate siblings of every held-out galaxy into training.

Carrying parent_id makes the grouping explicit rather than inferred, so a leak-free split is the obvious thing to write rather than something that has to be recovered after the fact.

Redshift shifts are translations on a log grid

Because log(lambda * (1 + z)) = log(lambda) + log(1 + z), applying a redshift offset on a logarithmic wavelength grid is a uniform shift along the axis, the same number of samples at every wavelength. On the old linear grid the same operation stretched the spectrum, moving red features further than blue ones and changing the sampling of a line depending on where it sat.

This also matches the model: the convolutional stages are translation equivariant, so an augmentation that is a pure translation exercises exactly the symmetry the architecture already has.

Functions

augment_pair(flux_low, flux_low_err, ...[, ...])

Expand one galaxy into 1 + n_aug rows.

shift_redshift_on_log_grid(flux, valid, ...)

Move a spectrum from redshift z_from to z_to.

Classes

AugmentationConfig([n_aug, sigma_z, ...])

Parameters of the augmentation.

class specsr.data.augment.AugmentationConfig(n_aug=20, sigma_z=0.3, noise_frac=0.1, seed=42)[source]

Bases: object

Parameters of the augmentation.

Variables:
  • n_aug (int) – Realizations generated per galaxy, in addition to the original.

  • sigma_z (float) – Standard deviation of the Gaussian redshift offset.

  • noise_frac (float) – Flux perturbation as a fraction of the local absolute flux.

  • seed (int) – Base seed. Each galaxy derives its own generator from this and its parent index, so a build is reproducible and adding galaxies does not change the realizations of existing ones.

Parameters:
n_aug: int = 20
sigma_z: float = 0.3
noise_frac: float = 0.1
seed: int = 42
specsr.data.augment.shift_redshift_on_log_grid(flux, valid, z_from, z_to, grid, err=None)[source]

Move a spectrum from redshift z_from to z_to.

On a log grid this is a shift of log((1 + z_to) / (1 + z_from)) in log lambda, i.e. a constant number of samples. The shift is generally fractional, so neighbouring samples are linearly combined; the validity mask is shifted with the same weights and a sample is kept only if both contributing samples were valid, so a shift cannot manufacture data at the edge of a gap.

Samples shifted in from outside the grid are marked invalid rather than wrapped or extrapolated: there is no measurement there.

Parameters:
specsr.data.augment.augment_pair(flux_low, flux_low_err, valid_low, flux_high, flux_high_err, valid_high, z, parent_id, grid, config=None)[source]

Expand one galaxy into 1 + n_aug rows.

The first row is the unmodified original. Each subsequent row applies the same redshift offset to both members of the pair — they are the same galaxy, so a shift that moved them differently would teach the model a wavelength mapping that does not exist — and independent noise to each, since their measurement noise is genuinely independent.

Returns a list of dicts, each carrying parent_id and the realized z.

Parameters:
Return type:

list[dict]