Commit 9768f561 authored by vertighel's avatar vertighel
Browse files

atik.py: controllare ArtemisImageFailed() e il return code di ArtemisTemperatureSensorInfo



Il lock introdotto nel commit precedente ha eliminato la race condition
sulla temperatura, ma un secondo bug distinto restava mascherato:
in binning 2 il valore di temperatura poteva risultare un sentinella
palesemente errato (es. 399.03°C), identico su più frame consecutivi
quindi non riconducibile a rumore/race.

Causa: ArtemisTemperatureSensorInfo restituisce un codice di errore
mai controllato, e la documentazione SDK richiede di verificare
ArtemisImageFailed() subito dopo che ArtemisImageReady() torna vero,
prima di leggere buffer/dati immagine — nessuno dei due controlli
era presente. Con binning 2 il readout ha una temporizzazione diversa
e può esporre questa finestra.

Ora download() abortisce se ArtemisImageFailed() è vero, e sia
download() che la property temperature ritentano una volta la
lettura della temperatura e, se fallisce ancora, omettono il valore
(CCD-TEMP non scritto / property None) invece di fidarsi di un
codice di errore ignorato.

Co-Authored-By: default avatarClaude Sonnet 5 <noreply@anthropic.com>
parent 5a6b0f29
Loading
Loading
Loading
Loading
Loading
+31 −3
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ from ..utils.image import make_png
from ..utils.logger import log


# AtikDefs.h: ARTEMISERROR enum, ARTEMIS_OK = 0
_ARTEMIS_OK = 0


class ArtemisProperties(ctypes.Structure):
    _fields_ = [
        ("Protocol", ctypes.c_int),
@@ -271,12 +275,23 @@ class Camera(BaseDevice):
        log.debug(f"Getting original data")
        # Poll with the lock released between checks so a long exposure
        # wait doesn't stall other threads' SDK calls (e.g. temperature).
        # Per the SDK docs, ArtemisImageFailed() must be checked right after
        # ArtemisImageReady() returns true, before touching GetImageData()/
        # ImageBuffer() (or any other post-exposure query).
        failed = False
        while True:
            with self._lock:
                ready = self._lib.ArtemisImageReady(h)
                if ready:
                    failed = self._lib.ArtemisImageFailed(h)
            if ready:
                break
            time.sleep(0.1)
        if failed:
            msg = "Atik: image capture failed (ArtemisImageFailed)"
            log.error(msg)
            self.error.append(msg)
            return None

        from pathlib import Path
        from ..config.constants import frame_type as _frame_type
@@ -317,8 +332,16 @@ class Camera(BaseDevice):
                                   "(UTC) Date the exposure was started")

            ccd_temp = ctypes.c_int()
            self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(ccd_temp))
            err = self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(ccd_temp))
            if err != _ARTEMIS_OK:
                # Seen right after a binned exposure: the sensor query can
                # briefly fail before the driver has settled post-readout.
                # One retry is enough in practice.
                err = self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(ccd_temp))
            if err == _ARTEMIS_OK:
                hdr['CCD-TEMP'] = (ccd_temp.value / 100.0, "[C] CCD temperature")
            else:
                log.error(f"Atik: ArtemisTemperatureSensorInfo failed (error {err}), CCD-TEMP omitted")

            flags, level, minl, maxl, setp = [ctypes.c_int() for _ in range(5)]
            self._lib.ArtemisCoolingInfo(h, ctypes.byref(flags), ctypes.byref(level),
@@ -533,7 +556,12 @@ class Camera(BaseDevice):
            h = self._check_connection()
            if not h: return None
            temp = ctypes.c_int()
            self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(temp))
            err = self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(temp))
            if err != _ARTEMIS_OK:
                err = self._lib.ArtemisTemperatureSensorInfo(h, 1, ctypes.byref(temp))
            if err != _ARTEMIS_OK:
                log.error(f"Atik: ArtemisTemperatureSensorInfo failed (error {err})")
                return None
            return temp.value / 100.0

    @temperature.setter