Skip to content

measure_arc_geometry

Measure smile_radius + slant_deg from an arc-lamp 2-D image.

Category Wavelength calibration
Backend scipy - implemented here on top of scipy primitives
Version 2.0.0
Reads -
Writes extras.geometry, metrics.geometry_rms_px, metrics.n_lines_used

Sums the arc along the slit, picks bright arc lines with scipy.signal.find_peaks, then walks each line row-by-row across the slit computing a sub-pixel column centroid in a small window. Fits a Schroeder parabola dx(y) = (y - y₀)² / (2 R) on the row-averaged offsets to get R; the residual linear slope dx/dy → tilt angle. y₀ comes from ctx.extras['trace'] (set by detect_trace) when present, otherwise defaults to the image centre. v2.0.0: slant_deg is now returned with the sign correct_slant_affine expects (slant_deg = -atan(dx/dy)); feeding it unchanged to correct_slant_affine(slant_deg=…, pivot_row=reference_row) straightens the lines. v1 returned the opposite sign, so the documented chain doubled the slant (synthetic +0.05 px/row: residual +0.10 px/row in v1, 0.000 in v2).

Parameters

Parameter Default Required Description
lamp_key 'lamp_image' - ctx.extras key holding the arc-lamp 2-D ImageFrame.
trace_key 'trace' - ctx.extras key holding the science trace dict (from detect_trace). The trace's center_row becomes the reference row y₀ ; absent ⇒ image centre.
detection_sigma 5.0 - Peak prominence threshold (× DER_SNR-style noise) when finding arc lines on the summed spectrum.
min_prominence 0.05 - Lower bound on the prominence as a fraction of the peak amplitude.
min_lines 6 - Minimum number of arc lines successfully tracked across the slit. The algorithm fails below this — too few lines makes the smile fit unreliable.
max_lines 30 - Cap on the number of arc lines fed to the fit.
search_half_width_px 12 - Half-window (column pixels) around each line's reference x for the per-row centroid.
row_step 5 - Spacing (rows) between sample points along the slit.
row_half_range 200 - Half-range (rows) above and below the reference row over which each line is tracked.
smile_order 2 - Polynomial order for the smile fit (2 → Schroeder parabola).
fit_tilt True - When True, also estimate the linear tilt slope.
output_key 'geometry' - ctx.extras key receiving the geometry dict.

Use it

from spectro_kernel import run_algorithm

output = run_algorithm("measure_arc_geometry", ctx, {
    "lamp_key": "lamp_image",
    "trace_key": "trace",
    "detection_sigma": 5.0,
    "min_prominence": 0.05,
    "min_lines": 6,
    "max_lines": 30,
    "search_half_width_px": 12,
    "row_step": 5,
    "row_half_range": 200,
    "smile_order": 2,
    "fit_tilt": True,
    "output_key": "geometry"
})
spectro run measure_arc_geometry --input spectrum.fits \
  --param lamp_key=lamp_image \
  --param trace_key=trace \
  --param detection_sigma=5.0 \
  --param min_prominence=0.05 \
  --param min_lines=6 \
  --param max_lines=30 \
  --param search_half_width_px=12 \
  --param row_step=5 \
  --param row_half_range=200 \
  --param smile_order=2 \
  --param fit_tilt=true \
  --param output_key=geometry
{
  "tool": "measure_arc_geometry",
  "arguments": {
    "session_id": "<session_id>",
    "params": {
      "lamp_key": "lamp_image",
      "trace_key": "trace",
      "detection_sigma": 5.0,
      "min_prominence": 0.05,
      "min_lines": 6,
      "max_lines": 30,
      "search_half_width_px": 12,
      "row_step": 5,
      "row_half_range": 200,
      "smile_order": 2,
      "fit_tilt": true,
      "output_key": "geometry"
    }
  }
}

Every algorithm is an MCP tool of the same name; describe_algorithm returns this page's metadata as JSON.

References

  • Tody 1986, Proc. SPIE 627, 733 — IRAF identify / reidentify / fitcoords 2-D wavelength solutions.
  • Prochaska et al. 2020, JOSS 5, 2308 — PypeIt wavelength / tilts module.
  • Schroeder 2000, Astronomical Optics 2nd ed. ch. 15 §15.3 — smile curvature parametrisation R.