Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyobs/modules/pointing/guidingstatistics/pixeloffset.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def _build_header(self, data: list[tuple[float, float]]) -> dict[str, FitsHeader
rms = self._calc_rms(data)

if rms is not None:
header["GUIDING RMS1"] = FitsHeaderEntry(float(rms[0]), "RMS for guiding on axis 1")
header["GUIDING RMS2"] = FitsHeaderEntry(float(rms[1]), "RMS for guiding on axis 2")
header["HIERARCH GUIDING RMS1"] = FitsHeaderEntry(float(rms[0]), "RMS for guiding on axis 1")
header["HIERARCH GUIDING RMS2"] = FitsHeaderEntry(float(rms[1]), "RMS for guiding on axis 2")

return header

Expand Down
2 changes: 1 addition & 1 deletion pyobs/modules/pointing/guidingstatistics/skyoffsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def _build_header(self, data: list[float]) -> dict[str, FitsHeaderEntry]:
rms = self._calc_rms(data)

if rms is not None:
header["GUIDING RMS"] = FitsHeaderEntry(float(rms), "RMS for guiding on sky")
header["HIERARCH GUIDING RMS"] = FitsHeaderEntry(float(rms), "RMS for guiding on sky")

return header

Expand Down
2 changes: 1 addition & 1 deletion pyobs/modules/pointing/guidingstatistics/uptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _build_header(self, data: list[tuple[bool | None, datetime]]) -> dict[str, F
data.append((None, now))

uptime_percentage = self._calc_uptime_percentage(data)
return {"GUIDING UPTIME": FitsHeaderEntry(uptime_percentage, "Time the guiding loop was closed [%]")}
return {"HIERARCH GUIDING UPTIME": FitsHeaderEntry(uptime_percentage, "Time the guiding loop was closed [%]")}

def _get_session_data(self, input_data: bool) -> tuple[bool | None, datetime] | None:
now = datetime.now()
Expand Down
14 changes: 13 additions & 1 deletion pyobs/utils/curvefit.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,20 @@ def fit_hyperbola(x_arr: list[float], y_arr: list[float], y_err: list[float]) ->
p0 = [a, b, c]

# fit
#
# absolute_sigma=True is required here: without it, curve_fit treats y_err as only
# relative weights and rescales the returned covariance matrix so that the fit's
# reduced chi-square equals 1. That makes the reported variance reflect how well the
# hyperbola shape matches this particular focus run rather than the actual per-point
# measurement uncertainty passed in via y_err, which silently miscalibrates every
# downstream error estimate.
coeffs, cov = curve_fit(
lambda xx, aa, bb, cc: bb * np.sqrt((xx - cc) ** 2 / aa**2 + 1.0), x_arr, y_arr, sigma=y_err, p0=p0
lambda xx, aa, bb, cc: bb * np.sqrt((xx - cc) ** 2 / aa**2 + 1.0),
x_arr,
y_arr,
sigma=y_err,
p0=p0,
absolute_sigma=True,
)

# return result
Expand Down
7 changes: 6 additions & 1 deletion pyobs/utils/focusseries/photometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ def fit_focus(self) -> tuple[float, float]:

# fit focus
try:
foc, err = fit_hyperbola(focus, r, rerr)
# fit_hyperbola returns (focus, variance), not (focus, error) -- take the
# square root, otherwise the reported error is actually the variance and is
# systematically too small (e.g. 0.01 mm true error would be reported as
# 0.0001).
foc, var = fit_hyperbola(focus, r, rerr)
err = np.sqrt(var)
except (RuntimeError, RuntimeWarning):
raise ValueError("Could not find best focus.")

Expand Down
17 changes: 9 additions & 8 deletions pyobs/utils/focusseries/projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,15 @@ def fit_focus(self) -> tuple[float, float]:

# fit focus
try:
xfoc, xerr = fit_hyperbola(focus, xfwhm, xsig)
yfoc, yerr = fit_hyperbola(focus, yfwhm, ysig)

# weighted mean
xerr = np.sqrt(xerr)
yerr = np.sqrt(yerr)
foc = (xfoc / xerr + yfoc / yerr) / (1.0 / xerr + 1.0 / yerr)
err = 2.0 / (1.0 / xerr + 1.0 / yerr)
# fit_hyperbola returns (focus, variance) for each axis
xfoc, xvar = fit_hyperbola(focus, xfwhm, xsig)
yfoc, yvar = fit_hyperbola(focus, yfwhm, ysig)

# inverse-variance weighted mean of the two independent axis estimates
xweight = 1.0 / xvar
yweight = 1.0 / yvar
foc = (xfoc * xweight + yfoc * yweight) / (xweight + yweight)
err = np.sqrt(1.0 / (xweight + yweight))
except (RuntimeError, RuntimeWarning):
raise ValueError("Could not find best focus.")

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "pyobs-core"
version = "2.0.0.dev26"
version = "2.0.0.dev27"
description = "robotic telescope software"
authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
requires-python = ">=3.11"
Expand Down
2 changes: 1 addition & 1 deletion tests/modules/pointing/test_guiding_statistic_uptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test_end_to_end() -> None:

header = statistic.add_to_header(client, {})

assert header["GUIDING UPTIME"].value == 100.0
assert header["HIERARCH GUIDING UPTIME"].value == 100.0


def test_calc_uptime_percentage() -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ def test_end_to_end(mock_meta_image) -> None:

header = statistic.add_to_header(client, {})

assert header["GUIDING RMS1"].value == 1.0
assert header["GUIDING RMS1"].comment == "RMS for guiding on axis 1"
assert header["GUIDING RMS2"].value == 1.0
assert header["GUIDING RMS2"].comment == "RMS for guiding on axis 2"
assert header["HIERARCH GUIDING RMS1"].value == 1.0
assert header["HIERARCH GUIDING RMS1"].comment == "RMS for guiding on axis 1"
assert header["HIERARCH GUIDING RMS2"].value == 1.0
assert header["HIERARCH GUIDING RMS2"].comment == "RMS for guiding on axis 2"


def test_build_header_to_few_values() -> None:
Expand Down
4 changes: 2 additions & 2 deletions tests/modules/pointing/test_guiding_statistics_sky_offset.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def test_end_to_end(mock_meta_image) -> None:

header = statistic.add_to_header(client, {})

np.testing.assert_almost_equal(header["GUIDING RMS"].value, 10.0)
assert header["GUIDING RMS"].comment == "RMS for guiding on sky"
np.testing.assert_almost_equal(header["HIERARCH GUIDING RMS"].value, 10.0)
assert header["HIERARCH GUIDING RMS"].comment == "RMS for guiding on sky"


def test_build_header_to_few_values() -> None:
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading