FITS files & images
The FITS module watches a folder for new FITS files and renders the STF-stretched previews shown on the Console's Last captured frame card — the single image surface since v20.98 (the standalone viewer page was retired). For deep inspection of a saved frame, open the FITS file in ASTAP / PixInsight / your tool of choice.
File location
Settings → FITS, set the images directory. The default is C:\Astroworx\Starship\IMAGES — the same folder the camera writes captures into. The FITS module starts watching as soon as it is enabled; if the directory doesn't exist yet it logs a warning and keeps polling until it appears.
Other FITS settings on that page:
- Enable FITS viewer — turn the whole module on or off.
- Watch recursively — also pick up files in sub-folders of the images directory (off by default, so only the top level is listed).
- Max files listed — cap on how many files the list shows (newest first). Default 100.
- Auto-stretch (STF) preview — whether previews open with the auto-stretch applied.
The module polls the folder every few seconds. When a new file appears it publishes fits.new_file on the bus, and the UI picks the frame up live so it shows up without you touching anything. Recognised extensions are .fit, .fits, and .fts.
Folder layout
Settings > FITS / images > Folder layout decides where a capture lands under the images directory:
- Everything in the images directory (
[fits] layout = "flat") - the behaviour
every earlier build had; existing installs keep it until you change it.
- By night and target (
layout = "night_target", the default for a fresh
install): - science subs go to <night>/<target>/, e.g. 2026-09-12/Eagle_and_Omega_M16_M17/starship-Eagle_and_Omega_M16_M17-Luminance-120s-....fits. The night is the local date rolled over at noon, so a session that runs past midnight stays in one folder; the target is the object name as it appears in the filename; - calibration frames (flat / dark / bias, including Auto Flat's per-filter folders) go to <night>/calibration/; - pointing, recenter, autofocus, focus-star, framing and polar-alignment frames go to one _service/ folder which Starship empties when the service starts (service_dir_wipe_on_start), so it never grows and a failed night's evidence is still there the next morning.
Listing, previews, star metrics and the night report all follow the layout; nothing already on disk is moved when you switch.
Where images appear
- The Console's Last captured frame preview is the image surface: HFD (focus quality) and star count in the card header, a toolbar with Zoom, Center here, and Show last image, and double-click to enlarge. Previews are stretched and rendered on demand; files that are corrupt, compressed, or use an unsupported format show a clear error instead of a broken image.
- The plate-solve tile's file picker lists the watched folder (newest first), so any frame in the images directory can be solved.
- Headers stay available to tooling via
/api/fits/header/<file>(every card: key, value, comment).
Center here — click the toolbar icon, then click a point on the preview and confirm: Starship plate-solves that frame and precise-slews the mount so the clicked point becomes the new frame centre. This needs a connected, solvable mount and a plate solver.
STF auto-stretch
Raw 16-bit FITS data is essentially black to the human eye — almost all pixels cluster in a narrow range near the bias level. We apply a PixInsight-style Screen Transfer Function (STF) auto-stretch:
- Compute the median and the median absolute deviation (MAD)
- Set the black point at
median − 2.8 × 1.4826 × MAD(the1.4826scales MAD to match a standard deviation), clamped so it never drops below the 0.1th percentile or rises above the median - Set the white point at the 99.9th percentile, so a handful of hot pixels or a bright star can't wash the frame out
- Choose a midtones balance so the median lands around 25% brightness, then apply the midtones transfer function across that black→white range
This matches what PixInsight, Siril, and other astro tools do. It's display-only — it doesn't modify the file.
Manual stretch
The preview endpoint also accepts explicit black, white, and midtones values as query parameters, which override the auto-stretch for that render. This is an advanced hook for scripting or tools that build their own preview URLs.
Supported formats
The reader is pure-Python (no external libraries) and reads the primary HDU of standard FITS files:
- BITPIX 8, 16, 32 (integers) and −32 / −64 (32- and 64-bit float)
- NAXIS 2 (single 2D images); for 3D cubes it reads the first plane
- BSCALE / BZERO scaling is applied when reading
It does not read compressed image extensions (RICE, PLIO, GZIP), multi-HDU extensions, or FITS tables. When it hits one of those — or a file that's truncated or not FITS at all — it reports a clear message rather than a broken image.
The BZERO=32768 detail
A subtle point worth knowing about: most cameras save unsigned 16-bit pixel data, but FITS originally only specified signed integer types. The convention is:
BITPIX = 16(signed 16-bit)BZERO = 32768(offset to apply when reading)BSCALE = 1
The reader applies actual_value = stored_value + BZERO so unsigned values come back correctly. If you see weird negative pixel values or all-black images from a specific camera, it's likely missing this header — inspect the file's BZERO and BSCALE header cards (e.g. /api/fits/header/<file>, or any FITS tool).
Memory
Rendered previews are held in a small on-demand cache so re-opening the same frame doesn't re-stretch it; the cache is refreshed automatically if the file changes on disk. The health monitor's memory-pressure response drops these cached previews automatically when memory is tight, and POST /api/console/free_memory reclaims them on demand — they simply re-render the next time you open a frame.
Writer
We write FITS files when capturing through the Console. Files are BITPIX 16 (unsigned via BZERO=32768), NAXIS 2, and compatible with our own reader as well as ASTAP, PixInsight, and AstroPy. Headers are populated from the capture context, including:
- Frame —
OBJECT,IMAGETYP(LIGHT/FLAT/DARK/BIAS),EXPTIME/EXPOSURE,FILTER,DATE-OBS(UTC) - Camera —
GAIN,OFFSET,XBINNING,YBINNING,CCD-TEMP,SET-TEMP,XPIXSZ,YPIXSZ,SENSOR,INSTRUME, andBAYERPAT(plusXBAYROFF/YBAYROFF) for colour/DSLR sensors - Optics / mount —
FOCALLEN,TELESCOP,OBJCTRA/OBJCTDEC(andRA/DEC),OBJCTALT,AIRMASS,PIERSIDE - Focuser —
FOCPOS/FOCUSPOS,FOCTEMP - Site / provenance —
SITELAT,SITELONG,SITEELEV,OBSERVER,CREATOR, and aHISTORYtrail
Two related camera settings affect these headers:
- Write AIRMASS header — computes
AIRMASSandOBJCTALTfrom the mount pointing, your[site]coordinates and the time (stacking software weights frames by airmass). - Hide personal info in FITS — strips
OBSERVERand theSITELAT/SITELONGlocation cards, for sharing frames publicly.AIRMASSis still written.