|
LSST Applications g00d0e8bbd7+edbf708997,g03191d30f7+9ce8016dbd,g1955dfad08+0bd186d245,g199a45376c+5137f08352,g1fd858c14a+a888a50aa2,g262e1987ae+45f9aba685,g29ae962dfc+1c7d47a24f,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3fd5ace14f+eed17d2c67,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+c4107e45b5,g67b6fd64d1+6dc8069a4c,g74acd417e5+f452e9c21a,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+2025e9ce17,g7cc15d900a+2d158402f9,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d4809ba88+c4107e45b5,g8d7436a09f+e96c132b44,g8ea07a8fe4+db21c37724,g98df359435+aae6d409c1,ga2180abaac+edbf708997,gac66b60396+966efe6077,gb632fb1845+88945a90f8,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gca7fc764a6+6dc8069a4c,gd7ef33dd92+6dc8069a4c,gda68eeecaf+7d1e613a8d,gdab6d2f7ff+f452e9c21a,gdbb4c4dda9+c4107e45b5,ge410e46f29+6dc8069a4c,ge41e95a9f2+c4107e45b5,geaed405ab2+e194be0d2b,w.2025.47
LSST Data Management Base Package
|
Classes | |
| class | SubtractBrightStarsConnections |
Variables | |
| logger = logging.getLogger(__name__) | |
| inputExposure : `~lsst.afw.image.ExposureF` | |
| inputBrightStarStamps : | |
| inputExtendedPsf : `~lsst.pipe.tasks.extended_psf.ExtendedPsf` | |
| dataId : `dict` or `~lsst.daf.butler.DataCoordinate` | |
| skyCorr : `~lsst.afw.math.backgroundList.BackgroundList`, optional | |
| refObjLoader : `~lsst.meas.algorithms.ReferenceObjectLoader`, optional | |
| subtractorExp : `~lsst.afw.image.ExposureF` | |
| invImages : `list` [`~lsst.afw.image.MaskedImageF`] | |
| invImage : `~lsst.afw.image.MaskedImageF` | |
| brightStarStamps : | |
| subtractor : `~lsst.afw.image.MaskedImageF` | |
| bool | multipleAnnuli , optional |
Retrieve extended PSF model and subtract bright stars at visit level.
| lsst.pipe.tasks.subtractBrightStars.brightStarStamps : |
bbox, invImage = self.preparePlaneModelStamp(brightStarStamp)
bbox.clip(self.inputExpBBox)
if bbox.getArea() > 0:
if multipleAnnuli:
cond = self.psf_annular_fluxes[:, 0] == brightStarStamp.optimalOuterRadius
psf_annular_flux = self.psf_annular_fluxes[cond, 1][0]
self.scaleModel(
invImage,
brightStarStamp,
inPlace=True,
nb90Rots=self.inv90Rots,
psf_annular_flux=psf_annular_flux,
)
else:
self.scaleModel(invImage, brightStarStamp, inPlace=True, nb90Rots=self.inv90Rots)
# Replace NaNs before subtraction (all NaNs have the NO_DATA flag).
invImage.image.array[np.isnan(invImage.image.array)] = 0
subtractor[bbox] += invImage[bbox]
return subtractor, invImage
def buildSubtractor(self, brightStarStamps, subtractor, invImages, multipleAnnuli=False):
Definition at line 810 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.dataId : `dict` or `~lsst.daf.butler.DataCoordinate` |
Definition at line 303 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.inputBrightStarStamps : |
Definition at line 295 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.inputExposure : `~lsst.afw.image.ExposureF` |
doWriteSubtractor = Field[bool](
doc="Should an exposure containing all bright star models be written to disk?",
default=True,
)
doWriteSubtractedExposure = Field[bool](
doc="Should an exposure with bright stars subtracted be written to disk?",
default=True,
)
magLimit = Field[float](
doc="Magnitude limit, in Gaia G; all stars brighter than this value will be subtracted",
default=18,
)
minValidAnnulusFraction = Field[float](
doc="Minimum number of valid pixels that must fall within the annulus for the bright star to be "
"saved for subsequent generation of a PSF.",
default=0.0,
)
numSigmaClip = Field[float](
doc="Sigma for outlier rejection; ignored if annularFluxStatistic != 'MEANCLIP'.",
default=4,
)
numIter = Field[int](
doc="Number of iterations of outlier rejection; ignored if annularFluxStatistic != 'MEANCLIP'.",
default=3,
)
warpingKernelName = ChoiceField[str](
doc="Warping kernel",
default="lanczos5",
allowed={
"bilinear": "bilinear interpolation",
"lanczos3": "Lanczos kernel of order 3",
"lanczos4": "Lanczos kernel of order 4",
"lanczos5": "Lanczos kernel of order 5",
"lanczos6": "Lanczos kernel of order 6",
"lanczos7": "Lanczos kernel of order 7",
},
)
scalingType = ChoiceField[str](
doc="How the model should be scaled to each bright star; implemented options are "
"`annularFlux` to reuse the annular flux of each stamp, or `leastSquare` to perform "
"least square fitting on each pixel with no bad mask plane set.",
default="leastSquare",
allowed={
"annularFlux": "reuse BrightStarStamp annular flux measurement",
"leastSquare": "find least square scaling factor",
},
)
annularFluxStatistic = ChoiceField[str](
doc="Type of statistic to use to compute annular flux.",
default="MEANCLIP",
allowed={
"MEAN": "mean",
"MEDIAN": "median",
"MEANCLIP": "clipped mean",
},
)
badMaskPlanes = ListField[str](
doc="Mask planes that, if set, lead to associated pixels not being included in the computation of "
"the scaling factor (`BAD` should always be included). Ignored if scalingType is `annularFlux`, "
"as the stamps are expected to already be normalized.",
# Note that `BAD` should always be included, as secondary detected
# sources (i.e., detected sources other than the primary source of
# interest) also get set to `BAD`.
default=("BAD", "CR", "CROSSTALK", "EDGE", "NO_DATA", "SAT", "SUSPECT", "UNMASKEDNAN"),
)
subtractionBox = ListField[int](
doc="Size of the stamps to be extracted, in pixels.",
default=(250, 250),
)
subtractionBoxBuffer = Field[float](
doc=(
"'Buffer' (multiplicative) factor to be applied to determine the size of the stamp the "
"processed stars will be saved in. This is also the size of the extended PSF model. The buffer "
"region is masked and contain no data and subtractionBox determines the region where contains "
"the data."
),
default=1.1,
)
doApplySkyCorr = Field[bool](
doc="Apply full focal plane sky correction before extracting stars?",
default=True,
)
refObjLoader = ConfigField[LoadReferenceObjectsConfig](
doc="Reference object loader for astrometric calibration.",
)
class SubtractBrightStarsTask(PipelineTask):
ConfigClass = SubtractBrightStarsConfig
_DefaultName = "subtractBrightStars"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Placeholders to set up Statistics if scalingType is leastSquare.
self.statsControl, self.statsFlag = None, None
# Warping control; only contains shiftingALg provided in config.
self.warpControl = WarpingControl(self.config.warpingKernelName)
def runQuantum(self, butlerQC, inputRefs, outputRefs):
# Docstring inherited.
inputs = butlerQC.get(inputRefs)
if inputs["inputExtendedPsf"].default_extended_psf is None:
if not self._detectorInRegions(inputs["inputExposure"], inputs["inputExtendedPsf"]):
self.log.warning(
"Extended PSF model is not available for detector %i. Skipping withouth processing this "
"exposure.",
inputs["inputExposure"].detector.getId(),
)
return None
dataId = butlerQC.quantum.dataId
refObjLoader = ReferenceObjectLoader(
dataIds=[ref.datasetRef.dataId for ref in inputRefs.refCat],
refCats=inputs.pop("refCat"),
name=self.config.connections.refCat,
config=self.config.refObjLoader,
)
subtractor, _, badStamps = self.run(**inputs, dataId=dataId, refObjLoader=refObjLoader)
if self.config.doWriteSubtractedExposure:
outputExposure = inputs["inputExposure"].clone()
outputExposure.image -= subtractor.image
if self.config.doApplySkyCorr and (inputs["skyCorr"] is not None):
outputExposure.image += inputs["skyCorr"].getImage()
else:
outputExposure = None
outputBackgroundExposure = subtractor if self.config.doWriteSubtractor else None
# In its current state, the code produces outputBadStamps which are the
# stamps of stars that have not been subtracted from the image for any
# reason. If all the stars are subtracted from the calexp, the output
# is an empty fits file.
output = Struct(
outputExposure=outputExposure,
outputBackgroundExposure=outputBackgroundExposure,
outputBadStamps=badStamps,
)
butlerQC.put(output, outputRefs)
def run(
self, inputExposure, inputBrightStarStamps, inputExtendedPsf, dataId, skyCorr=None, refObjLoader=None
):
Definition at line 293 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.inputExtendedPsf : `~lsst.pipe.tasks.extended_psf.ExtendedPsf` |
Definition at line 300 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.invImage : `~lsst.afw.image.MaskedImageF` |
self.inputExpBBox = inputExposure.getBBox()
if self.config.doApplySkyCorr and (skyCorr is not None):
self.log.info(
"Applying sky correction to exposure %s (exposure will be modified in-place).", dataId
)
self.applySkyCorr(inputExposure, skyCorr)
# Create an empty image the size of the exposure.
# TODO: DM-31085 (set mask planes).
subtractorExp = ExposureF(bbox=inputExposure.getBBox())
subtractor = subtractorExp.maskedImage
# Make a copy of the input model.
self.model = inputExtendedPsf(dataId["detector"]).clone()
self.modelStampSize = self.model.getDimensions()
# Number of 90 deg. rotations to reverse each stamp's rotation.
self.inv90Rots = 4 - inputBrightStarStamps.nb90Rots % 4
self.model = rotateImageBy90(self.model, self.inv90Rots)
brightStarList = self.makeBrightStarList(inputBrightStarStamps, inputExposure, refObjLoader)
invImages = []
subtractor, invImages = self.buildSubtractor(
inputBrightStarStamps, subtractor, invImages, multipleAnnuli=False
)
if brightStarList:
self.setMissedStarsStatsControl()
# This may change when multiple star bins are used for PSF
# creation.
innerRadius = inputBrightStarStamps._innerRadius
outerRadius = inputBrightStarStamps._outerRadius
brightStarStamps, badStamps = BrightStarStamps.initAndNormalize(
brightStarList,
innerRadius=innerRadius,
outerRadius=outerRadius,
nb90Rots=self.warpOutputs.nb90Rots,
imCenter=self.warper.modelCenter,
use_archive=True,
statsControl=self.missedStatsControl,
statsFlag=self.missedStatsFlag,
badMaskPlanes=self.warper.config.badMaskPlanes,
discardNanFluxObjects=False,
forceFindFlux=True,
)
self.metadata["subtractedStarCount"] = len(inputBrightStarStamps) + len(brightStarStamps)
self.psf_annular_fluxes = self.findPsfAnnularFluxes(brightStarStamps)
subtractor, invImages = self.buildSubtractor(
brightStarStamps, subtractor, invImages, multipleAnnuli=True
)
else:
self.metadata["subtractedStarCount"] = len(inputBrightStarStamps)
badStamps = []
badStamps = BrightStarStamps(badStamps)
return subtractorExp, invImages, badStamps
def _detectorInRegions(self, inputExposure, inputExtendedPsf):
Definition at line 780 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.invImages : `list` [`~lsst.afw.image.MaskedImageF`] |
Definition at line 319 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.logger = logging.getLogger(__name__) |
Definition at line 49 of file subtractBrightStars.py.
| bool lsst.pipe.tasks.subtractBrightStars.multipleAnnuli , optional |
Definition at line 821 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.refObjLoader : `~lsst.meas.algorithms.ReferenceObjectLoader`, optional |
Definition at line 310 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.skyCorr : `~lsst.afw.math.backgroundList.BackgroundList`, optional |
Definition at line 306 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.subtractor : `~lsst.afw.image.MaskedImageF` |
Definition at line 815 of file subtractBrightStars.py.
| lsst.pipe.tasks.subtractBrightStars.subtractorExp : `~lsst.afw.image.ExposureF` |
Definition at line 315 of file subtractBrightStars.py.