Skip to content

Commit e9de813

Browse files
committed
Add solve time to the guider solution metadata and output files
1 parent c905d24 commit e9de813

File tree

4 files changed

+24
-1
lines changed

4 files changed

+24
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
* Back to using the official `sep` package from `sep-developers/sep` now that it's maintained again.
88
* Apply rotation and translation corrections independently, starting with rotation until the rotator has converged. The first correction, however, applies both rotation and translation at once to minimize the number of telescope offsets.
9+
* Add solve time to the guider solution metadata and output files.
910

1011

1112
## 0.7.0 - February 27, 2025

src/lvmguider/dataclasses.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class CameraSolution(BaseSolution):
114114
ref_frame: pathlib.Path | None = None
115115
wcs_mode: WCS_MODE_T = "none"
116116
guider_version: Version = Version("0.0.0")
117+
solve_time: float | None = None
117118
hdul: fits.HDUList | None = None
118119

119120
@classmethod
@@ -149,6 +150,7 @@ def open(cls, file: str | pathlib.Path):
149150
with warnings.catch_warnings():
150151
warnings.simplefilter("ignore", category=FITSFixedWarning)
151152
solved = proc["SOLVED"]
153+
solve_time = proc.get("SOLVET", None)
152154
wcs_mode = proc["WCSMODE"].lower()
153155
wcs = WCS(proc) if solved and wcs_mode != "none" else None
154156

@@ -172,6 +174,7 @@ def open(cls, file: str | pathlib.Path):
172174
matched=len(sources.ra.dropna()) > 0 if sources is not None else False,
173175
ref_frame=ref_frame,
174176
guider_version=guiderv,
177+
solve_time=solve_time,
175178
hdul=hdul,
176179
)
177180

@@ -386,6 +389,15 @@ def open(cls, file: str | pathlib.Path, dirname: str | pathlib.Path | None = Non
386389
guider_version=guiderv,
387390
)
388391

392+
@property
393+
def solve_time(self):
394+
"""Returns the total time required to solve all cameras.."""
395+
396+
if all(cs.solve_time is None for cs in self.solutions):
397+
return None
398+
399+
return max([cs.solve_time or 0.0 for cs in self.solutions])
400+
389401

390402
@dataclass(kw_only=True)
391403
class FrameData:
@@ -597,6 +609,7 @@ def guider_data(self):
597609
pa=numpy.float32(pa),
598610
zero_point=numpy.float32(gs.zero_point),
599611
solved=bool(gs.solved),
612+
solve_time=numpy.float32(gs.solve_time),
600613
n_cameras_solved=int(gs.n_cameras_solved),
601614
guide_mode=gs.guide_mode,
602615
x_ff_pixel=numpy.float32(gs.guide_pixel[0]),

src/lvmguider/etc/datamodel.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ GUIDERDATA_HEADER:
9090
DIRNAME: [null, 'Original file directory']
9191
SOURCESF: [null, 'Sources file']
9292
SOLVED: [False, 'Astrometric solution found?']
93+
SOLVET: [null, '[s] Time needed to solve the frame']
9394
NCAMSOL: [0, 'Number of cameras combined for the WCS']
9495
XFFPIX: [null, 'The x pixel of the full frame']
9596
ZFFPIX: [null, 'The z pixel of the full frame']
@@ -146,6 +147,7 @@ GUIDERDATA_FRAME:
146147
mjd: 'int32[pyarrow]'
147148
date_obs: 'string[pyarrow]'
148149
solved: 'bool[pyarrow]'
150+
solve_time: 'f4[pyarrow]'
149151
n_cameras_solved: 'int8[pyarrow]'
150152
guide_mode: 'string[pyarrow]'
151153
fwhm: 'f4[pyarrow]'

src/lvmguider/guider.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import asyncio
1212
import pathlib
13+
import time
1314

1415
from typing import TYPE_CHECKING
1516

@@ -383,6 +384,8 @@ async def solve_camera(
383384
):
384385
"""Astrometrically solves a single camera using astrometry.net or k-d tree."""
385386

387+
t0 = time.time()
388+
386389
file = pathlib.Path(file)
387390
frameno = get_frameno(file)
388391
hdul = fits.open(str(file))
@@ -491,6 +494,8 @@ async def solve_camera(
491494
zp = estimate_zeropoint(data, sources)
492495
sources.update(zp)
493496

497+
solve_time = round(time.time() - t0, 3)
498+
494499
camera_solution = CameraSolution(
495500
frameno=frameno,
496501
camera=camname,
@@ -501,6 +506,7 @@ async def solve_camera(
501506
matched=matched,
502507
ref_frame=ref_frame if wcs is not None else None,
503508
telescope=self.telescope,
509+
solve_time=solve_time,
504510
)
505511

506512
if camera_solution.solved is False:
@@ -730,7 +736,8 @@ async def update_fits(self, guider_solution: GuiderSolution):
730736
gheader["PAFIELD"] = numpy.round(self.field_centre[2], 4)
731737
gheader["XFFPIX"] = guider_solution.guide_pixel[0]
732738
gheader["ZFFPIX"] = guider_solution.guide_pixel[1]
733-
gheader["SOLVED"] = guider_solution.solved
739+
gheader["SOLVED"] = nan_or_none(guider_solution.solved, 3)
740+
gheader["SOLVET"] = guider_solution.solve_time
734741
gheader["NCAMSOL"] = guider_solution.n_cameras_solved
735742
gheader["RAMEAS"] = nan_or_none(guider_solution.pointing[0], 6)
736743
gheader["DECMEAS"] = nan_or_none(guider_solution.pointing[1], 6)

0 commit comments

Comments
 (0)