Coverage for python/lsst/daf/butler/registry/obscore/default_spatial.py: 95%
34 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 02:52 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-30 02:52 -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 software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28from __future__ import annotations
30__all__ = ["DefaultSpatialObsCorePlugin"]
32from collections.abc import Mapping
33from typing import TYPE_CHECKING, Any
35import sqlalchemy
36from lsst.sphgeom import ConvexPolygon, LonLat, Region
38from ... import ddl
39from ._spatial import RegionTypeError, SpatialObsCorePlugin
41if TYPE_CHECKING:
42 from ..interfaces import Database
43 from ._records import Record
45# Columns added/filled by this plugin
46_COLUMNS = (
47 ddl.FieldSpec(name="s_ra", dtype=sqlalchemy.Float, doc="Central right ascension, ICRS (deg)"),
48 ddl.FieldSpec(name="s_dec", dtype=sqlalchemy.Float, doc="Central declination, ICRS (deg)"),
49 ddl.FieldSpec(name="s_fov", dtype=sqlalchemy.Float, doc="Diameter (bounds) of the covered region (deg)"),
50 ddl.FieldSpec(
51 name="s_region",
52 dtype=sqlalchemy.String,
53 length=65535,
54 doc="Sky region covered by the data product (expressed in ICRS frame)",
55 ),
56)
59class DefaultSpatialObsCorePlugin(SpatialObsCorePlugin):
60 """Class for a spatial ObsCore plugin which creates standard spatial
61 obscore columns.
63 Parameters
64 ----------
65 name : `str`
66 The name.
67 config : `~collections.abc.Mapping` [`str`, `~typing.Any`]
68 ObsCore configuration.
69 """
71 def __init__(self, *, name: str, config: Mapping[str, Any]):
72 self._name = name
74 @classmethod
75 def initialize(cls, *, name: str, config: Mapping[str, Any], db: Database | None) -> SpatialObsCorePlugin:
76 # docstring inherited.
77 return cls(name=name, config=config)
79 def extend_table_spec(self, table_spec: ddl.TableSpec) -> None:
80 # docstring inherited.
81 table_spec.fields.update(_COLUMNS)
83 def make_records(self, region: Region | None) -> Record | None:
84 # docstring inherited.
86 if region is None:
87 return None
89 record: Record = {}
91 # Get spatial parameters from the bounding circle.
92 circle = region.getBoundingCircle()
93 center = LonLat(circle.getCenter())
94 record["s_ra"] = center.getLon().asDegrees()
95 record["s_dec"] = center.getLat().asDegrees()
96 record["s_fov"] = circle.getOpeningAngle().asDegrees() * 2
98 if isinstance(region, ConvexPolygon): 98 ↛ 108line 98 didn't jump to line 108, because the condition on line 98 was never false
99 poly = ["POLYGON ICRS"]
100 for vertex in region.getVertices():
101 lon_lat = LonLat(vertex)
102 poly += [
103 f"{lon_lat.getLon().asDegrees():.6f}",
104 f"{lon_lat.getLat().asDegrees():.6f}",
105 ]
106 record["s_region"] = " ".join(poly)
107 else:
108 raise RegionTypeError(f"Unexpected region type: {type(region)}")
110 return record