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 Any, Dict, Tuple 

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[str, DimensionElement] = dict() 

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

120 kwargs: Dict[str, Any] = {} 

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