lsst.pipe.tasks g1c91cc4c4e+d2f8426a14
Loading...
Searching...
No Matches
lsst.pipe.tasks.prettyPictureMaker._task Namespace Reference

Classes

class  fixes
 
class  PrettyPictureBackgroundFixerConnections
 
class  PrettyPictureConnections
 

Functions

Struct run (self, Mapping[str, Exposure] images)
 
None runQuantum (self, QuantumContext butlerQC, InputQuantizedConnection inputRefs, OutputQuantizedConnection outputRefs)
 
dict[str, Exposure] makeInputsFromRefs (self, Iterable[DatasetRef] refs, Butler|QuantumContext butler)
 
dict[int, DeferredDatasetHandle] makeInputsFromArrays (self, **kwargs)
 
dict[int, DeferredDatasetHandle] makeInputsFromExposures (self, **kwargs)
 

Variables

 doWrite
 
 r
 
 g
 
 b
 
 array : `numpy.array`
 
 mean : `float`
 
 sigma : `float`
 
tuple lower_pos = (array - mu) < sigma
 
 sigma_ratio = min_sig / sigma
 
 R : `int`
 
 C : `int`
 
 slices : `list` of `tuple`
 
 image : `NDArray`
 
 inputCoadd : `Exposure`
 
 result : `Struct`
 
 results : `Struct` of `Mapping` of `str` to `ExposureF`
 

Function Documentation

◆ makeInputsFromArrays()

dict[int, DeferredDatasetHandle] lsst.pipe.tasks.prettyPictureMaker._task.makeInputsFromArrays ( self,
** kwargs )
Make valid inputs for the run method from numpy arrays.

Parameters
----------
kwargs : `NDArray`
    This is standard python kwargs where the left side of the equals
    is the data band, and the right side is the corresponding `NDArray`
    array.

Returns
-------
sortedImages : `dict` of `str` to `Exposure`
    A dictionary of `Exposure`\ s that keyed by the band they
    correspond to.

Definition at line 531 of file _task.py.

◆ makeInputsFromExposures()

dict[int, DeferredDatasetHandle] lsst.pipe.tasks.prettyPictureMaker._task.makeInputsFromExposures ( self,
** kwargs )
Make valid inputs for the run method from `Exposure` objects.

Parameters
----------
kwargs : `Exposure`
    This is standard python kwargs where the left side of the equals
    is the data band, and the right side is the corresponding
    `Exposure`.

Returns
-------
sortedImages : `dict` of `str` to `Exposure`
    A dictionary of `Exposure`\ s that keyed by the band they
    correspond to.

Definition at line 555 of file _task.py.

◆ makeInputsFromRefs()

dict[str, Exposure] lsst.pipe.tasks.prettyPictureMaker._task.makeInputsFromRefs ( self,
Iterable[DatasetRef] refs,
Butler | QuantumContext butler )
Make valid inputs for the run method from butler references.

Parameters
----------
refs : `Iterable` of `DatasetRef`
    Some `Iterable` container of `Butler` `DatasetRef`\ s
butler : `Butler` or `QuantumContext`
    This is the object that fetches the input data.

Returns
-------
sortedImages : `dict` of `str` to `Exposure`
    A dictionary of `Exposure`\ s that keyed by the band they
    correspond to.

Definition at line 506 of file _task.py.

◆ run()

Struct lsst.pipe.tasks.prettyPictureMaker._task.run ( self,
Mapping[str, Exposure] images )
Turns the input arguments in arguments into an RGB array.

Parameters
----------
images : `Mapping` of `str` to `Exposure`
    A mapping of input images and the band they correspond to.

Returns
-------
result : `Struct`
    A struct with the corresponding RGB image, and mask used in
    RGB image construction. The struct will have the attributes
    outputRGBImage and outputRGBMask. Each of the outputs will
    be a `NDarray` object.

Notes
-----
Construction of input images are made easier by use of the
makeInputsFrom* methods.

Definition at line 368 of file _task.py.

◆ runQuantum()

None lsst.pipe.tasks.prettyPictureMaker._task.runQuantum ( self,
QuantumContext butlerQC,
InputQuantizedConnection inputRefs,
OutputQuantizedConnection outputRefs )

Definition at line 495 of file _task.py.

Variable Documentation

◆ array

lsst.pipe.tasks.prettyPictureMaker._task.array : `numpy.array`
r = Field[float](doc="The amount of red contained in this channel")
g = Field[float](doc="The amount of green contained in this channel")
b = Field[float](doc="The amount of blue contained in this channel")


class LumConfig(Config):
stretch = Field[float](doc="The stretch of the luminance in asinh", default=400)
max = Field[float](doc="The maximum allowed luminance on a 0 to 100 scale", default=85)
floor = Field[float](doc="A scaling factor to apply to the luminance before asinh scaling", default=0.0)
Q = Field[float](doc="softening parameter", default=0.7)
highlight = Field[float](
    doc="The value of highlights in scaling factor applied to post asinh streaching", default=1.0
)
shadow = Field[float](
    doc="The value of shadows in scaling factor applied to post asinh streaching", default=0.0
)
midtone = Field[float](
    doc="The value of midtone in scaling factor applied to post asinh streaching", default=0.5
)


