Coverage for python/lsst/daf/butler/registry/obscore/default_spatial.py: 100%
34 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-07 00:58 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-07 00:58 -0700
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22from __future__ import annotations
24__all__ = ["DefaultSpatialObsCorePlugin"]
26from collections.abc import Mapping
27from typing import TYPE_CHECKING, Any, Optional
29import sqlalchemy
30from lsst.sphgeom import ConvexPolygon, LonLat, Region
32from ...core import ddl
33from ._spatial import RegionTypeError, SpatialObsCorePlugin
35if TYPE_CHECKING:
36 from ..interfaces import Database
37 from ._records import Record
39# Columns added/filled by this plugin
40_COLUMNS = (
41 ddl.FieldSpec(name="s_ra", dtype=sqlalchemy.Float, doc="Central right ascension, ICRS (deg)"),
42 ddl.FieldSpec(name="s_dec", dtype=sqlalchemy.Float, doc="Central declination, ICRS (deg)"),
43 ddl.FieldSpec(name="s_fov", dtype=sqlalchemy.Float, doc="Diameter (bounds) of the covered region (deg)"),
44 ddl.FieldSpec(
45 name="s_region",
46 dtype=sqlalchemy.String,
47 length=65535,
48 doc="Sky region covered by the data product (expressed in ICRS frame)",
49 ),
50)
53class DefaultSpatialObsCorePlugin(SpatialObsCorePlugin):
54 """Class for a spatial ObsCore plugin which creates standard spatial
55 obscore columns.
56 """
58 def __init__(self, *, name: str, config: Mapping[str, Any]):
59 self._name = name
61 @classmethod
62 def initialize(
63 cls, *, name: str, config: Mapping[str, Any], db: Optional[Database]
64 ) -> SpatialObsCorePlugin:
65 # docstring inherited.
66 return cls(name=name, config=config)
68 def extend_table_spec(self, table_spec: ddl.TableSpec) -> None:
69 # docstring inherited.
70 table_spec.fields.update(_COLUMNS)
72 def make_records(self, region: Optional[Region]) -> Optional[Record]:
73 # docstring inherited.
75 if region is None:
76 return None
78 record: Record = {}
80 # Get spatial parameters from the bounding circle.
81 circle = region.getBoundingCircle()
82 center = LonLat(circle.getCenter())
83 record["s_ra"] = center.getLon().asDegrees()
84 record["s_dec"] = center.getLat().asDegrees()
85 record["s_fov"] = circle.getOpeningAngle().asDegrees() * 2
87 if isinstance(region, ConvexPolygon):
88 poly = ["POLYGON ICRS"]
89 for vertex in region.getVertices():
90 lon_lat = LonLat(vertex)
91 poly += [
92 f"{lon_lat.getLon().asDegrees():.6f}",
93 f"{lon_lat.getLat().asDegrees():.6f}",
94 ]
95 record["s_region"] = " ".join(poly)
96 else:
97 raise RegionTypeError(f"Unexpected region type: {type(region)}")
99 return record