Commit 6c6807bc authored by vertighel's avatar vertighel
Browse files

Added stage to APIs

parent b0af948b
Loading
Loading
Loading
Loading
Loading

noctua/api/stage.py

0 → 100644
+88 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''REST API for PI Mercury Linear Stage operations'''

# Custom modules
from .baseresource import BaseResource

class Position(BaseResource):
    """Manage the absolute position of the stage in mm."""

    async def get(self):
        """Retrieve the current stage position."""
        res = await self.run_blocking(lambda: self.dev.position)
        return self.make_response(res)

    async def put(self):
        """Move the stage to an absolute position."""
        target = await self.get_payload() # expected float
        def action():
            self.dev.position = target
            return self.dev.position
        res = await self.run_blocking(action)
        return self.make_response(res)


class Named(BaseResource):
    """Manage named positions (e.g., 'imaging', 'spectroscopy')."""

    async def get(self):
        """Get the name of the current position if matched."""
        res = await self.run_blocking(lambda: self.dev.named)
        return self.make_response(res)

    async def put(self):
        """Move the stage to a named position."""
        target_name = await self.get_payload() # expected string
        def action():
            self.dev.named = target_name
            return self.dev.named
        
        try:
            res = await self.run_blocking(action)
            return self.make_response(res)
        except KeyError as e:
            return self.make_response(None, errors=[str(e)], status_code=400)


class Initialization(BaseResource):
    """Handle stage homing and status."""

    async def get(self):
        """Check if the stage is initialized and referenced."""
        res = await self.run_blocking(lambda: self.dev.is_init)
        return self.make_response(res)

    async def post(self):
        """Start the initialization (FNL/FPL) sequence."""
        await self.run_blocking(self.dev.init)
        res = await self.run_blocking(lambda: self.dev.is_init)
        return self.make_response(res)


class Movement(BaseResource):
    """Monitor stage motion status."""

    async def get(self):
        """Check if the stage is currently moving."""
        res = await self.run_blocking(lambda: self.dev.is_moving)
        return self.make_response(res)


class Limits(BaseResource):
    """Manage software movement limits."""

    async def get(self):
        """Retrieve the software limits [min, max]."""
        res = await self.run_blocking(lambda: self.dev.limits)
        return self.make_response(res)

    async def put(self):
        """Set new software limits."""
        target_limits = await self.get_payload() # expected [float, float]
        def action():
            self.dev.limits = target_limits
            return self.dev.limits
        res = await self.run_blocking(action)
        return self.make_response(res)
+25 −0
Original line number Diff line number Diff line
@@ -248,6 +248,30 @@ device = cam
# resource = Status
# device = cam

##############
# stage
##############

[/stage/position]
resource = Position
device = stage

[/stage/named]
resource = Named
device = stage

[/stage/status]
resource = Initialization
device = stage

[/stage/movement]
resource = Movement
device = stage

[/stage/limits]
resource = Limits
device = stage

##############
# webcam
##############
@@ -283,3 +307,4 @@ device = ipcam
# [/environment/internal/reception]
# resource = Temperature
# device = rec
+11 −5
Original line number Diff line number Diff line
@@ -19,6 +19,17 @@ pos_imaging = 120
pos_spectro = 110
pos_echelle = 100

[cam]
module = stx
class = Camera
node = STX

[pdu_cam]
module = netio
class = Switch
node = PDU
outlet = 3

[pdu_teccam]
module = netio
class = Switch
@@ -90,11 +101,6 @@ outlet = 7
# node = ASCOM_REMOTE
# outlet = 3

# [cam]
# module = stx
# class = Camera
# node = STX

# [cab]
# module = siemens
# class = Switch
+2 −42
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "noctua"
version = "0.3.0"
version = "0.3.1"
authors = [
    { name="Davide Ricci", email="davide.ricci@inaf.it" },
]
@@ -36,10 +36,10 @@ dependencies = [
    "opencv-python", # If stream_opencv() in mako.py
    "quart",
    "quart_cors",
    "quart-schema", # validation and Swagger (instead of restx)
    "uvicorn",
    "httpx", # Suggested for async calls to devices

    # "Fourth" party :)
    "PIPython", # for PI - Physik Instrumente controllers
    "vmbpy @ git+https://github.com/alliedvision/VmbPy.git",
]
@@ -82,46 +82,6 @@ import_heading_thirdparty = "Third-party modules"
import_heading_firstparty = "Custom modules" # 'noctua' and its subpackages
import_heading_localfolder = "Other templates"

# This was 'import_heading_templates'.  For isort, LOCALFOLDER is for
# relative imports like 'from . import foo' The 'templates' specific
# heading is unusual for standard isort sections.  Let's map your
# 'Other templates' to how isort handles it.  If 'templates' are truly
# separate from 'noctua' (firstparty), they might need a different
# 'known_' type.  Given 'from templates.basetemplate import ...'  this
# implies 'templates' is a top-level import path or a special case.
# For now, assuming 'Other templates' are relative imports within a
# module, or you want a custom section header.

# sections = "FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER"

# Removed TEMPLATES as it's not standard.  If 'Other templates' are
# from e.g. `noctua.templates.something`, they'd fall under
# FIRSTPARTY.  If they are `from . import foo` they are LOCALFOLDER.
# Let's assume for now that "Other templates" are from
# `noctua.templates` which `known_first_party = "noctua"` should
# cover.  We'll keep the custom heading if that's the intent.

# If you want to enforce the "Other templates" heading specifically
# for imports from `noctua.templates`, you might need to list
# `noctua.templates` in `known_other_templates` (custom known type)
# and add `OTHER_TEMPLATES` to your sections, then map the heading.
# Example for more specific control: known_other_templates =
# "noctua.templates" sections =
# "FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,OTHER_TEMPLATES,LOCALFOLDER"
# import_heading_other_templates = "Other templates"

# Simpler approach assuming 'Other templates' are from 'noctua.templates':
# known_first_party = "noctua"
# sections = "FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER"
# import_heading_stdlib = "System modules"
# import_heading_thirdparty = "Third-party modules"
# import_heading_firstparty = "Custom modules"
# import_heading_localfolder = "Local (relative) imports" # isort default for LOCALFOLDER

# Let's try to achieve your desired heading for templates, assuming
# they are first-party.  We'll make 'templates' a specific first-party
# section.

known_noctua = "noctua"
known_templates_pkg = "noctua.templates" # Treat imports from here specifically
sections = "FUTURE,STDLIB,THIRDPARTY,NOCTUA,TEMPLATES_PKG,LOCALFOLDER"