Commit 976d4bd9 authored by vertighel's avatar vertighel
Browse files

debug notturno con leonardo e massimiliano

parent 1f672ea9
Loading
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#                half_frame(); omit to use the device's built-in default
# small_frame  — [px] xstart,ystart,xend,yend at binning 1, used by
#                small_frame(); omit to use the device's built-in default
# background_estimate — [ADU] initial guess for fit_star()'s background
#                model; depends on sensor bias/bit-depth, tune on real
#                data. Omit to fall back to 900 (scicam1/STX level).
# #########################################################

##############
@@ -41,8 +44,6 @@ power_api = /scicam2/power
fits_path   = fits/scicam2.fits
pixel_scale = 0.283
orientation = -60
# spettrografo long-slit: la finestra ritaglia solo in Y, tutta la
# larghezza del sensore (KAI-11002, 4008x2672) resta leggibile.
half_frame  = 0, 668, 4007, 2004
small_frame = 0, 1500, 4007, 2000

@@ -53,8 +54,6 @@ power_api = /telescope/power
fits_path   = fits/scicam3.fits
pixel_scale = 0.283
orientation = -60
# stesso sensore KAI-11002 di scicam2 (4008x2672), ma qui centrato su
# entrambi gli assi come STX: camera scientifica, non slit.
half_frame  = 1002, 668, 3006, 2004
small_frame = 1803, 1202, 2203, 1469

@@ -71,6 +70,7 @@ device = tec1
has_loop    = true
pixel_scale = 0.283
orientation = -60
background_estimate = 900

[teccam2]
role        = tec
@@ -79,8 +79,9 @@ power_api = /telescope/power
fits_path   = fits/teccam2.fits
device      = tec2
has_loop    = true
pixel_scale = 0.283
pixel_scale = 0.160
orientation = -60
background_estimate = 10

[teccam3]
role        = tec
@@ -89,5 +90,6 @@ power_api = /telescope/power
fits_path   = fits/teccam3.fits
device      = tec3
has_loop    = true
pixel_scale = 0.283
pixel_scale = 0.160
orientation = -60
background_estimate = 10
+16 −0
Original line number Diff line number Diff line
@@ -46,6 +46,22 @@ def camera_optics(viewer_key):
    return scale, orientation


def camera_star_estimate(viewer_key):
    """Return background_estimate [ADU] for a cam_id from cameras.ini.

    Initial guess for fit_star()'s background model; depends on sensor
    bias/bit-depth. Falls back to 900 (scicam1/STX level) if the key is
    absent or not configured.
    """

    if not viewer_key:
        return 900.0
    cfg = configparser.ConfigParser()
    cfg.read(_CAMERAS_INI)

    return cfg.getfloat(viewer_key, 'background_estimate', fallback=900.0)


def camera_frame(viewer_key, name):
    """Return (x0, y0, x1, y1) unbinned px for 'half_frame'/'small_frame'
    from cameras.ini, or None if the key is absent or not configured.
+37 −17
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
# System modules
import argparse
import asyncio
import time

# Third-party modules
import numpy as np
@@ -16,7 +17,8 @@ from astropy.wcs import WCS

# Custom modules
from noctua import devices
from noctua.config.constants import alt, camera_optics, lat, lon, viewer_fits_path
from noctua.config.constants import (alt, camera_optics, camera_star_estimate,
                                     dateobs, lat, lon, viewer_fits_path)
from noctua.utils.analysis import fit_star
from noctua.utils.logger import log

@@ -42,6 +44,7 @@ class Guider:
        self.last_correction = [0.0, 0.0]
        self._task           = None
        self._stick_target   = None
        self._last_frame_time = None

        self.ao_pos               = [50.0, 50.0]
        self.ao_offload_threshold = 90
@@ -108,6 +111,7 @@ class Guider:
        self.active            = True
        self.error             = []
        self._stick_target     = None
        self._last_frame_time  = None
        self._task             = asyncio.get_running_loop().create_task(self._loop())
        log.info(f"Guider started: camera={self.camera} actuator={self.actuator} target={self.target}")

@@ -156,8 +160,9 @@ class Guider:
        x0, x1 = max(cx - half, 0), min(cx + half, nx)
        y0, y1 = max(cy - half, 0), min(cy + half, ny)

        background = camera_star_estimate(getattr(cam, "_viewer_key", None))
        try:
            fitted = fit_star(data[y0:y1, x0:x1])
            fitted = fit_star(data[y0:y1, x0:x1], background_estimation=background)

        except Exception as e:
            msg = f"fit_star: {e}"
@@ -256,24 +261,39 @@ class Guider:
        self.ao_pos = [50.0, 50.0]

    def _acquire(self, cam):
        """Read the latest FITS frame (and header) for this camera from disk.
        """Read the next FITS frame (and header) for this camera from disk.

        The guider never drives acquisition itself — it only reads whatever
        the camera's own loop (or, for scicam, the last Expose) last wrote.
        Freshness is the caller's responsibility: guiding is only meaningful
        while something else keeps producing new frames.
        It blocks here (this runs in a worker thread, so a plain sleep is
        fine) until a frame with a new DATE-OBS shows up, so a correction is
        never computed twice off the same, still-uncorrected image.
        """

        fits_path = viewer_fits_path(getattr(cam, "_viewer_key", None))
        timeout   = max(3.0, 3 * getattr(cam, "loop_exposure", 1.0))
        deadline  = time.monotonic() + timeout

        while True:
            try:
                data, header = fits.getdata(fits_path, header=True)
            return data.astype(np.float32), header
            except Exception as e:
                msg = f"acquire: {e}"
                log.error(f"Guider: {msg}")
                self.error.append(msg)
                return None, None

            frame_time = header.get(dateobs)
            if frame_time != self._last_frame_time:
                self._last_frame_time = frame_time
                return data.astype(np.float32), header

            if time.monotonic() > deadline:
                log.warning(f"Guider: no new frame from '{self.camera}' within {timeout:.1f}s")
                return None, None

            time.sleep(0.1)

    def _pixel_to_offset(self, cam, header, nx, ny, star_x, star_y, tgt_x, tgt_y):

        coordinates = devices.tel.coordinates