Coverage for python/lsst/meas/extensions/scarlet/source.py : 29%

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 meas_extensions_scarlet.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://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 <https://www.gnu.org/licenses/>.
22import numpy as np
23from scarlet.bbox import Box
24from scarlet.frame import Frame
26from lsst.geom import Point2I
27import lsst.log
28import lsst.afw.detection as afwDet
30__all__ = ["modelToHeavy"]
32logger = lsst.log.Log.getLogger("meas.extensions.scarlet.source")
35def modelToHeavy(source, filters, xy0=Point2I(), observation=None, dtype=np.float32):
36 """Convert the model to a `MultibandFootprint`
38 Parameters
39 ----------
40 source : `scarlet.Component`
41 The source to convert to a `HeavyFootprint`.
42 filters : `iterable`
43 A "list" of names for each filter.
44 xy0 : `lsst.geom.Point2I`
45 `(x,y)` coordinates of the bounding box containing the
46 `HeavyFootprint`. If `observation` is not `None` then
47 this parameter is updated with the position of the new model
48 observation : `scarlet.Observation`
49 The scarlet observation, used to convolve the image with
50 the origin PSF. If `observation`` is `None` then the
51 `HeavyFootprint` will exist in the model frame.
52 dtype : `numpy.dtype`
53 The data type for the returned `HeavyFootprint`.
55 Returns
56 -------
57 mHeavy : `lsst.detection.MultibandFootprint`
58 The multi-band footprint containing the model for the source.
59 """
60 if observation is not None:
61 # We want to convolve the model with the observed PSF,
62 # which means we need to grow the model box by the PSF to
63 # account for all of the flux after convolution.
64 # FYI: The `scarlet.Box` class implements the `&` operator
65 # to take the intersection of two boxes.
67 # Get the PSF size and radii to grow the box
68 py, px = observation.frame.psf.get_model().shape[1:]
69 dh = py // 2
70 dw = px // 2
71 shape = (source.bbox.shape[0], source.bbox.shape[1] + py, source.bbox.shape[2] + px)
72 origin = (source.bbox.origin[0], source.bbox.origin[1] - dh, source.bbox.origin[2] - dw)
73 # Create the larger box to fit the model + PSf
74 bbox = Box(shape, origin=origin)
75 # Only use the portion of the convolved model that fits in the image
76 overlap = Frame(bbox & source.frame.bbox, source.frame.channels, psfs=source.frame.psf)
77 # Load the full multiband model in the larger box
78 model = source.model_to_frame(overlap)
79 # Convolve the model with the PSF in each band
80 # Always use a real space convolution to limit artifacts
81 model = observation.convolve(model, convolution_type="real").astype(dtype)
82 # Update xy0 with the origin of the sources box
83 xy0 = Point2I(overlap.origin[-1] + xy0.x, overlap.origin[-2] + xy0.y)
84 else:
85 model = source.get_model().astype(dtype)
86 mHeavy = afwDet.MultibandFootprint.fromArrays(filters, model, xy0=xy0)
87 peakCat = afwDet.PeakCatalog(source.detectedPeak.table)
88 peakCat.append(source.detectedPeak)
89 for footprint in mHeavy:
90 footprint.setPeakCatalog(peakCat)
91 return mHeavy