class LocalContrastConfig(Config):
doLocalContrast = Field[bool](
    doc="Apply local contrast enhancements to the luminance channel", default=True
)
highlights = Field[float](doc="Adjustment factor for the highlights", default=-0.9)
shadows = Field[float](doc="Adjustment factor for the shadows", default=0.5)
clarity = Field[float](doc="Amount of clarity to apply to contrast modification", default=0.1)
sigma = Field[float](
    doc="The scale size of what is considered local in the contrast enhancement", default=30
)
maxLevel = Field[int](
    doc="The maximum number of scales the contrast should be enhanced over, if None then all",
    default=4,
    optional=True,
)


class ScaleColorConfig(Config):
saturation = Field[float](
    doc=(
        "The overall saturation factor with the scaled luminance between zero and one. "
        "A value of one is not recommended as it makes bright pixels very saturated"
    ),
    default=0.5,
)
maxChroma = Field[float](
    doc=(
        "The maximum chromaticity in the CIELCh color space, large "
        "values will cause bright pixels to fall outside the RGB gamut."
    ),
    default=50.0,
)


class RemapBoundsConfig(Config):
quant = Field[float](
    doc=(
        "The maximum values of each of the three channels will be multiplied by this factor to "
        "determine the maximum flux of the image, values larger than this quantity will be clipped."
    ),
    default=0.8,
)
absMax = Field[float](
    doc="Instead of determining the maximum value from the image, use this fixed value instead",
    default=220,
    optional=True,
)


class PrettyPictureConfig(PipelineTaskConfig, pipelineConnections=PrettyPictureConnections):
channelConfig = ConfigDictField(
    doc="A dictionary that maps band names to their rgb channel configurations",
    keytype=str,
    itemtype=ChannelRGBConfig,
    default={},
)
imageRemappingConfig = ConfigField[RemapBoundsConfig](
    doc="Configuration controlling channel normalization process"
)
luminanceConfig = ConfigField[LumConfig](
    doc="Configuration for the luminance scaling when making an RGB image"
)
localContrastConfig = ConfigField[LocalContrastConfig](
    doc="Configuration controlling the local contrast correction in RGB image production"
)
colorConfig = ConfigField[ScaleColorConfig](
    doc="Configuration to control the color scaling process in RGB image production"
)
cieWhitePoint = ListField[float](
    doc="The white point of the input arrays in ciexz coordinates", maxLength=2, default=[0.28, 0.28]
)
arrayType = ChoiceField[str](
    doc="The dataset type for the output image array",
    default="uint8",
    allowed={
        "uint8": "Use 8 bit arrays, 255 max",
        "uint16": "Use 16 bit arrays, 65535 max",
        "half": "Use 16 bit float arrays, 1 max",
        "float": "Use 32 bit float arrays, 1 max",
    },
)
doPSFDeconcovlve = Field[bool](
    doc="Use the PSF in a richardson lucy deconvolution on the luminance channel.", default=True
)
exposureBrackets = ListField[float](
    doc=(
        "Exposure scaling factors used in creating multiple exposures with different scalings which will "
        "then be fused into a final image"
    ),
    optional=True,
    default=[1.25, 1, 0.75],
)
doRemapGamut = Field[bool](
    doc="Apply a color correction to unrepresentable colors, if false they will clip", default=True
)
gamutMethod = ChoiceField[str](
    doc="If doRemapGamut is True this determines the method",
    default="inpaint",
    allowed={
        "mapping": "Use a mapping function",
        "inpaint": "Use surrounding pixels to determine likely value",
    },
)
recenterNoise = Field[float](
    doc="Recenter the noise away from zero. Supplied value is in units of sigma",
    optional=True,
    default=None,
)
noiseSearchThreshold = Field[float](
    doc=(
        "Flux threshold below which most flux will be considered noise, used to estimate noise properties"
    ),
    default=10,
)

def setDefaults(self):
    self.channelConfig["i"] = ChannelRGBConfig(r=1, g=0, b=0)
    self.channelConfig["r"] = ChannelRGBConfig(r=0, g=1, b=0)
    self.channelConfig["g"] = ChannelRGBConfig(r=0, g=0, b=1)
    return super().setDefaults()


class PrettyPictureTask(PipelineTask):
_DefaultName = "prettyPictureTask"
ConfigClass = PrettyPictureConfig

config: ConfigClass

def _find_normal_stats(self, array):

Definition at line 287 of file _task.py.

◆ b

lsst.pipe.tasks.prettyPictureMaker._task.b

Definition at line 112 of file _task.py.

◆ C

lsst.pipe.tasks.prettyPictureMaker._task.C : `int`

Definition at line 666 of file _task.py.

◆ doWrite

lsst.pipe.tasks.prettyPictureMaker._task.doWrite

Definition at line 85 of file _task.py.

◆ g

lsst.pipe.tasks.prettyPictureMaker._task.g

Definition at line 112 of file _task.py.

◆ image

lsst.pipe.tasks.prettyPictureMaker._task.image : `NDArray`
M = arr.shape[0]
N = arr.shape[1]

