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) noctua/config/api.ini +25 −0 Original line number Diff line number Diff line Loading @@ -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 ############## Loading Loading @@ -283,3 +307,4 @@ device = ipcam # [/environment/internal/reception] # resource = Temperature # device = rec noctua/config/devices.ini +11 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -90,11 +101,6 @@ outlet = 7 # node = ASCOM_REMOTE # outlet = 3 # [cam] # module = stx # class = Camera # node = STX # [cab] # module = siemens # class = Switch Loading pyproject.toml +2 −42 Original line number Diff line number Diff line Loading @@ -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" }, ] Loading Loading @@ -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", ] Loading Loading @@ -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" 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)
noctua/config/api.ini +25 −0 Original line number Diff line number Diff line Loading @@ -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 ############## Loading Loading @@ -283,3 +307,4 @@ device = ipcam # [/environment/internal/reception] # resource = Temperature # device = rec
noctua/config/devices.ini +11 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -90,11 +101,6 @@ outlet = 7 # node = ASCOM_REMOTE # outlet = 3 # [cam] # module = stx # class = Camera # node = STX # [cab] # module = siemens # class = Switch Loading
pyproject.toml +2 −42 Original line number Diff line number Diff line Loading @@ -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" }, ] Loading Loading @@ -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", ] Loading Loading @@ -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" Loading