Linux replacement for Alcor System's Windows-only Skywatch software, written for the MMTO's OMEA 8C all-sky camera (a ZWO ASI294MC Pro behind a fisheye, with an Alcor sensor board for temperature, humidity, the dome heater, focus and iris). Modeled on cyclop_linux, and built on skycam_utils for all geometry, photometry and visualization.
-
Acquisition. Takes one exposure after another: auto-exposure by day, and at night a fixed gain of 250 with up to 20 s exposures. The iris switches between f/16 and f/2.8 at Sun -6 deg. Sensor cooling to -5 C is on while the Sun is down. At start-up it homes the focus and drives it to 1320 steps.
-
Skywatch-compatible frames. Each RAW16 frame becomes the same (3, 1411, 1422) int16 cube Skywatch saved: same crop, demosaic, 2x2 binning, mirror and clipping, with the same FITS header, file names and noon-to-noon directories (
/mnt/d/skycam/YYYY-MM-DD/YYYY_MM_DD__HH_MM_SS.fits.bz2). Every skycam_utils calibration (WCS epochs, bad-pixel and horizon masks, zeropoints) stays valid. docs/skywatch.md explains how the format was recovered. -
Display products. The annotated all-sky JPEG, the
Unwrap_panorama and the 24 h keogram, drawn from skycam_utils' calibrated WCS rather than a hand-set circle, so they are distortion-corrected. Star, planet and MMT-pointing overlays come from the same WCS. Hot and bad pixels are replaced by their 5x5 local median using skycam_utils' nearest-date bad-pixel mask, as itsload_alcor_fitsdoes; the FITS files stay raw. Latest copies go to/var/www/html/skycam/ImageLastFTP_AllSKY*.jpg, as before. -
Real-time science. Each night frame (Sun < -12 deg) is passed to skycam_utils in a worker process. It writes star photometry to
<frame>_phot.csv, whichalcor_process_nightreuses rather than re-measures. It also measures calibrated sky brightness in 5 deg cones, and rebuilds the cloud-extinction map from the newest 10 frames as a running average (single-frame star magnitudes scatter by ~0.3 mag). Results go to<day>/omea_live.csvand to redis. -
Redis. These keys are floats, or
nanwhen there is no measurement. All of them are set tonanwhen the night ends.Key Meaning allsky_mv_zenithsurface brightness at the zenith, V mag/arcsec² (5 deg cone median) allsky_mv_tucsonover Tucson, cone at az 0, alt 15 allsky_mv_nogalesover Nogales, cone at az 190, alt 15 allsky_mv_targetat the MMT pointing (mid-exposure; nanwhen parked)allsky_extinction_medianmedian extinction across the sky, V mag. Undetected stars count as the most extinguished; when over half are lost, the largest measured value is published as a floor; when over 90 % are lost (fog, thick cloud) it is 10, meaning opaque ( [science] extinction_opaque_fraction,extinction_opaque)allsky_extinction_lost_fractionshare of the map's stars not detected at all; near 1 means overcast allsky_extinction_targetextinction interpolated from the map at the MMT pointing; nanwhere the map has no stars nearbyallsky_fog_indexper-frame extinction near the zenith (alt > 55) minus low down (20-35), median of 3 frames, mag. About 0 on a clear sky; condensation on the dome starts at its top, so it rises first there allsky_dome_fog1 when the fog index is above 0.2 mag (until it drops below 0.1) with outside humidity above 50 % and at most 5 % of the extinction map's stars lost (cloud hides stars; dome fog at first does not), or with the index held above 0.2 for 30 min whatever the stars lost (cloud moves on; fog stays): the extinction values then measure the dome, not the sky. It also turns the dome heater on The pointing comes from the mount's redis keys, as in skycam-utils'
mmt_extinction_redis.py, which this replaces. -
Sensors. Polls the RS232 board every 30 s and publishes the keys skycam-utils'
tcs_logger.pycron job did (allsky_external_temp,allsky_internal_temp,allsky_hotside_temp,allsky_ccd_temp,allsky_external_rh,allsky_internal_rh), which it replaces, plusallsky_dewpoint(C) andallsky_heater(0/1). It also appends the Skywatch-formatDataOut_Weather.csv. -
Web status at
http://<host>:8081/: the latest image, panorama and keogram, camera, sky and enclosure state, the night's plots, and the log. The sky brightness, extinction and stars-lost plots start afresh at 00:00 UT (17:00 MST), before each sunset. Read-only.
conda activate skycam # the env that has skycam_utils
pip install -e ".[test,redis]"
pytestThe ZWO SDK library (lib/libASICamera2.so.1.37, from ZWO's Linux SDK in this
directory) is found automatically. See docs/hardware.md for
attaching the camera and serial adapter to Linux (usbipd under WSL2), and the
first-light checklist. docs/migration.md is the plan for moving
from WSL2 to native Debian.
cp config.example.toml config.toml # then edit; empty sections keep Skywatch's values
omea -c config.toml camera-info
omea -c config.toml board # firmware, temperatures, heater thresholds
omea -c config.toml run # the real thing
# a dry run: replays a night of Skywatch frames through the whole pipeline,
# 30x faster, writing only under ./data (no redis)
omea run --simulate --archive /mnt/d/skycam/2026-10-09 --start 2026-10-10T01:20 --speed 30
# hardware utilities: they need the board/camera, so stop the service first
# (systemctl --user stop omea). The service writes the [board] heater_* settings
# at start-up, so make lasting heater changes in the config file
omea iris 2.8
omea focus 1320
omea heater --temp 7 --rh 90 --power 50 # automatic mode, thresholds
omea snap --exposure 0.005 -o test.fits.bz2
omea check-geometry test.fits.bz2 <a Skywatch frame of the same scene>The same arrangement as cyclop: a systemd user service under WSL2
(systemd=true and vmIdleTimeout=-1 are already set on this host).
mkdir -p ~/.config/systemd/user
cp systemd/omea.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now omea
journalctl --user -u omea -fThe cooler set point ramps at cooling_ramp (2 C/min) both ways: after sunrise
it warms at that rate and switches off once the cooler is idle.
The keogram so far is kept in the day directory (omea_keogram.npz) and picked
up after a restart. The dome heater runs in dew mode: the
board's automatic thresholds stay as a backstop that works without the
software, and the service switches the heater on early, when the humidity is
above 60 %, rising more than 10 %/h, or the unheated heater ring is within 4 C
of the dew point (see omea/heater.py; the log says why it switched).
- Night gain is fixed. Skywatch lowered the gain under moonlight, which skycam_utils does not correct for; omea shortens the exposure instead. See docs/skywatch.md.
- The FITS header adds keywords and changes none:
DATE-BEG/DATE-END(UT),FRATIO,FOCUSSTP,COOLPWR,SUNALT,MOONALT, and the board's temperatures and humidity, which Skywatch left at 0. - Products are written directly with atomic renames, not FTP'd to localhost.