# Function to compute slices for a given dimension size and number of divisions
def get_slices(total_size, num_divisions):
    base = total_size // num_divisions
    remainder = total_size % num_divisions
    slices = []
    start = 0
    for i in range(num_divisions):
        end = start + base
        if i < remainder:
            end += 1
        slices.append((start, end))
        start = end
    return slices

# Get row and column slices
row_slices = get_slices(M, R)
col_slices = get_slices(N, C)

# Generate all possible tile combinations of row and column slices
tiles = []
for rs in row_slices:
    r_start, r_end = rs
    for cs in col_slices:
        c_start, c_end = cs
        tile_slice = (slice(r_start, r_end), slice(c_start, c_end))
        tiles.append(tile_slice)

return tiles

def fixBackground(self, image):

Definition at line 717 of file _task.py.

◆ inputCoadd

lsst.pipe.tasks.prettyPictureMaker._task.inputCoadd : `Exposure`
# Find the median value in the image, which is likely to be
# close to average background. Note this doesn't work well
# in fields with high density or diffuse flux.
maxLikely = np.median(image, axis=None)

# find all the pixels that are fainter than this
# and find the std. This is just used as an initialization
# parameter and doesn't need to be accurate.
mask = image < maxLikely
initial_std = (image[mask] - maxLikely).std()

# Don't do anything if there are no pixels to check
if np.any(mask):
    # use a minimizer to determine best mu and sigma for a Gaussian
    # given only samples below the mean of the Gaussian.
    _, sigma_hat = halfnorm.fit(np.abs(image[mask] - maxLikely))
    mu_hat = maxLikely
else:
    mu_hat, sigma_hat = (maxLikely, 2 * initial_std)

# create a new masking threshold that is the determined
# mean plus std from the fit
threshhold = mu_hat + sigma_hat
image_mask = image < threshhold

# create python slices that tile the image.
tiles = self._tile_slices(image, 25, 25)

yloc = []
xloc = []
values = []

# for each box find the middle position and the median background
# value in the window.
for xslice, yslice in tiles:
    ypos = (yslice.stop - yslice.start) / 2 + yslice.start
    xpos = (xslice.stop - xslice.start) / 2 + xslice.start
    yloc.append(ypos)
    xloc.append(xpos)
    window = image[yslice, xslice][image_mask[yslice, xslice]]
    if window.size > 0:
        value = np.median(window)
    else:
        value = 0
    values.append(value)

positions = np.meshgrid(np.arange(image.shape[0]), np.arange(image.shape[1]))
# create an interpolant for the background and interpolate over the image.
inter = RBFInterpolator(
    np.vstack((yloc, xloc)).T, values, kernel="thin_plate_spline", degree=4, smoothing=0.05
)
backgrounds = inter(np.array(positions)[::-1].reshape(2, -1).T).reshape(image.shape)

return backgrounds

def run(self, inputCoadd: Exposure):

Definition at line 785 of file _task.py.

◆ lower_pos

tuple lsst.pipe.tasks.prettyPictureMaker._task.lower_pos = (array - mu) < sigma
# Extract negative values efficiently
values_noise = array[array < self.config.noiseSearchThreshold]

# find the mode
center = mode(np.round(values_noise, 2)).mode

# extract the negative values
values_neg = array[array < center]

# Return infinity if no negative values found
if values_neg.size == 0:
    return 0, np.inf

try:
    # Fit half-normal distribution to absolute negative values
    mu, sigma = halfnorm.fit(np.abs(values_neg))
except (ValueError, RuntimeError):
    # Handle fitting failures (e.g., constant data, optimization issues)
    return 0, np.inf

return center, sigma

def _match_sigmas_and_recenter(self, *arrays, factor=1):

Definition at line 356 of file _task.py.

◆ mean

lsst.pipe.tasks.prettyPictureMaker._task.mean : `float`

Definition at line 292 of file _task.py.

◆ R

lsst.pipe.tasks.prettyPictureMaker._task.R : `int`
_DefaultName = "prettyPictureBackgroundFixerTask"
ConfigClass = PrettyPictureBackgroundFixerConfig

config: ConfigClass

def _neg_log_likelihood(self, params, x):

Definition at line 664 of file _task.py.

◆ r

lsst.pipe.tasks.prettyPictureMaker._task.r

Definition at line 111 of file _task.py.

◆ result

lsst.pipe.tasks.prettyPictureMaker._task.result : `Struct`

Definition at line 790 of file _task.py.

◆ results

lsst.pipe.tasks.prettyPictureMaker._task.results : `Struct` of `Mapping` of `str` to `ExposureF`

Definition at line 857 of file _task.py.

◆ sigma

lsst.pipe.tasks.prettyPictureMaker._task.sigma : `float`

Definition at line 294 of file _task.py.

◆ sigma_ratio

lsst.pipe.tasks.prettyPictureMaker._task.sigma_ratio = min_sig / sigma

Definition at line 363 of file _task.py.

◆ slices

lsst.pipe.tasks.prettyPictureMaker._task.slices : `list` of `tuple`

Definition at line 671 of file _task.py.