LSST Applications g04e9c324dd+8c5ae1fdc5,g134cb467dc+b203dec576,g18429d2f64+358861cd2c,g199a45376c+0ba108daf9,g1fd858c14a+dd066899e3,g262e1987ae+ebfced1d55,g29ae962dfc+72fd90588e,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+b668f15bc5,g4595892280+3897dae354,g47891489e3+abcf9c3559,g4d44eb3520+fb4ddce128,g53246c7159+8c5ae1fdc5,g67b6fd64d1+abcf9c3559,g67fd3c3899+1f72b5a9f7,g74acd417e5+cb6b47f07b,g786e29fd12+668abc6043,g87389fa792+8856018cbb,g89139ef638+abcf9c3559,g8d7436a09f+bcf525d20c,g8ea07a8fe4+9f5ccc88ac,g90f42f885a+6054cc57f1,g97be763408+06f794da49,g9dd6db0277+1f72b5a9f7,ga681d05dcb+7e36ad54cd,gabf8522325+735880ea63,gac2eed3f23+abcf9c3559,gb89ab40317+abcf9c3559,gbf99507273+8c5ae1fdc5,gd8ff7fe66e+1f72b5a9f7,gdab6d2f7ff+cb6b47f07b,gdc713202bf+1f72b5a9f7,gdfd2d52018+8225f2b331,ge365c994fd+375fc21c71,ge410e46f29+abcf9c3559,geaed405ab2+562b3308c0,gf9a733ac38+8c5ae1fdc5,w.2025.35
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.scarlet.lite.measure Namespace Reference

Functions

float calculate_snr (Image images, Image variance, np.ndarray psfs, tuple[int, int] center)
 
None conserve_flux (blend, bool mask_footprint=True, Image|None images=None)
 

Function Documentation

◆ calculate_snr()

float lsst.scarlet.lite.measure.calculate_snr ( Image images,
Image variance,
np.ndarray psfs,
tuple[int, int] center )
Calculate the signal to noise for a point source

This is done by weighting the image with the PSF in each band
and dividing by the PSF weighted variance.

Parameters
----------
images:
    The 3D (bands, y, x) image containing the data.
variance:
    The variance of `images`.
psfs:
    The PSF in each band.
center:
    The center of the signal.

Returns
-------
snr:
    The signal to noise of the source.

Definition at line 30 of file measure.py.

35) -> float:
36 """Calculate the signal to noise for a point source
37
38 This is done by weighting the image with the PSF in each band
39 and dividing by the PSF weighted variance.
40
41 Parameters
42 ----------
43 images:
44 The 3D (bands, y, x) image containing the data.
45 variance:
46 The variance of `images`.
47 psfs:
48 The PSF in each band.
49 center:
50 The center of the signal.
51
52 Returns
53 -------
54 snr:
55 The signal to noise of the source.
56 """
57 py = psfs.shape[1] // 2
58 px = psfs.shape[2] // 2
59 bbox = Box(psfs[0].shape, origin=(-py + center[0], -px + center[1]))
60 overlap = images.bbox & bbox
61 noise = variance[overlap].data
62 img = images[overlap].data
63 _psfs = Image(psfs, bands=images.bands, yx0=cast(tuple[int, int], bbox.origin))[overlap].data
64 numerator = img * _psfs
65 denominator = (_psfs * noise) * _psfs
66 return np.sum(numerator) / np.sqrt(np.sum(denominator))
67
68

◆ conserve_flux()

None lsst.scarlet.lite.measure.conserve_flux ( blend,
bool mask_footprint = True,
Image | None images = None )
Use the source models as templates to re-distribute flux
from the data

The source models are used as approximations to the data,
which redistribute the flux in the data according to the
ratio of the models for each source.
There is no return value for this function,
instead it adds (or modifies) a ``flux_weighted_image``
attribute to each the sources with the flux attributed to
that source.

Parameters
----------
blend:
    The blend that is being fit
mask_footprint:
    Whether or not to apply a mask for pixels with zero weight.

Definition at line 69 of file measure.py.

69def conserve_flux(blend, mask_footprint: bool = True, images: Image | None = None) -> None:
70 """Use the source models as templates to re-distribute flux
71 from the data
72
73 The source models are used as approximations to the data,
74 which redistribute the flux in the data according to the
75 ratio of the models for each source.
76 There is no return value for this function,
77 instead it adds (or modifies) a ``flux_weighted_image``
78 attribute to each the sources with the flux attributed to
79 that source.
80
81 Parameters
82 ----------
83 blend:
84 The blend that is being fit
85 mask_footprint:
86 Whether or not to apply a mask for pixels with zero weight.
87 """
88 observation = blend.observation
89 py = observation.psfs.shape[-2] // 2
90 px = observation.psfs.shape[-1] // 2
91
92 if images is None:
93 images = observation.images.copy()
94 if mask_footprint:
95 images.data[observation.weights.data == 0] = 0
96 model = blend.get_model()
97 bands = None
98 else:
99 bands = images.bands
100 model = blend.get_model()[bands,]
101 # Always convolve in real space to avoid FFT artifacts
102 model = observation.convolve(model, mode="real")
103 model.data[model.data < 0] = 0
104
105 for src in blend.sources:
106 if src.is_null:
107 src.flux_weighted_image = Image.from_box(Box((0, 0)), bands=observation.bands) # type: ignore
108 continue
109 src_model = src.get_model()
110
111 # Grow the model to include the wings of the PSF
112 src_box = src.bbox.grow((py, px))
113 overlap = observation.bbox & src_box
114 src_model = src_model.project(bbox=overlap)
115 src_model = observation.convolve(src_model, mode="real")
116 if bands is not None:
117 src_model = src_model[bands,]
118 src_model.data[src_model.data < 0] = 0
119 numerator = src_model.data
120 denominator = model[overlap].data
121 cuts = denominator != 0
122 ratio = np.zeros(numerator.shape, dtype=numerator.dtype)
123 ratio[cuts] = numerator[cuts] / denominator[cuts]
124 ratio[denominator == 0] = 0
125 # sometimes numerical errors can cause a hot pixel to have a
126 # slightly higher ratio than 1
127 ratio[ratio > 1] = 1
128 src.flux_weighted_image = src_model.copy_with(data=ratio) * images[overlap]