Skip to content

Commit

Permalink
EXP: Build test case for
Browse files Browse the repository at this point in the history
advanced aperture photometry.

Add tests that will fail without fix

WIP: How to actually fix this mess

Remove warning from doc

[ci skip] [rtd skip]
  • Loading branch information
pllim committed Aug 8, 2023
1 parent 0bbc1f8 commit 30f611d
Show file tree
Hide file tree
Showing 10 changed files with 330 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ Cubeviz
Imviz
^^^^^

- Fixed inaccurate results when aperture photometry is performed on non-reference data
that are of a different pixel scale or are rotated w.r.t. the reference data when
linked by WCS. [#2154]

Mosviz
^^^^^^

Expand Down
4 changes: 0 additions & 4 deletions docs/imviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,6 @@ Simple Aperture Photometry

Regardless of your workflow, any WCS distortion in an image is ignored.

When you have multiple images linked by WCS and they have different
pixel scales or sky orientation, the selected aperture may be incorrectly defined
for images that are not the reference image (usually the first loaded one).

This plugin performs simple aperture photometry
and plots a radial profile for one object within
an interactively selected region. A typical workflow is as follows:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ def vue_recenter_subset(self, *args):
data = self.dataset.selected_dc_item
comp = data.get_component(data.main_components[0])
comp_data = comp.data
phot_aperstats = ApertureStats(comp_data, aperture)
phot_aperstats = ApertureStats(comp_data, aperture, wcs=data.coords)

# Centroid was calculated in selected data, which might or might not be
# the reference data. However, Subset is always defined w.r.t.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

__all__ = ['SimpleAperturePhotometry']

# TODO: This plugin needs to show params wrt ref data because that is how glue
# defined it, but then it needs to do internal calculation using region
# that took account of the dither.


@tray_registry('imviz-aper-phot-simple', label="Imviz Simple Aperture Photometry")
class SimpleAperturePhotometry(PluginTemplateMixin, DatasetSelectMixin, TableMixin, PlotMixin):
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
57 changes: 56 additions & 1 deletion jdaviz/configs/imviz/tests/test_simple_aper_phot.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import pytest
import numpy as np
from astropy import units as u
from astropy.io import fits
from astropy.tests.helper import assert_quantity_allclose
from astropy.utils.data import get_pkg_data_filename
from numpy.testing import assert_allclose, assert_array_equal
from photutils.aperture import (ApertureStats, CircularAperture, EllipticalAperture,
RectangularAperture, EllipticalAnnulus)
from regions import CircleAnnulusPixelRegion, PixCoord
from regions import CircleAnnulusPixelRegion, CirclePixelRegion, RectanglePixelRegion, PixCoord

from jdaviz.configs.imviz.plugins.aper_phot_simple.aper_phot_simple import (
_curve_of_growth, _radial_profile)
Expand Down Expand Up @@ -184,6 +186,59 @@ def test_plugin_no_wcs(self):
assert_array_equal(tbl['sky_center'], None)


class TestAdvancedAperPhot:
@pytest.fixture(autouse=True)
def setup_class(self, imviz_helper):
# Reference image
fn_1 = get_pkg_data_filename('data/gauss100_fits_wcs.fits')
imviz_helper.load_data(fn_1)
# Different pixel scale
imviz_helper.load_data(get_pkg_data_filename('data/gauss100_fits_wcs_block_reduced.fits'))
# Different pixel scale + rotated
imviz_helper.load_data(get_pkg_data_filename('data/gauss100_fits_wcs_block_reduced_rotated.fits')) # noqa: E501

# Reference image again but without any WCS
data = fits.getdata(fn_1, ext=0)
imviz_helper.load_data(data, data_label='no_wcs')

# Link them by WCS
imviz_helper.link_data(link_type='wcs')

# Regions to be used for aperture photometry
regions = []
positions = [(145.1, 168.3), (84.7, 224.1), (48.3, 200.3)]
for x, y in positions:
regions.append(CirclePixelRegion(center=PixCoord(x=x, y=y), radius=5))
regions.append(RectanglePixelRegion(center=PixCoord(x=229, y=152), width=17, height=5))
imviz_helper.load_regions(regions)

self.imviz = imviz_helper
self.viewer = imviz_helper.default_viewer
self.phot_plugin = imviz_helper.plugins["Imviz Simple Aperture Photometry"]._obj

# Data has a mean background of 5.
self.phot_plugin.bg_subset_selected = 'Manual'
self.phot_plugin.background_value = 5.0

@pytest.mark.parametrize('data_label', [
'gauss100_fits_wcs[PRIMARY,1]',
'gauss100_fits_wcs_block_reduced[PRIMARY,1]',
'gauss100_fits_wcs_block_reduced_rotated[PRIMARY,1]',
'no_wcs'])
@pytest.mark.parametrize(('subset_label', 'expected_sum'), [
('Subset 1', 738.8803424408962),
('Subset 2', 348.33262363800094),
('Subset 3', 857.5194857987592),
('Subset 4', 762.3263959884644)])
def test_aperphot(self, data_label, subset_label, expected_sum):
"""All data should give similar result for the same Subset."""
self.phot_plugin.dataset_selected = data_label
self.phot_plugin.subset_selected = subset_label
self.phot_plugin.vue_do_aper_phot()
tbl = self.imviz.get_aperture_photometry_results()
assert_allclose(tbl['sum'][-1], expected_sum)


def test_annulus_background(imviz_helper):
from photutils.datasets import make_4gaussians_image

Expand Down
24 changes: 13 additions & 11 deletions jdaviz/core/region_translators.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _get_region_from_spatial_subset(plugin_obj, subset_label):
The plugin is assumed to have a special setup that gives
it access to these attributes: ``app`` and ``dataset_selected``.
The ``app._jdaviz_helper.default_viewer`` attribute must also
exist and point to an image viewer that has a ``_get_real_xy``
exist and point to an image viewer that has a ``get_link_type``
method.
subset_label : str
Expand All @@ -41,7 +41,8 @@ def _get_region_from_spatial_subset(plugin_obj, subset_label):
Returns
-------
reg : `regions.Region`
An equivalent ``regions`` shape.
An equivalent ``regions`` shape. This can be a pixel or sky
region, so the plugin needs to be able to deal with both.
Raises
------
Expand All @@ -59,18 +60,19 @@ def _get_region_from_spatial_subset(plugin_obj, subset_label):
if sbst.data.label == plugin_obj.dataset_selected:
reg = sbst.data.get_selection_definition(
subset_id=subset_label, format='astropy-regions')

# Works around https://github.com/glue-viz/glue-astronomy/issues/52
# Assume it is always pixel region, not sky region. Even with multiple
# viewers, they all seem to share the same reference image even when it is
# not loaded in all the viewers, so use default viewer.
# Even with multiple viewers, they all seem to share the same
# reference image even when it is not loaded in all the viewers,
# so use default viewer.
viewer = plugin_obj.app._jdaviz_helper.default_viewer
link_type = viewer.get_link_type(plugin_obj.dataset_selected)

x, y, _, _ = viewer._get_real_xy(
plugin_obj.app.data_collection[plugin_obj.dataset_selected],
reg.center.x, reg.center.y)
reg.center.x = x
reg.center.y = y
return reg
if link_type == 'wcs':
return reg.to_sky(
plugin_obj.app.data_collection[plugin_obj.dataset_selected].coords)
else: # pixels or self
return reg
else:
raise ValueError(f'Subset "{subset_label}" not found')

Expand Down
Loading

0 comments on commit 30f611d

Please sign in to comment.