LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
_multiband.py
Go to the documentation of this file.
1 # This file is part of afw.
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 __all__ = ["MultibandExposure"]
23 
24 import numpy as np
25 
26 from lsst.geom import Point2D
27 from . import Exposure, ExposureF
28 from ..image._multiband import MultibandImage, MultibandTripleBase
29 from ..image._multiband import tripleFromSingles, tripleFromArrays, makeTripleFromKwargs
30 from ..maskedImage import MaskedImage
31 
32 
34  """MultibandExposure class
35 
36  This class acts as a container for multiple `afw.Exposure` objects.
37  All exposures must have the same bounding box, and the associated
38  images must all have the same data type.
39 
40  See `MultibandTripleBase` for parameter definitions.
41  """
42  def __init__(self, filters, image, mask, variance, psfs=None):
43  super().__init__(filters, image, mask, variance)
44  if psfs is not None:
45  for psf, exposure in zip(psfs, self.singlessingles):
46  exposure.setPsf(psf)
47 
48  @staticmethod
49  def fromExposures(filters, singles):
50  """Construct a MultibandImage from a collection of single band images
51 
52  see `tripleFromExposures` for a description of parameters
53  """
54  psfs = [s.getPsf() for s in singles]
55  return tripleFromSingles(MultibandExposure, filters, singles, psfs=psfs)
56 
57  @staticmethod
58  def fromArrays(filters, image, mask, variance, bbox=None):
59  """Construct a MultibandExposure from a collection of arrays
60 
61  see `tripleFromArrays` for a description of parameters
62  """
63  return tripleFromArrays(MultibandExposure, filters, image, mask, variance, bbox)
64 
65  @staticmethod
66  def fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs):
67  """Build a MultibandImage from a set of keyword arguments
68 
69  see `makeTripleFromKwargs` for a description of parameters
70  """
71  return makeTripleFromKwargs(MultibandExposure, filters, filterKwargs, singleType, **kwargs)
72 
73  def _buildSingles(self, image=None, mask=None, variance=None):
74  """Make a new list of single band objects
75 
76  Parameters
77  ----------
78  image: `list`
79  List of `Image` objects that represent the image in each band.
80  mask: `list`
81  List of `Mask` objects that represent the mask in each band.
82  variance: `list`
83  List of `Image` objects that represent the variance in each band.
84 
85  Returns
86  -------
87  singles: tuple
88  Tuple of `MaskedImage` objects for each band,
89  where the `image`, `mask`, and `variance` of each `single`
90  point to the multiband objects.
91  """
92  singles = []
93  if image is None:
94  image = self.imageimage
95  if mask is None:
96  mask = self.maskmask
97  if variance is None:
98  variance = self.variancevariance
99 
100  dtype = image.array.dtype
101  for f in self.filtersfilters:
102  maskedImage = MaskedImage(image=image[f], mask=mask[f], variance=variance[f], dtype=dtype)
103  single = Exposure(maskedImage, dtype=dtype)
104  singles.append(single)
105  return tuple(singles)
106 
107  @staticmethod
108  def fromButler(butler, filters, filterKwargs, *args, **kwargs):
109  """Load a multiband exposure from a butler
110 
111  Because each band is stored in a separate exposure file,
112  this method can be used to load all of the exposures for
113  a given set of bands
114 
115  Parameters
116  ----------
117  butler: `Butler`
118  Butler connection to use to load the single band
119  calibrated images
120  filters: `list` or `str`
121  List of filter names for each band
122  filterKwargs: `dict`
123  Keyword arguments to pass to the Butler
124  that are different for each filter.
125  The keys are the names of the arguments and the values
126  should also be dictionaries, with filter names as keys
127  and the value of the argument for the given filter as values.
128  args: `list`
129  Arguments to the Butler.
130  kwargs: `dict`
131  Keyword arguments to pass to the Butler
132  that are the same in all bands.
133 
134  Returns
135  -------
136  result: `MultibandExposure`
137  The new `MultibandExposure` created by combining all of the
138  single band exposures.
139  """
140  # Load the Exposure in each band
141  exposures = []
142  for f in filters:
143  if filterKwargs is not None:
144  for key, value in filterKwargs:
145  kwargs[key] = value[f]
146  exposures.append(butler.get(*args, filter=f, **kwargs))
147  return MultibandExposure.fromExposures(filters, exposures)
148 
149  def computePsfKernelImage(self, position=None):
150  """Get a multiband PSF image
151 
152  The PSF Kernel Image is computed for each band
153  and combined into a (filter, y, x) array and stored
154  as `self._psfImage`.
155  The result is not cached, so if the same PSF is expected
156  to be used multiple times it is a good idea to store the
157  result in another variable.
158 
159  Parameters
160  ----------
161  position: `Point2D` or `tuple`
162  Coordinates to evaluate the PSF. If `position` is `None`
163  then `Psf.getAveragePosition()` is used.
164 
165  Returns
166  -------
167  self._psfImage: array
168  The multiband PSF image.
169  """
170  psfs = []
171  # Make the coordinates into a Point2D (if necessary)
172  if not isinstance(position, Point2D) and position is not None:
173  position = Point2D(position[0], position[1])
174  for single in self.singlessingles:
175  if position is None:
176  psfs.append(single.getPsf().computeKernelImage().array)
177  else:
178  psfs.append(single.getPsf().computeKernelImage(position).array)
179  psfs = np.array(psfs)
180  psfImage = MultibandImage(self.filtersfilters, array=psfs)
181  return psfImage
182 
183  def computePsfImage(self, position=None):
184  """Get a multiband PSF image
185 
186  The PSF Kernel Image is computed for each band
187  and combined into a (filter, y, x) array and stored
188  as `self._psfImage`.
189  The result is not cached, so if the same PSF is expected
190  to be used multiple times it is a good idea to store the
191  result in another variable.
192 
193  Parameters
194  ----------
195  position: `Point2D` or `tuple`
196  Coordinates to evaluate the PSF. If `position` is `None`
197  then `Psf.getAveragePosition()` is used.
198 
199  Returns
200  -------
201  self._psfImage: array
202  The multiband PSF image.
203  """
204  psfs = []
205  # Make the coordinates into a Point2D (if necessary)
206  if not isinstance(position, Point2D) and position is not None:
207  position = Point2D(position[0], position[1])
208  for single in self.singlessingles:
209  if position is None:
210  psfs.append(single.getPsf().computeImage().array)
211  else:
212  psfs.append(single.getPsf().computeImage(position).array)
213  psfs = np.array(psfs)
214  psfImage = MultibandImage(self.filtersfilters, array=psfs)
215  return psfImage
def fromButler(butler, filters, filterKwargs, *args, **kwargs)
Definition: _multiband.py:108
def __init__(self, filters, image, mask, variance, psfs=None)
Definition: _multiband.py:42
def fromArrays(filters, image, mask, variance, bbox=None)
Definition: _multiband.py:58
def fromKwargs(filters, filterKwargs, singleType=ExposureF, **kwargs)
Definition: _multiband.py:66
def makeTripleFromKwargs(cls, filters, filterKwargs, singleType, **kwargs)
Definition: _multiband.py:770
def tripleFromSingles(cls, filters, singles, **kwargs)
Definition: _multiband.py:720
def tripleFromArrays(cls, filters, image, mask, variance, bbox=None)
Definition: _multiband.py:739
Point< double, 2 > Point2D
Definition: Point.h:324