Fiber Bundle Configuration for Multi-Fiber Instruments¶
Overview¶
PyReduce supports multi-fiber instruments where each spectral order contains multiple physical fibers. The fibers section in config.yaml defines how these fibers are organized into groups and which traces to use for each reduction step.
Terminology¶
Trace: Polynomial describing one fiber’s path across detector
Fiber: Physical fiber in bundle (numbered 1-N within each order/group)
Group: Named collection of fibers with semantic meaning (e.g., “A”, “cal”, “B”). Use groups when fibers have distinct roles - science targets, calibration sources, sky fibers, etc.
Bundle: Numbered groups of identical fibers (e.g., “bundle_1”, “bundle_2”, …). Use bundles for repeating patterns like IFU spaxels where each bundle has the same structure.
Spectral Order: Wavelength range; multi-order instruments have same fiber pattern repeated across orders
fiber_idx: Index of a fiber within its group/order (1-indexed). Used for per-fiber wavelength calibration.
In short: groups are for named, semantically distinct fiber sets; bundles are for numbered, structurally identical fiber sets.
Each Trace object has:
m: Spectral order number (physical diffraction order)group: Group/bundle identifier (“A”, “B”, “cal”, or bundle index)fiber_idx: Fiber index within the group (1-indexed), or None if merged
Configuration¶
Named Groups (single-order instruments)¶
For instruments with explicitly defined fiber groups:
fibers:
groups:
A:
range: [1, 36] # Fibers 1-35 (1-based, half-open interval)
merge: average # Average all fiber traces into one
cal:
range: [37, 40] # Fibers 37-39
merge: average
B:
range: [40, 76] # Fibers 40-75
merge: average
use:
science: [A, B] # Science extraction uses A and B groups
wavecal: [cal] # Wavelength calibration uses cal fiber
norm_flat: all # Flat normalization uses all individual fibers
Bundle Pattern (MOSAIC-style)¶
For instruments with repeating fiber bundles:
fibers:
bundles:
size: 7 # 7 fibers per bundle
count: 90 # 90 bundles total (optional validation)
merge: center # Select middle fiber from each bundle
use:
curvature: groups # Use all 90 bundle centers
science: groups
Handling Missing/Broken Fibers¶
When some fibers are broken or missing, the trace count won’t be divisible by bundle size. Use bundle_centers_file to assign traces to bundles by proximity rather than fixed division:
fibers:
bundles:
size: 7
bundle_centers_file: bundle_centers.yaml # y-position of each bundle center
merge: center
use:
curvature: groups
science: groups
The bundle_centers.yaml file maps bundle IDs to y-positions at detector center:
# bundle_centers.yaml
1: 3975.0
2: 3932.4
3: 3889.8
# ... etc for all 90 bundles
Each detected trace is assigned to its nearest bundle center. When merging:
merge: center with all fibers present: picks middle index (e.g., fiber 4 of 7)
merge: center with missing fibers: picks trace closest to bundle_center
merge: average: averages all present fibers (no extrapolation for missing)
This approach handles arbitrary patterns of missing fibers without requiring the trace count to be divisible by bundle size.
Per-Order Grouping (echelle multi-fiber)¶
For echelle instruments where fiber groups repeat across spectral orders (e.g., ANDES_YJH with 75 fibers per order across 18 orders):
fibers:
fibers_per_order: 75 # Enables per-order organization
order_centers_file: order_centers.yaml # Or inline with order_centers:
groups:
A:
range: [1, 36]
merge: average
cal:
range: [37, 40]
merge: average
B:
range: [40, 76]
merge: average
use:
science: [A, B]
wavecal: [cal]
norm_flat: all
Setting fibers_per_order enables per-order organization (no separate per_order: true needed).
The order_centers.yaml file maps spectral order numbers to y-positions at detector center:
# order_centers.yaml
90: 3868.1
91: 3609.0
92: 3356.4
# ... etc
Or inline for instruments with few orders:
fibers:
fibers_per_order: 3
order_centers:
1: 150.5
2: 320.3
3: 490.1
Multi-Channel Instruments¶
For instruments with multiple channels (detectors/arms), per-order fields can be lists indexed by channel:
channels: [UVB, VIS, NIR]
fibers:
fibers_per_order: [75, 75, 60] # Can vary per channel
order_centers_file: [uvb_centers.yaml, vis_centers.yaml, nir_centers.yaml]
groups: # Same structure across all channels
A: {range: [1, 36], merge: average}
B: {range: [40, 76], merge: average}
If fiber arrangements differ fundamentally between channels, use separate instrument configs.
Merge Methods¶
average- Fit polynomial to mean y-positions of all fibers in groupcenter- Select the middle fiber’s trace[i]or[i, j, ...]- Select specific 1-based indices within group
Per-Step Trace Selection¶
The use section specifies which traces each reduction step receives:
all- All individual fiber traces (ignores grouping)groups- All merged group/bundle traces stacked[A, B]- Specific named groups (kept separate in output)per_fiber- Traces grouped byfiber_idxfor per-fiber processing
Steps not listed in use default to groups when groups/bundles are defined.
Per-Fiber Wavelength Calibration¶
For 2D wavelength calibration (dimensionality: "2D"), all traces in a fit must share the same optical path. When multiple fibers exist per order:
fibers:
use:
wavecal: [A] # One 2D fit for group A across all orders
# OR
wavecal: [A, B] # Separate 2D fits for A and B
# OR
wavecal: per_fiber # Separate 2D fit per fiber_idx
With per_fiber, each unique fiber_idx gets its own 2D polynomial fit. This is useful when fibers have slightly different wavelength solutions and you want to calibrate each independently.
Output Format¶
Tracing saves all traces to a FITS binary table (.traces.fits) with one row per trace:
Column |
Type |
Description |
|---|---|---|
M |
int16 |
Spectral order number (-1 if N/A) |
GROUP |
16A |
Group/bundle identifier (‘A’, ‘B’, ‘cal’, etc.) |
FIBER_IDX |
int16 |
Fiber index within group (1-indexed, -1 if N/A) |
POS |
float64[deg+1] |
Position polynomial coefficients |
COL_RANGE |
int32[2] |
Valid x range [start, end) |
HEIGHT |
float32 |
Extraction aperture height in pixels |
SLIT |
float64[…] |
Curvature coefficients (if available) |
SLITDELTA |
float32[…] |
Per-row curvature residuals (if available) |
WAVE |
float64[…] |
Wavelength polynomial (if available) |
The GROUP column identifies which group/bundle each trace belongs to. The FIBER_IDX column identifies the fiber within the group (1-indexed). For merged groups, multiple raw fibers become a single trace with the group name and FIBER_IDX = -1.
Automatic Extraction Heights¶
The heights array stores per-trace extraction heights computed from trace geometry:
For middle traces: half the distance between neighboring traces
For edge traces: distance to the single neighbor
Measured at multiple reference columns; maximum is used
These heights are used automatically when extraction_height is set to null in settings.json. This provides optimal per-trace apertures without manual tuning.
For groups/bundles, heights are derived from fiber spacing within each group (span + fiber diameter).
Example Instruments¶
ANDES_UBV / ANDES_RIZ (66 fibers per order)¶
Simulated echelle spectrographs for visible wavelengths:
Fibers 1-31: Slit A
Fibers 33-35: Calibration
Fibers 36-66: Slit B
ANDES_UBV: channels U, B, V (selected by
BANDheader)ANDES_RIZ: channels R, R1, R2, IZ (selected by
HDFMODELheader, since R variants all haveBAND=R)
ANDES_YJH (75 fibers per order)¶
Simulated NIR echelle with science fibers A/B, calibration, and IFU:
Fibers 1-35: Slit A
Fibers 37-39: Calibration
Fibers 40-75: Slit B
Additional groups: ifu, ring0-4 (subsets of the fiber bundle)
Channels Y, J, H (selected by
BANDheader)
MOSAIC (630 fibers, single order)¶
ELT multi-object spectrograph with 90 IFU targets:
7 fibers per target bundle
Extract center fiber from each bundle for reduction
Uses
bundlespattern withbundle_centers_fileto handle broken fibers