Reconstruction Algorithm

3DCubeGen reconstructs regular 3D data cubes (RA, Dec, wavelength) from irregularly sampled IFU fiber data using weighted kernel interpolation. The same core algorithm is shared across all three supported spectrographs (LVM, MEGARA, VirusP).

Kernel Interpolation

For each output spaxel, the algorithm computes a weighted sum of all fiber spectra within a cutoff radius. The weight assigned to each fiber depends on its distance from the spaxel center:

\[w_k = \exp\!\left(-\frac{1}{2}\left(\frac{R_k}{\sigma}\right)^{\!\alpha}\right)\]

where:

  • \(R_k\) is the Euclidean distance from fiber k to the spaxel center (arcsec)

  • \(\sigma\) is the smoothing kernel size (sigm_s config parameter, arcsec)

  • \(\alpha\) is the shape factor (alph_s config parameter)

The shape factor controls the kernel profile:

  • \(\alpha = 2\) produces a Gaussian kernel (the default)

  • \(\alpha > 2\) produces a sharper, more top-hat-like kernel

The interpolated flux at each spaxel is the weighted mean:

\[F_{\text{spaxel}} = \frac{\sum_k F_k \, w_k}{\sum_k w_k}\]

Only fibers with finite, positive flux values contribute to the sum. Spaxels with zero total weight are left at zero flux.

Radius Cutoff

To avoid unnecessary computation, only fibers within a cutoff radius of each spaxel are considered. The cutoff radius is:

\[r_{\text{cut}} = \max\!\left(\frac{\sigma}{2},\; \frac{d_{\text{fib}} \times 3.5 \times 2}{2}\right)\]

where \(d_{\text{fib}}\) is the fiber diameter. For LVM, the fiber diameter parameter (fibA) is 35.3 arcsec; for VirusP it is configurable (default 4.16 arcsec); for MEGARA it is derived from the hexagonal bundle geometry.

Additionally, a Y-axis pre-filter selects only fibers whose Y coordinate is within \(r_{\text{cut}}\) of the current row, reducing the inner loop to nearby fibers.

Error Propagation

When error propagation is enabled (errors: True), errors are propagated using inverse-variance weighting:

\[\sigma_{\text{spaxel}} = \frac{\sqrt{\sum_k (\sigma_k \, w_k)^2}}{\sum_k w_k}\]

where \(\sigma_k\) is the error spectrum of fiber k. This preserves the correct noise scaling through the weighted interpolation.

ADR-Aware Mode

When fiber positions vary as a function of wavelength (e.g., due to Atmospheric Differential Refraction correction), the position arrays become 2D: x_ifu_V[n_fibers, n_wavelengths]. The algorithm detects this automatically (len(x_ifu_V.shape) > 1) and switches to per-wavelength distance calculations:

  • In 1D mode (fixed positions): a single scalar distance is computed per fiber-spaxel pair, and the weight applies uniformly across the spectrum.

  • In 2D mode (wavelength-dependent positions): the distance \(R_k(\lambda)\) is computed for each wavelength channel independently, producing wavelength-dependent weights.

This mode is used by the VirusP pipeline when adrcor: True.

Spaxel Size

The output spaxel size is controlled by the pix_s parameter. When set to 0 (auto-calculate), each spectrograph uses its own default:

  • LVM: pix_s = 0.75 * sigm_s

  • MEGARA: pix_s = sigm_s

  • VirusP: pix_s = 0.75 * sigm_s

Flux Scaling

After interpolation, the flux in each spaxel is scaled by an area factor to convert from fiber-integrated flux to surface brightness:

\[\text{factor} = \frac{(\text{pix\_s})^2}{\pi \, (d_{\text{fib}} / 2)^2}\]

This accounts for the different solid angles subtended by a square spaxel versus a circular fiber aperture.

Multi-Threading

The reconstruction is parallelized along the spatial Y-axis using Python’s ThreadPool. The number of threads is controlled by the nproc config parameter. Each thread processes a contiguous block of rows independently.

The outer loop iterates over X columns, and for each column the Y-axis work is split across nproc threads, with each thread calling the ifu_const() kernel function on its assigned row range.

Implementation Reference

The core interpolation functions are in CubeGen/tools/kernel.py:

  • ifu_const() – cube reconstruction kernel (flux + optional error)

  • map_const() – map reconstruction kernel (flux + magnitude + errors)

  • matrix_const() – matrix-mode variant used for covariance estimation

The kernel functions are called by the spectrograph-specific drivers:

  • CubeGen/tools/cubegen.py::map_ifu() – LVM cube generation

  • CubeGen/tools/mapgen.py::gen_map() – LVM map generation

  • CubeGen/megaratools/megcubegen.py::megmap_ifu() – MEGARA cube generation

  • CubeGen/virustools/viruscubegen.py::virusmap_ifu() – VirusP cube generation