Hide keyboard shortcuts

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/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ("DimensionConfig",) 

25 

26from typing import Tuple, Dict 

27 

28from ..config import Config, ConfigSubset 

29from ..utils import doImport 

30from .. import ddl 

31from .elements import DimensionElement, Dimension, SkyPixDimension, RelatedDimensions 

32 

33 

34class DimensionConfig(ConfigSubset): 

35 """Configuration that defines a `DimensionUniverse`. 

36 

37 The configuration tree for dimensions is a (nested) dictionary 

38 with four top-level entries: 

39 

40 - version: an integer version number, used as keys in a singleton registry 

41 of all `DimensionUniverse` instances; 

42 

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; 

47 

48 - elements: a nested dictionary whose entries each define a non-skypix 

49 `DimensionElement`; 

50 

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" 

57 

58 

59def processSkyPixConfig(config: Config) -> Tuple[Dict[str, SkyPixDimension], SkyPixDimension]: 

60 """Process the "skypix" section of a `DimensionConfig`. 

61 

62 Parameters 

63 ---------- 

64 config : `Config` 

65 The subset of a `DimensionConfig` that corresponds to the "skypix" key. 

66 

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 skyPixNames = set(config.keys()) 

80 try: 

81 skyPixNames.remove("common") 

82 except KeyError as err: 

83 raise ValueError("No common skypix dimension defined in configuration.") from err 

84 dimensions = {} 

85 for name in skyPixNames: 

86 subconfig = config[name] 

87 pixelizationClass = doImport(subconfig["class"]) 

88 level = subconfig.get("level", None) 

89 if level is not None: 

90 pixelization = pixelizationClass(level) 

91 else: 

92 pixelization = pixelizationClass() 

93 dimensions[name] = SkyPixDimension(name, pixelization) 

94 try: 

95 common = dimensions[config["common"]] 

96 except KeyError as err: 

97 raise ValueError(f"Undefined name for common skypix dimension ({config['common']}).") from err 

98 return dimensions, common 

99 

100 

101def processElementsConfig(config: Config) -> Dict[str, DimensionElement]: 

102 """Process the "elements" section of a `DimensionConfig`. 

103 

104 Parameters 

105 ---------- 

106 config : `Config` 

107 The subset of a `DimensionConfig` that corresponds to the "elements" 

108 key. 

109 

110 Returns 

111 ------- 

112 dimensions : `dict` 

113 A dictionary mapping `str` names to partially-constructed 

114 `DimensionElement` instances; the caller (i.e. a `DimensionUniverse`) 

115 is responsible for calling `DimensionElement._finish` to complete 

116 construction. 

117 """ 

118 elements = dict() 

119 for name, subconfig in config.items(): 

120 kwargs = {} 

121 kwargs["related"] = RelatedDimensions( 

122 required=set(subconfig.get("requires", ())), 

123 implied=set(subconfig.get("implies", ())), 

124 spatial=subconfig.get("spatial"), 

125 temporal=subconfig.get("temporal"), 

126 ) 

127 kwargs["metadata"] = [ddl.FieldSpec.fromConfig(c) for c in subconfig.get("metadata", ())] 

128 kwargs["cached"] = subconfig.get("cached", False) 

129 kwargs["viewOf"] = subconfig.get("view_of", None) 

130 kwargs["alwaysJoin"] = subconfig.get("always_join", False) 

131 keys = subconfig.get("keys") 

132 if keys is not None: 

133 uniqueKeys = [ddl.FieldSpec.fromConfig(c, nullable=False) for c in keys] 

134 uniqueKeys[0].primaryKey = True 

135 elements[name] = Dimension(name, uniqueKeys=uniqueKeys, **kwargs) 

136 else: 

137 elements[name] = DimensionElement(name, **kwargs) 

138 return elements