Loading [MathJax]/extensions/tex2jax.js
LSST Applications 28.0.0,g1653933729+a8ce1bb630,g1a997c3884+a8ce1bb630,g28da252d5a+5bd70b7e6d,g2bbee38e9b+638fca75ac,g2bc492864f+638fca75ac,g3156d2b45e+07302053f8,g347aa1857d+638fca75ac,g35bb328faa+a8ce1bb630,g3a166c0a6a+638fca75ac,g3e281a1b8c+7bbb0b2507,g4005a62e65+17cd334064,g414038480c+5b5cd4fff3,g41af890bb2+4ffae9de63,g4e1a3235cc+0f1912dca3,g6249c6f860+3c3976f90c,g80478fca09+46aba80bd6,g82479be7b0+77990446f6,g858d7b2824+78ba4d1ce1,g89c8672015+f667a5183b,g9125e01d80+a8ce1bb630,ga5288a1d22+2a6264e9ca,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc22bb204ba+78ba4d1ce1,gc28159a63d+638fca75ac,gcf0d15dbbd+32ddb6096f,gd6b7c0dfd1+3e339405e9,gda3e153d99+78ba4d1ce1,gda6a2b7d83+32ddb6096f,gdaeeff99f8+1711a396fd,gdd5a9049c5+b18c39e5e3,ge2409df99d+a5e4577cdc,ge33fd446bb+78ba4d1ce1,ge79ae78c31+638fca75ac,gf0baf85859+64e8883e75,gf5289d68f6+e1b046a8d7,gfa443fc69c+91d9ed1ecf,gfda6b12a05+8419469a56
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
apdbSchema.py
Go to the documentation of this file.
1# This file is part of dax_apdb.
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/>.
21
22"""Module containing methods and classes for generic APDB schema operations.
23
24The code in this module is independent of the specific technology used to
25implement APDB.
26"""
27
28from __future__ import annotations
29
30__all__ = ["ApdbTables", "ApdbSchema"]
31
32import enum
33import logging
34import os
35from collections.abc import Mapping, MutableMapping
36
37import felis.datamodel
38import numpy
39import yaml
40
41from .schema_model import ExtraDataTypes, Schema, Table
42from .versionTuple import VersionTuple
43
44_LOG = logging.getLogger(__name__)
45
46# In most cases column types are determined by Cassandra driver, but in some
47# cases we need to create Pandas Dataframe ourselves and we use this map to
48# infer types of columns from their YAML schema. Note that Cassandra saves
49# timestamps with millisecond precision, but pandas maps datetime type to
50# "datetime64[ns]".
51_dtype_map: Mapping[felis.datamodel.DataType | ExtraDataTypes, type | str] = {
52 felis.datamodel.DataType.double: numpy.float64,
53 felis.datamodel.DataType.float: numpy.float32,
54 felis.datamodel.DataType.timestamp: "datetime64[ns]",
55 felis.datamodel.DataType.long: numpy.int64,
56 felis.datamodel.DataType.int: numpy.int32,
57 felis.datamodel.DataType.short: numpy.int16,
58 felis.datamodel.DataType.byte: numpy.int8,
59 felis.datamodel.DataType.binary: object,
60 felis.datamodel.DataType.char: object,
61 felis.datamodel.DataType.text: object,
62 felis.datamodel.DataType.string: object,
63 felis.datamodel.DataType.unicode: object,
64 felis.datamodel.DataType.boolean: bool,
65}
66
67
68@enum.unique
69class ApdbTables(enum.Enum):
70 """Names of the tables in APDB schema."""
71
72 DiaObject = "DiaObject"
73 """Name of the table for DIAObject records."""
74
75 DiaSource = "DiaSource"
76 """Name of the table for DIASource records."""
77
78 DiaForcedSource = "DiaForcedSource"
79 """Name of the table for DIAForcedSource records."""
80
81 DiaObjectLast = "DiaObjectLast"
82 """Name of the table for the last version of DIAObject records.
83
84 This table may be optional for some implementations.
85 """
86
87 SSObject = "SSObject"
88 """Name of the table for SSObject records."""
89
90 DiaObject_To_Object_Match = "DiaObject_To_Object_Match"
91 """Name of the table for DiaObject_To_Object_Match records."""
92
93 metadata = "metadata"
94 """Name of the metadata table, this table may not always exist."""
95
96 def table_name(self, prefix: str = "") -> str:
97 """Return full table name."""
98 return prefix + self.value
99
100
102 """Class for management of APDB schema.
103
104 Attributes
105 ----------
106 tableSchemas : `dict`
107 Maps table name to `TableDef` instance.
108
109 Parameters
110 ----------
111 schema_file : `str`
112 Name of the YAML schema file.
113 schema_name : `str`, optional
114 Name of the schema in YAML files.
115 """
116
118 self,
119 schema_file: str,
120 schema_name: str = "ApdbSchema",
121 ):
122 # build complete table schema
123 self.tableSchemas, self._schemaVersion = self._buildSchemas(schema_file, schema_name)
124
125 def column_dtype(self, felis_type: felis.datamodel.DataType | ExtraDataTypes) -> type | str:
126 """Return Pandas data type for a given Felis column type.
127
128 Parameters
129 ----------
130 felis_type : `felis.datamodel.DataType`
131 Felis type, on of the enums defined in `felis.datamodel` module.
132
133 Returns
134 -------
135 column_dtype : `type` or `str`
136 Type that can be used for columns in Pandas.
137
138 Raises
139 ------
140 TypeError
141 Raised if type is cannot be handled.
142 """
143 try:
144 return _dtype_map[felis_type]
145 except KeyError:
146 raise TypeError(f"Unexpected Felis type: {felis_type}")
147
148 def schemaVersion(self) -> VersionTuple:
149 """Return schema version as defined in YAML schema file.
150
151 Returns
152 -------
153 version : `VersionTuple`
154 Version number read from YAML file, if YAML file does not define
155 schema version then "0.1.0" is returned.
156 """
157 if self._schemaVersion is None:
158 return VersionTuple(0, 1, 0)
159 else:
160 return self._schemaVersion
161
162 @classmethod
164 cls, schema_file: str, schema_name: str = "ApdbSchema"
165 ) -> tuple[Mapping[ApdbTables, Table], VersionTuple | None]:
166 """Create schema definitions for all tables.
167
168 Reads YAML schema and builds a dictionary containing
169 `.schema_model.Table` instances for each table.
170
171 Parameters
172 ----------
173 schema_file : `str`
174 Name of YAML file with ``felis`` schema.
175 schema_name : `str`, optional
176 Name of the schema in YAML files.
177
178 Returns
179 -------
180 tables : `dict`
181 Mapping of table names to `.schema_model.Table` instances.
182 version : `VersionTuple` or `None`
183 Schema version defined in schema file, `None` if version is not
184 defined.
185 """
186 schema_file = os.path.expandvars(schema_file)
187 with open(schema_file) as yaml_stream:
188 schemas_list = list(yaml.load_all(yaml_stream, Loader=yaml.SafeLoader))
189 schemas_list = [schema for schema in schemas_list if schema.get("name") == schema_name]
190 if not schemas_list:
191 raise ValueError(f"Schema file {schema_file!r} does not define schema {schema_name!r}")
192 elif len(schemas_list) > 1:
193 raise ValueError(f"Schema file {schema_file!r} defines multiple schemas {schema_name!r}")
194 felis_schema = felis.datamodel.Schema.model_validate(schemas_list[0])
195 schema = Schema.from_felis(felis_schema)
196
197 # convert all dicts into classes
198 tables: MutableMapping[ApdbTables, Table] = {}
199 for table in schema.tables:
200 try:
201 table_enum = ApdbTables(table.name)
202 except ValueError:
203 # There may be other tables in the schema that do not belong
204 # to APDB.
205 continue
206 else:
207 tables[table_enum] = table
208
209 version: VersionTuple | None = None
210 if schema.version is not None:
211 version = VersionTuple.fromString(schema.version.current)
212
213 return tables, version
type|str column_dtype(self, felis.datamodel.DataType|ExtraDataTypes felis_type)
__init__(self, str schema_file, str schema_name="ApdbSchema")
tuple[Mapping[ApdbTables, Table], VersionTuple|None] _buildSchemas(cls, str schema_file, str schema_name="ApdbSchema")
str table_name(self, str prefix="")
Definition apdbSchema.py:96