LSST Applications g013ef56533+63812263fb,g083dd6704c+a047e97985,g199a45376c+0ba108daf9,g1fd858c14a+fde7a7a78c,g210f2d0738+db0c280453,g262e1987ae+abed931625,g29ae962dfc+058d1915d8,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+64337f1634,g47891489e3+f459a6810c,g53246c7159+8c5ae1fdc5,g54cd7ddccb+890c8e1e5d,g5a60e81ecd+d9e514a434,g64539dfbff+db0c280453,g67b6fd64d1+f459a6810c,g6ebf1fc0d4+8c5ae1fdc5,g7382096ae9+36d16ea71a,g74acd417e5+c70e70fbf6,g786e29fd12+668abc6043,g87389fa792+8856018cbb,g89139ef638+f459a6810c,g8d7436a09f+1b779678e3,g8ea07a8fe4+81eaaadc04,g90f42f885a+34c0557caf,g97be763408+9583a964dd,g98a1a72a9c+028271c396,g98df359435+530b675b85,gb8cb2b794d+4e54f68785,gbf99507273+8c5ae1fdc5,gc2a301910b+db0c280453,gca7fc764a6+f459a6810c,gd7ef33dd92+f459a6810c,gdab6d2f7ff+c70e70fbf6,ge410e46f29+f459a6810c,ge41e95a9f2+db0c280453,geaed405ab2+e3b4b2a692,gf9a733ac38+8c5ae1fdc5,w.2025.43
LSST Data Management Base Package
Loading...
Searching...
No Matches
blend.py
Go to the documentation of this file.
1from __future__ import annotations
2
3import logging
4from dataclasses import dataclass
5from typing import Any
6
7import numpy as np
8from numpy.typing import DTypeLike
9
10from ..bbox import Box
11from ..blend import Blend
12from ..observation import Observation
13from .blend_base import ScarletBlendBaseData
14from .migration import PRE_SCHEMA, MigrationRegistry, migration
15from .source import ScarletSourceBaseData
16from .utils import decode_metadata, encode_metadata, extract_from_metadata
17
18__all__ = ["ScarletBlendData"]
19
20CURRENT_SCHEMA = "1.0.0"
21BLEND_TYPE = "blend"
22MigrationRegistry.set_current(BLEND_TYPE, CURRENT_SCHEMA)
23logger = logging.getLogger(__name__)
24
25
26@dataclass(kw_only=True)
28 """Data for an entire blend.
29
30 Attributes
31 ----------
32 blend_type :
33 The type of blend being stored.
34 metadata :
35 Metadata associated with the blend,
36 for example the order of bands, the PSF, etc.
37 origin :
38 The lower bound of the blend's bounding box.
39 shape :
40 The shape of the blend's bounding box.
41 sources :
42 Data for the sources contained in the blend,
43 indexed by the source id.
44 version :
45 The schema version of the stored data.
46 """
47
48 blend_type: str = BLEND_TYPE
49 origin: tuple[int, int]
50 shape: tuple[int, int]
51 sources: dict[Any, ScarletSourceBaseData]
52 version: str = CURRENT_SCHEMA
53
54 def as_dict(self) -> dict:
55 """Return the object encoded into a dict for JSON serialization
56
57 Returns
58 -------
59 result :
60 The object encoded as a JSON compatible dict
61 """
62 result: dict[str, Any] = {
63 "blend_type": self.blend_type,
64 "origin": self.origin,
65 "shape": self.shape,
66 "sources": {bid: source.as_dict() for bid, source in self.sources.items()},
67 "version": self.version,
68 }
69 if self.metadata is not None:
70 result["metadata"] = encode_metadata(self.metadata)
71 return result
72
73 @classmethod
74 def from_dict(cls, data: dict, dtype: DTypeLike = np.float32) -> ScarletBlendData:
75 """Reconstruct `ScarletBlendData` from JSON compatible
76 dict.
77
78 Parameters
79 ----------
80 data :
81 Dictionary representation of the object
82 dtype :
83 Datatype of the resulting model.
84
85 Returns
86 -------
87 result :
88 The reconstructed object
89 """
90 data = MigrationRegistry.migrate(BLEND_TYPE, data)
91 metadata = data.get("metadata", None)
92
93 return cls(
94 origin=tuple(data["origin"]), # type: ignore
95 shape=tuple(data["shape"]), # type: ignore
96 sources={
97 bid: ScarletSourceBaseData.from_dict(source, dtype=dtype)
98 for bid, source in data["sources"].items()
99 },
100 metadata=decode_metadata(metadata),
101 )
102
104 self,
105 model_psf: np.ndarray | None = None,
106 psf: np.ndarray | None = None,
107 bands: tuple[str] | None = None,
108 dtype: DTypeLike = np.float32,
109 ) -> Blend:
110 """Convert the storage data model into a scarlet lite blend
111
112 Parameters
113 ----------
114 model_psf :
115 PSF in model space (usually a nyquist sampled circular Gaussian).
116 psf :
117 The PSF of the observation.
118 If not provided, the PSF stored in the blend data is used.
119 bands :
120 The bands in the blend model.
121 If not provided, the bands stored in the blend data are used.
122 dtype :
123 The data type of the model that is generated.
124
125 Returns
126 -------
127 blend :
128 A scarlet blend model extracted from persisted data.
129 """
130
131 _model_psf: np.ndarray = extract_from_metadata(model_psf, self.metadata, "model_psf")
132 _psf: np.ndarray = extract_from_metadata(psf, self.metadata, "psf")
133 _bands: tuple[str] = extract_from_metadata(bands, self.metadata, "bands")
134 model_box = Box(self.shape, origin=self.origin)
135 observation = Observation.empty(
136 bands=_bands,
137 psfs=_psf,
138 model_psf=_model_psf,
139 bbox=model_box,
140 dtype=dtype,
141 )
142 return self.to_blend(observation)
143
144 def to_blend(self, observation: Observation) -> Blend:
145 """Convert the storage data model into a scarlet lite blend
146
147 Parameters
148 ----------
149 observation :
150 The observation that contains the blend.
151 If `observation` is ``None`` then an `Observation` containing
152 no image data is initialized.
153
154 Returns
155 -------
156 blend :
157 A scarlet blend model extracted from persisted data.
158 """
159 sources = []
160 for source_data in self.sources.values():
161 source = source_data.to_source(observation)
162 sources.append(source)
163
164 return Blend(sources=sources, observation=observation, metadata=self.metadata)
165
166 @staticmethod
167 def from_blend(blend: Blend) -> ScarletBlendData:
168 """Deprecated: Convert a scarlet lite blend into a storage data model.
169
170 Parameters
171 ----------
172 blend :
173 The blend to convert.
174 Returns
175 -------
176 result :
177 The storage data model representing the blend.
178 """
179 logger.warning("ScarletBlendData.from_blend is deprecated. Use blend.to_data() instead.")
180 return blend.to_data()
181
182
183ScarletBlendData.register()
184
185
186@migration(BLEND_TYPE, PRE_SCHEMA)
187def _to_1_0_0(data: dict) -> dict:
188 """Migrate a pre-schema blend to schema version 1.0.0
189
190 Parameters
191 ----------
192 data :
193 The data to migrate.
194
195 Returns
196 -------
197 result :
198 The migrated data.
199 """
200 # Support legacy models before metadata was used
201 if "metadata" not in data and "psf" in data:
202 data["metadata"] = {
203 "psf": data["psf"],
204 "psf_shape": data["psf_shape"],
205 "bands": tuple(data["bands"]),
206 "array" "_keys": ["psf"],
207 }
208 data["version"] = "1.0.0"
209 return data
ScarletBlendData from_blend(Blend blend)
Definition blend.py:167
Blend minimal_data_to_blend(self, np.ndarray|None model_psf=None, np.ndarray|None psf=None, tuple[str]|None bands=None, DTypeLike dtype=np.float32)
Definition blend.py:109
ScarletBlendData from_dict(cls, dict data, DTypeLike dtype=np.float32)
Definition blend.py:74
Blend to_blend(self, Observation observation)
Definition blend.py:144
dict _to_1_0_0(dict data)
Definition blend.py:187