Skip to content

Commit

Permalink
Remove mask_comp and mask_pupil from DonutStamp since they don't pers…
Browse files Browse the repository at this point in the history
…ist and mask is already contained in MaskedImage stamp.
  • Loading branch information
jbkalmbach committed Jan 26, 2024
1 parent 2077b6f commit 7c2e4c7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 110 deletions.
8 changes: 8 additions & 0 deletions doc/versionHistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
Version History
##################

.. _lsst.ts.wep-8.3.0:

-------------
8.3.0
-------------

* Remove mask_comp and mask_pupil from DonutStamp since they don't persist and mask is already contained in MaskedImage stamp.

.. _lsst.ts.wep-8.2.0:

-------------
Expand Down
23 changes: 20 additions & 3 deletions python/lsst/ts/wep/task/cutOutDonutsBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
"CutOutDonutsBaseTask",
]

import os
import lsst.afw.cameraGeom
import lsst.afw.image as afwImage
import lsst.pex.config as pexConfig
import lsst.pipe.base as pipeBase
import numpy as np
Expand All @@ -43,7 +45,9 @@
createInstDictFromConfig,
getCameraFromButlerName,
getCamTypeFromButlerName,
getConfigDir,
)
from lsst.ts.wep.paramReader import ParamReader
from scipy.ndimage import binary_dilation, rotate, shift
from scipy.signal import correlate

Expand Down Expand Up @@ -391,6 +395,12 @@ def cutOutStamps(self, exposure, donutCatalog, defocalType, cameraName):
camType = getCamTypeFromButlerName(cameraName, detectorType)
bandpass = exposure.filter.bandLabel

# Set boundary thickness for masks to be consistent with exp algorithm
configDir = getConfigDir()
algoParams = ParamReader()
algoParams.setFilePath(os.path.join(configDir, "cwfs", "algo", "exp.yaml"))
boundaryT = algoParams.getSetting("boundaryThickness")

# Run background subtraction
self.subtractBackground.run(exposure=exposure).background

Expand Down Expand Up @@ -519,9 +529,8 @@ def cutOutStamps(self, exposure, donutCatalog, defocalType, cameraName):
bandpass=bandpass,
archive_element=linear_wcs,
)
boundaryT = 1
maskScalingFactorLocal = 1
donutStamp.makeMasks(
donutStamp.comp_im.makeBlendedMask(
inst, self.opticalModel, boundaryT, maskScalingFactorLocal
)

Expand Down Expand Up @@ -556,7 +565,15 @@ def cutOutStamps(self, exposure, donutCatalog, defocalType, cameraName):
donutStamp.stamp_im.image.array, eulerZ
)

donutStamp.stamp_im.setMask(donutStamp.mask_comp)
# Set masks
afwImage.Mask.addMaskPlane("DONUT")
donutMaskVal = afwImage.Mask.getPlaneBitMask("DONUT")
donutStamp.stamp_im.setMask(
afwImage.MaskX(
np.array(donutStamp.comp_im.mask_comp, dtype=np.int32)
* donutMaskVal
)
)

finalStamps.append(donutStamp)

Expand Down
42 changes: 0 additions & 42 deletions python/lsst/ts/wep/task/donutStamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ class DonutStamp(AbstractStamp):
bandpass: str
archive_element: Optional[afwTable.io.Persistable] = None
comp_im: CompensableImage = field(default_factory=CompensableImage)
mask_comp: afwImage.Mask = field(init=False)
mask_pupil: afwImage.Mask = field(init=False)

def __post_init__(self):
"""
Expand Down Expand Up @@ -238,46 +236,6 @@ def _setCompensableImage(self):
blendOffsets=blendOffsets.tolist(),
image=self.stamp_im.getImage().getArray(),
)
self.mask_pupil = afwImage.Mask()
self.mask_comp = afwImage.Mask()

def makeMasks(self, inst, model, boundaryT, maskScalingFactorLocal):
"""Get the binary mask which considers the obscuration and off-axis
correction.
Parameters
----------
inst : `Instrument`
Instrument to use.
model : `str`
Optical model. It can be "paraxial", "onAxis", or "offAxis".
boundaryT : `int`
Extended boundary in pixel. It defines how far the computation mask
extends beyond the pupil mask. And, in fft, it is also the width of
Neuman boundary where the derivative of the wavefront is set to
zero.
maskScalingFactorLocal : `float`
Mask scaling factor (for fast beam) for local correction.
Returns
-------
mask_pupil : `afwImage.Mask`
Non-padded mask for use at the offset planes.
mask_comp : `afwImage.Mask`
Padded mask for use at the offset planes.
"""

self.comp_im.makeBlendedMask(inst, model, boundaryT, maskScalingFactorLocal)

# Set masks
afwImage.Mask.addMaskPlane("DONUT")
donutMaskVal = afwImage.Mask.getPlaneBitMask("DONUT")
self.mask_comp = afwImage.Mask(
np.array(self.comp_im.mask_comp, dtype=np.int32) * donutMaskVal
)
self.mask_pupil = afwImage.Mask(
np.array(self.comp_im.mask_pupil, dtype=np.int32) * donutMaskVal
)

def getLinearWCS(self):
"""
Expand Down
9 changes: 9 additions & 0 deletions tests/task/test_cutOutDonutsBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ def testCutOutStamps(self):
donutStamps[0].stamp_im.image.array, expCutOut
)

