Coverage for python / lsst / images / fields / _concrete.py: 41%
29 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-15 08:44 +0000
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-15 08:44 +0000
1# This file is part of lsst-images.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
12from __future__ import annotations
14__all__ = (
15 "Field",
16 "FieldSerializationModel",
17 "field_from_legacy",
18 "field_from_legacy_background",
19)
21from typing import TYPE_CHECKING, Annotated, Any
23import astropy.units
24import pydantic
26from ._chebyshev import ChebyshevField, ChebyshevFieldSerializationModel
27from ._product import ProductField, ProductFieldSerializationModel
28from ._spline import SplineField, SplineFieldSerializationModel
29from ._sum import SumField, SumFieldSerializationModel
31if TYPE_CHECKING:
32 try:
33 from lsst.afw.math import BackgroundList as LegacyBackgroundList
34 from lsst.afw.math import BackgroundMI as LegacyBackground
35 from lsst.afw.math import BoundedField as LegacyBoundedField
36 except ImportError:
37 type LegacyBoundedField = Any # type: ignore[no-redef]
38 type LegacyBackground = Any # type: ignore[no-redef]
39 type LegacyBackgroundList = Any # type: ignore[no-redef]
42# Since Sphinx can't handle doc links to type aliases, whenever we annotate
43# a type as `Field`, we override the docs to say `BaseField`, since
44# `BaseField` is a base class that serves as a much more useful doc link, and
45# because the hierarchy is closed they're equivalent. But we have to use
46# `Field` in the type annotations because there's no way to declare to MyPy
47# et all that the hierarchy is closed.
49type Field = ChebyshevField | ProductField | SplineField | SumField
50type FieldSerializationModel = Annotated[
51 ChebyshevFieldSerializationModel
52 | ProductFieldSerializationModel
53 | SplineFieldSerializationModel
54 | SumFieldSerializationModel,
55 pydantic.Field(discriminator="field_type"),
56]
59ProductFieldSerializationModel.model_rebuild()
60SumFieldSerializationModel.model_rebuild()
63def field_from_legacy(
64 legacy_bounded_field: LegacyBoundedField, unit: astropy.units.UnitBase | None = None
65) -> Field:
66 """Convert a legacy `lsst.afw.math.BoundedField` subclass to a `BaseField`
67 object.
68 """
69 from lsst.afw.math import ChebyshevBoundedField, ProductBoundedField
71 match legacy_bounded_field:
72 case ChebyshevBoundedField():
73 return ChebyshevField.from_legacy(legacy_bounded_field, unit=unit)
74 case ProductBoundedField():
75 return ProductField.from_legacy(legacy_bounded_field, unit=unit)
76 case _:
77 raise NotImplementedError(
78 f"Conversion from {type(legacy_bounded_field).__name__} is not supported."
79 )
82def field_from_legacy_background(
83 legacy_background: LegacyBackground | LegacyBackgroundList, unit: astropy.units.UnitBase | None = None
84) -> Field:
85 """Convert a legacy `lsst.afw.math.Background` or
86 `lsst.afw.math.BackgroundList` instance to a `BaseField` object.
87 """
88 from lsst.afw.math import ApproximateControl, BackgroundList
90 if isinstance(legacy_background, BackgroundList):
91 return SumField.from_legacy_background(legacy_background)
93 approx_control = legacy_background.getBackgroundControl().getApproximateControl()
94 if approx_control.getStyle() == ApproximateControl.UNKNOWN:
95 return SplineField.from_legacy_background(legacy_background, unit=unit)
96 else:
97 return ChebyshevField.from_legacy_background(legacy_background, unit=unit)