Skip to content

Commit

Permalink
Add get-etr command (#25)
Browse files Browse the repository at this point in the history
* Add ETR command

* Some fixes

* Update changelog
  • Loading branch information
albireox authored Aug 26, 2024
1 parent 1e18615 commit 1fb0224
Show file tree
Hide file tree
Showing 7 changed files with 692 additions and 658 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Next version

### 🚀 Added

* [#25](https://github.com/sdss/lvmscp/pull/25) Added new command `get-etr` which returns the estimated remaining time for the exposure including readout.


## 0.9.0 - July 14, 2024

### 🔥 Breaking changes
Expand Down
1,263 changes: 612 additions & 651 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ fitsio = ["fitsio"]

[tool.poetry.dev-dependencies]
ipython = ">=8.17.2"
flake8 = ">=3.7.9"
doc8 = ">=0.8.0"
isort = ">=4.3.21"
ipdb = ">=0.12.3"
rstcheck = ">=3.3.1"
ruff = ">=0.5.1"
Expand All @@ -63,11 +61,6 @@ sphinx-autobuild = ">=2021.3.14"
sphinx-copybutton = ">=0.3.3"
sphinx-click = ">=3.0.1"

[tool.black]
line-length = 88
target-version = ['py312']
fast = true

[tool.ruff]
line-length = 88
target-version = 'py312'
Expand Down
1 change: 1 addition & 0 deletions python/lvmscp/actor/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def __init__(self, *args, **kwargs):

# Just for typing.
self.controllers: dict[str, SCPController]
self.exposure_delegate: LVMExposeDelegate

super().__init__(*args, schema=schema, version=__version__, **kwargs)

Expand Down
1 change: 1 addition & 0 deletions python/lvmscp/actor/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@

from archon.actor.commands import parser

from .etr import get_etr
from .focus import focus
from .hardware_status import hardware_status
30 changes: 30 additions & 0 deletions python/lvmscp/actor/commands/etr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author: José Sánchez-Gallego ([email protected])
# @Date: 2024-08-26
# @Filename: etr.py
# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause)

from __future__ import annotations

from typing import TYPE_CHECKING

from . import parser


if TYPE_CHECKING:
from lvmscp.actor import CommandType


@parser.command()
async def get_etr(command: CommandType, *_):
"""Gets the ETR of the exposure."""

delegate = command.actor.exposure_delegate
etr = delegate.get_etr()

if etr is None:
command.warning("ETR not available. The controllers may be idle.")

command.finish(etr=etr)
41 changes: 41 additions & 0 deletions python/lvmscp/delegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from __future__ import annotations

import asyncio
import time

from typing import TYPE_CHECKING, Any, Literal

Expand All @@ -19,6 +20,7 @@
from astropy.utils.iers import conf

from archon.actor import ExposureDelegate
from archon.controller import ControllerStatus
from sdsstools.time import get_sjd

from lvmscp import __version__
Expand All @@ -39,6 +41,9 @@
iers.earth_orientation_table.set(iers_a)


EXPECTED_READOUT_TIME: float = 55


class LVMExposeDelegate(ExposureDelegate["SCPActor"]):
"""Expose delegate for LVM."""

Expand Down Expand Up @@ -384,3 +389,39 @@ async def get_telescope_info(self):
else:
foc_position = numpy.round(foc_cmd.replies.get("Position"), 2)
self.header_data[f"TE{telescope.upper()}FO"] = foc_position

def get_etr(self):
"""Returns the estimated time remaining including readout, or null if idle."""

edata = self.expose_data
readout_time = EXPECTED_READOUT_TIME

if edata is None or edata.controllers is None:
return None

IDLE = ControllerStatus.IDLE
EXPOSING = ControllerStatus.EXPOSING
READING = ControllerStatus.READING
PENDING = ControllerStatus.READOUT_PENDING

status = [c.status for c in edata.controllers]
if all([s & IDLE for s in status]) and not any([s & PENDING for s in status]):
return None

if edata.start_time is None:
return None

if all([s & EXPOSING for s in status]):
start_time = edata.start_time.unix
elapsed = time.time() - start_time
return round(max(0, edata.exposure_time - elapsed + readout_time), 1)

if all([s & PENDING for s in status]):
return readout_time

if any([s & READING for s in status]) and edata.end_time:
end_time = edata.end_time.unix
elapsed = time.time() - end_time
return round(max(0, readout_time - elapsed), 1)

return None

0 comments on commit 1fb0224

Please sign in to comment.