Coverage for python/lsst/daf/butler/core/dimensions/config.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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__ = ("DimensionConfig",)
26from typing import Any, Dict, Tuple
28from ..config import Config, ConfigSubset
29from ..utils import doImport
30from .. import ddl
31from .elements import DimensionElement, Dimension, SkyPixDimension, RelatedDimensions
34class DimensionConfig(ConfigSubset):
35 """Configuration that defines a `DimensionUniverse`.
37 The configuration tree for dimensions is a (nested) dictionary
38 with four top-level entries:
40 - version: an integer version number, used as keys in a singleton registry
41 of all `DimensionUniverse` instances;
43 - skypix: a dictionary whose entries each define a `SkyPixDimension`,
44 along with a special "common" key whose value is the name of a skypix
45 dimension that is used to relate all other spatial dimensions in the
46 `Registry` database;
48 - elements: a nested dictionary whose entries each define a non-skypix
49 `DimensionElement`;
51 - packers: a nested dictionary whose entries define a factory for a
52 `DimensionPacker` instance.
53 """
54 component = "dimensions"
55 requiredKeys = ("version", "elements", "skypix")
56 defaultConfigFile = "dimensions.yaml"
59def processSkyPixConfig(config: Config) -> Tuple[Dict[str, SkyPixDimension], SkyPixDimension]:
60 """Process the "skypix" section of a `DimensionConfig`.
62 Parameters
63 ----------
64 config : `Config`
65 The subset of a `DimensionConfig` that corresponds to the "skypix" key.
67 Returns
68 -------
69 dimensions: `dict`
70 A dictionary mapping `str` names to partially-constructed
71 `SkyPixDimension` instances; the caller (i.e. a `DimensionUniverse`)
72 is responsible for calling `DimensionElement._finish` to complete
73 construction.
74 common: `SkyPixDimension`
75 The special dimension used to relate all other spatial dimensions in
76 the universe. This instance is also guaranteed to be a value in
77 the returned ``dimensions``.
78 """
79 skyPixSysNames = set(config.keys())
80 try:
81 skyPixSysNames.remove("common")
82 except KeyError as err:
83 raise ValueError("No common skypix dimension defined in configuration.") from err
84 dimensions = {}
85 for sysName in sorted(skyPixSysNames):
86 subconfig = config[sysName]
87 pixelizationClass = doImport(subconfig["class"])
88 max_level = subconfig.get("max_level", 24)
89 for level in range(max_level + 1):
90 name = f"{sysName}{level}"
91 dimensions[name] = SkyPixDimension(name, pixelizationClass(level))
92 try:
93 common = dimensions[config["common"]]
94 except KeyError as err:
95 raise ValueError(f"Undefined name for common skypix dimension ({config['common']}).") from err
96 return dimensions, common
99def processElementsConfig(config: Config) -> Dict[str, DimensionElement]:
100 """Process the "elements" section of a `DimensionConfig`.
102 Parameters
103 ----------
104 config : `Config`
105 The subset of a `DimensionConfig` that corresponds to the "elements"
106 key.
108 Returns
109 -------
110 dimensions : `dict`
111 A dictionary mapping `str` names to partially-constructed
112 `DimensionElement` instances; the caller (i.e. a `DimensionUniverse`)
113 is responsible for calling `DimensionElement._finish` to complete
114 construction.
115 """
116 elements: Dict[str, DimensionElement] = dict()
117 for name, subconfig in config.items():
118 kwargs: Dict[str, Any] = {}
119 kwargs["related"] = RelatedDimensions(
120 required=set(subconfig.get("requires", ())),
121 implied=set(subconfig.get("implies", ())),
122 spatial=subconfig.get("spatial"),
123 temporal=subconfig.get("temporal"),
124 )
125 kwargs["metadata"] = [ddl.FieldSpec.fromConfig(c) for c in subconfig.get("metadata", ())]
126 kwargs["cached"] = subconfig.get("cached", False)
127 kwargs["viewOf"] = subconfig.get("view_of", None)
128 kwargs["alwaysJoin"] = subconfig.get("always_join", False)
129 keys = subconfig.get("keys")
130 if keys is not None:
131 uniqueKeys = [ddl.FieldSpec.fromConfig(c, nullable=False) for c in keys]
132 uniqueKeys[0].primaryKey = True
133 elements[name] = Dimension(name, uniqueKeys=uniqueKeys, **kwargs)
134 else:
135 elements[name] = DimensionElement(name, **kwargs)
136 return elements