Skip to content

Commit

Permalink
Implement RMS asymmetry.
Browse files Browse the repository at this point in the history
  • Loading branch information
vrodgom committed Apr 12, 2024
1 parent 1869de2 commit f36ca2f
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 4 deletions.
31 changes: 27 additions & 4 deletions statmorph/statmorph.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
'multimode',
'intensity',
'deviation',
'rms_asymmetry',
'outer_asymmetry',
'shape_asymmetry',
'sersic_amplitude',
Expand Down Expand Up @@ -1654,9 +1655,9 @@ def _asymmetry_function(self, center, image, kind):
The (x,y) position of the center.
image : array-like
The 2D image.
kind : {'cas', 'outer', 'shape'}
kind : {'cas', 'rms', 'outer', 'shape'}
Whether to calculate the traditional CAS asymmetry (default),
outer asymmetry or shape asymmetry.
RMS asymmetry, outer asymmetry, or shape asymmetry.
Returns
-------
Expand Down Expand Up @@ -1686,7 +1687,7 @@ def _asymmetry_function(self, center, image, kind):
image_180 = np.where(~mask_symmetric, image_180, 0.0)

# Create aperture for the chosen kind of asymmetry
if kind == 'cas':
if kind == 'cas' or kind == 'rms':
r = self._petro_extent_cas * self._rpetro_circ_centroid
ap = photutils.aperture.CircularAperture(center, r)
elif kind == 'outer':
Expand All @@ -1706,6 +1707,9 @@ def _asymmetry_function(self, center, image, kind):
else:
raise NotImplementedError('Asymmetry kind not understood:', kind)

# Aperture area (in pixels)
ap_area = _aperture_area(ap, mask_symmetric)

# Apply eq. 10 from Lotz et al. (2004)
ap_abs_sum = ap.do_photometry(np.abs(image), method='exact')[0][0]
ap_abs_diff = ap.do_photometry(np.abs(image_180-image), method='exact')[0][0]
Expand All @@ -1720,11 +1724,19 @@ def _asymmetry_function(self, center, image, kind):
if kind == 'shape':
# The shape asymmetry of the background is zero
asym = ap_abs_diff / ap_abs_sum
elif kind == 'rms':
# Apply eq. 27 from Sazonova et al. (2024)
ap_sqr_sum = ap.do_photometry(image**2, method='exact')[0][0]
ap_sqr_diff = ap.do_photometry((image_180-image)**2, method='exact')[0][0]
if self.sky_sigma == -99.0: # invalid skybox
asym = ap_sqr_diff / ap_sqr_sum
else:
asym = (ap_sqr_diff - 2*ap_area*self.sky_sigma**2) / (
ap_sqr_sum - ap_area*self.sky_sigma**2)
else:
if self._sky_asymmetry == -99.0: # invalid skybox
asym = ap_abs_diff / ap_abs_sum
else:
ap_area = _aperture_area(ap, mask_symmetric)
asym = (ap_abs_diff - ap_area*self._sky_asymmetry) / ap_abs_sum

return asym
Expand Down Expand Up @@ -1842,6 +1854,17 @@ def asymmetry(self):

return asym

@lazyproperty
def rms_asymmetry(self):
"""
Calculate RMS asymmetry as described in Sazonova et al. (2024).
"""
image = self._cutout_stamp_maskzeroed
asym = self._asymmetry_function(self._asymmetry_center,
image, 'rms')

return asym

def _radius_at_fraction_of_total_cas(self, fraction):
"""
Specialization of ``_radius_at_fraction_of_total_circ`` for
Expand Down
1 change: 1 addition & 0 deletions statmorph/tests/test_statmorph.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ def setup_class(self):
'multimode': 0.23423423423423,
'intensity': 0.51203949030140,
'deviation': 0.01522525597953,
'rms_asymmetry': 0.0053900924481633,
'outer_asymmetry': -0.01821399684443,
'shape_asymmetry': 0.16308278287864,
'sersic_amplitude': 1296.95288208155739,
Expand Down

0 comments on commit f36ca2f

Please sign in to comment.