# Test MaskPlaneDict has DONUT and mask has donut mask
self.assertIn(
"DONUT", list(donutStamps[0].stamp_im.mask.getMaskPlaneDict().keys())
)
self.assertCountEqual(
[0, donutStamps[0].stamp_im.mask.getPlaneBitMask("DONUT")],
np.unique(donutStamps[0].stamp_im.mask.array),
)

# Check that local linear WCS in archive element is consistent with the
# original exposure WCS.
exposure_wcs = exposure.wcs
Expand Down
66 changes: 1 addition & 65 deletions tests/task/test_donutStamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import os
import unittest

import lsst.afw.image as afwImage
Expand All @@ -29,9 +28,8 @@
from lsst.afw.cameraGeom import FIELD_ANGLE, FOCAL_PLANE
from lsst.daf.base import PropertyList
from lsst.ts.wep.cwfs.compensableImage import CompensableImage
from lsst.ts.wep.cwfs.instrument import Instrument
from lsst.ts.wep.task.donutStamp import DonutStamp
from lsst.ts.wep.utils import CamType, DefocalType, getConfigDir
from lsst.ts.wep.utils import DefocalType


class TestDonutStamp(unittest.TestCase):
Expand Down Expand Up @@ -126,8 +124,6 @@ def testFactory(self):
self.assertEqual(bandpass, "r")

self.assertEqual(type(donutStamp.comp_im), CompensableImage)
self.assertEqual(type(donutStamp.mask_comp), afwImage.MaskX)
self.assertEqual(type(donutStamp.mask_pupil), afwImage.MaskX)
np.testing.assert_array_equal(
donutStamp.comp_im.getImg(), donutStamp.stamp_im.image.array
)
Expand Down Expand Up @@ -229,63 +225,3 @@ def testCalcFieldXY(self):
)
self.assertEqual(donutStamp.comp_im.fieldX, np.degrees(trueFieldAngleX))
self.assertEqual(donutStamp.comp_im.fieldY, np.degrees(trueFieldAngleY))

def testMakeMasks(self):
donutStamp = DonutStamp(
self.testStamps[0],
lsst.geom.SpherePoint(0.0, 0.0, lsst.geom.degrees),
lsst.geom.Point2D(2047.5, 2001.5),
np.array([[], []]).T,
DefocalType.Extra.value,
1.5e-3,
"R22_S11",
"LSSTCam",
"r",
)

# Set up instrument
instDataPath = os.path.join(getConfigDir(), "cwfs", "instData")
instConfigFile = os.path.join(
instDataPath, "lsstfam", "instParamPipeConfig.yaml"
)
maskConfigFile = os.path.join(instDataPath, "lsstfam", "maskMigrate.yaml")
inst = Instrument()
donutWidth = 126
inst.configFromFile(
donutWidth, CamType.LsstFamCam, instConfigFile, maskConfigFile
)

# Check that masks are empty at start
np.testing.assert_array_equal(
np.empty(shape=(0, 0)), donutStamp.mask_comp.getArray()
)
np.testing.assert_array_equal(
np.empty(shape=(0, 0)), donutStamp.mask_pupil.getArray()
)

# Check masks after creation
donutStamp.makeMasks(inst, "offAxis", 0, 1)
self.assertEqual(afwImage.MaskX, type(donutStamp.mask_comp))
self.assertEqual(afwImage.MaskX, type(donutStamp.mask_pupil))
self.assertIn("DONUT", list(donutStamp.mask_comp.getMaskPlaneDict().keys()))
self.assertIn("DONUT", list(donutStamp.mask_pupil.getMaskPlaneDict().keys()))
maskC = donutStamp.mask_comp.getArray()
maskP = donutStamp.mask_pupil.getArray()
# Donut should match
self.assertEqual(np.shape(maskC), (126, 126))
self.assertEqual(np.shape(maskP), (126, 126))
# Make sure not just an empty array
self.assertTrue(np.sum(maskC) > 0.0)
self.assertTrue(np.sum(maskP) > 0.0)
# Make sure bits set are donut bits
self.assertCountEqual(
[0, afwImage.Mask.getPlaneBitMask("DONUT")],
list(np.unique(donutStamp.mask_comp.array)),
)
self.assertCountEqual(
[0, afwImage.Mask.getPlaneBitMask("DONUT")],
list(np.unique(donutStamp.mask_pupil.array)),
)
# Donut at center of focal plane should be symmetric
np.testing.assert_array_equal(maskC[:63], maskC[-63:][::-1])
np.testing.assert_array_equal(maskP[:63], maskP[-63:][::-1])

0 comments on commit 7c2e4c7

Please sign in to comment.