Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conical aperture support in the spectral extraction plugin #2679

Merged
merged 56 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f35f7bc
Add conical aperture support in the spectral extraction plugin
javerbukh Jan 26, 2024
775a9ca
Rebase and remove commented out code
javerbukh Feb 1, 2024
a1efbc5
Fix style
javerbukh Feb 1, 2024
2e523b3
Add test
javerbukh Feb 6, 2024
1a3800b
Update test, address review comments, remove debug statements
javerbukh Feb 6, 2024
6ae4b15
Fix style
javerbukh Feb 6, 2024
ef5e97a
Address review comments
javerbukh Feb 8, 2024
3b8a3b3
Update test
javerbukh Feb 8, 2024
defe3b6
Remove change to SPECTRUM_SIZE in conftest
javerbukh Feb 9, 2024
a2b7a35
Add docs
javerbukh Feb 19, 2024
0a6468f
Address review comments
javerbukh Feb 19, 2024
7eabb16
Fix test
javerbukh Feb 19, 2024
59a3acc
Update test and change log
javerbukh Feb 19, 2024
f3a0118
Update docs/cubeviz/plugins.rst
javerbukh Feb 20, 2024
6ab130c
Change button to Slice to Wavelength
javerbukh Feb 20, 2024
42df577
Add link to photutils docs, use blank mask cube
javerbukh Feb 20, 2024
1428cb6
Use center as default aperture masking method
javerbukh Feb 20, 2024
24ee0ae
Switch test to use exact
javerbukh Feb 20, 2024
fb54e88
Fix test and change dtype
javerbukh Feb 20, 2024
c9c6c47
Fix typo
javerbukh Feb 20, 2024
9f854d3
Change test
javerbukh Feb 20, 2024
305890a
Throw exception if spectral axis is not in wavelength
javerbukh Feb 20, 2024
20e4bf2
Drastic change
javerbukh Feb 20, 2024
7be10fc
Change code
javerbukh Feb 21, 2024
4727f7d
Undo boolean conversion
javerbukh Feb 21, 2024
239d7f4
Remove loaded_mask_cube
javerbukh Feb 21, 2024
8bf7b55
jdaviz/configs/cubeviz/helper.py
javerbukh Feb 21, 2024
2621fa6
Move physical_type check to top
pllim Feb 21, 2024
7cb5328
Clean up test
pllim Feb 21, 2024
ba90b05
Simplify cone_aperture algorithm
pllim Feb 21, 2024
0bb158a
Have to flip shape so test would pass
pllim Feb 21, 2024
0c1ed55
Apply fractional pixel array when needed and update test
javerbukh Feb 22, 2024
c63cd0d
Fix style
javerbukh Feb 22, 2024
2350c72
More fixes
javerbukh Feb 22, 2024
76ac070
Return cone aperture as float32 pixel array
javerbukh Feb 22, 2024
0c968ae
Apply suggestions from code review
javerbukh Feb 23, 2024
5b575c5
Fix whitespace
javerbukh Feb 23, 2024
2fd9e63
Cover case where function is mean
javerbukh Feb 23, 2024
2e47c77
Remove subpixel option and add warning for exact plus min or max
javerbukh Feb 26, 2024
beed652
Extend fractional pixel functionality to cylindrical apertures
javerbukh Feb 27, 2024
497e5f9
Fix indentation
javerbukh Feb 27, 2024
8fc323f
Move aperture functionality and checks to get_aperture
javerbukh Feb 27, 2024
2c1dae4
Remove snackbar message
javerbukh Feb 27, 2024
5670532
Update test name
javerbukh Feb 27, 2024
1d7944d
Move display unit check to cone aperture section
javerbukh Feb 27, 2024
3efe0ff
Move commentS
javerbukh Feb 27, 2024
f26ab36
Move radius
javerbukh Feb 27, 2024
da78654
Clarify when physical type must be wavelength
javerbukh Feb 27, 2024
a3ad411
Remove old methods
javerbukh Feb 27, 2024
628b919
Change shape of test data
javerbukh Feb 27, 2024
40c3fed
Add test for non-wavelength axis units
javerbukh Feb 27, 2024
97090bb
pllim code clean-up and add tests
pllim Feb 28, 2024
e43992e
Add shape check in cone section of get_aperture
javerbukh Feb 28, 2024
0827ee6
Make test case off-center
pllim Feb 28, 2024
26043c7
pllim clean up exception handling
pllim Feb 28, 2024
7816905
Implement JDAT-4268 and add tests
pllim Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ New Features

- Live-preview of aperture selection in plugins. [#2664, #2684]

- Add conical aperture support to cubeviz in the spectral extraction plugin [#2679]

Cubeviz
^^^^^^^

Expand Down
17 changes: 17 additions & 0 deletions docs/cubeviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,23 @@ Click :guilabel:`EXTRACT` to produce a new 1D spectrum dataset
from the spectral cube, which has uncertainties propagated by
`astropy.nddata <https://docs.astropy.org/en/stable/nddata/nddata.html>`_.

If using a simple subset for the spatial aperture, an option to
make the aperture wavelength dependent will appear. If checked, this will
create a cone aperture that increases linearly with wavelength.
pllim marked this conversation as resolved.
Show resolved Hide resolved
The formula for that is::

radius = ((slice_wavelength / reference_wavelength) *
aperture.selected_spatial_region.radius)

The reference wavelength for the cone can be changed using the
:guilabel:`Adopt Current Slice` button.

The method of aperture masking can also be changed using the
pllim marked this conversation as resolved.
Show resolved Hide resolved
:guilabel:`Aperture masking method` dropdown. To see a description
for each of these options, please see
:ref:`photutils:photutils-aperture-overlap`.


.. _cubeviz-aper-phot:

Aperture Photometry
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/cubeviz/helper.py
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Cubeviz(ImageConfigHelper, LineListMixin):

_loaded_flux_cube = None
_loaded_uncert_cube = None
_loaded_mask_cube = None

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
14 changes: 11 additions & 3 deletions jdaviz/configs/cubeviz/plugins/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@

if data_type == 'mask':
# We no longer auto-populate the mask cube into a viewer
pass
app._jdaviz_helper._loaded_mask_cube = app.data_collection[data_label]

elif data_type == 'uncert':
app.add_data_to_viewer(uncert_viewer_reference_name, data_label)
Expand Down Expand Up @@ -319,6 +319,8 @@
app._jdaviz_helper._loaded_flux_cube = app.data_collection[data_label]
elif data_type == 'uncert':
app._jdaviz_helper._loaded_uncert_cube = app.data_collection[data_label]
elif data_type == 'mask':
app._jdaviz_helper._loaded_mask_cube = app.data_collection[data_label]


def _parse_esa_s3d(app, hdulist, data_label, ext='DATA', flux_viewer_reference_name=None,
Expand Down Expand Up @@ -368,8 +370,10 @@

if data_type == 'flux':
app._jdaviz_helper._loaded_flux_cube = app.data_collection[data_label]
if data_type == 'uncert':
elif data_type == 'uncert':

Check warning on line 373 in jdaviz/configs/cubeviz/plugins/parsers.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/parsers.py#L373

Added line #L373 was not covered by tests
app._jdaviz_helper._loaded_uncert_cube = app.data_collection[data_label]
elif data_type == 'mask':
app._jdaviz_helper._loaded_mask_cube = app.data_collection[data_label]

Check warning on line 376 in jdaviz/configs/cubeviz/plugins/parsers.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/parsers.py#L375-L376

Added lines #L375 - L376 were not covered by tests


def _parse_spectrum1d_3d(app, file_obj, data_label=None,
Expand Down Expand Up @@ -422,7 +426,9 @@
elif attr == 'uncertainty':
app.add_data_to_viewer(uncert_viewer_reference_name, cur_data_label)
app._jdaviz_helper._loaded_uncert_cube = app.data_collection[cur_data_label]
# We no longer auto-populate the mask cube into a viewer
elif attr == 'mask':

Check warning on line 429 in jdaviz/configs/cubeviz/plugins/parsers.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/parsers.py#L429

Added line #L429 was not covered by tests
# We no longer auto-populate the mask cube into a viewer
app._jdaviz_helper._loaded_mask_cube = app.data_collection[cur_data_label]

Check warning on line 431 in jdaviz/configs/cubeviz/plugins/parsers.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/parsers.py#L431

Added line #L431 was not covered by tests


def _parse_spectrum1d(app, file_obj, data_label=None, spectrum_viewer_reference_name=None):
Expand Down Expand Up @@ -470,6 +476,8 @@
elif data_type == 'uncert':
app.add_data_to_viewer(uncert_viewer_reference_name, data_label)
app._jdaviz_helper._loaded_uncert_cube = app.data_collection[data_label]
elif data_type == 'mask':
app._jdaviz_helper._loaded_mask_cube = app.data_collection[data_label]

Check warning on line 480 in jdaviz/configs/cubeviz/plugins/parsers.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/parsers.py#L479-L480

Added lines #L479 - L480 were not covered by tests


def _parse_gif(app, file_obj, data_label=None, flux_viewer_reference_name=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
NDDataArray, StdDevUncertainty, NDUncertainty
)
from traitlets import Any, Bool, Dict, Float, List, Unicode, observe
from photutils.aperture import CircularAperture
from specutils import Spectrum1D

from jdaviz.core.custom_traitlets import FloatHandleEmpty
from jdaviz.core.events import SnackbarMessage, SliceWavelengthUpdatedMessage
Expand Down Expand Up @@ -48,14 +50,18 @@
Subset to use for the spectral extraction, or ``Entire Cube``.
* ``add_results`` (:class:`~jdaviz.core.template_mixin.AddResults`)
* :meth:`collapse`
* ``wavelength_dependent``:
When true, the cone_aperture method will be used to determine the mask.
* ``reference_wavelength``:
The wavelength that will be used to calculate the radius of the cone through the cube.
* ``aperture_method`` (:class:`~jdaviz.core.template_mixin.SelectPluginComponent`):
Extract spectrum using an aperture masking method in place of the subset mask.
"""
template_file = __file__, "spectral_extraction.vue"
uses_active_status = Bool(True).tag(sync=True)

# feature flag for cone support
dev_cone_support = Bool(False).tag(sync=True) # when enabling: add entries to docstring
# feature flag for background cone support
dev_bg_support = Bool(False).tag(sync=True) # when enabling: add entries to docstring
dev_subpixel_support = Bool(False).tag(sync=True) # when enabling: add entries to docstring

active_step = Unicode().tag(sync=True)

Expand All @@ -69,14 +75,15 @@
bg_scale_factor = Float(1).tag(sync=True)
bg_wavelength_dependent = Bool(False).tag(sync=True)

subpixel = Bool(False).tag(sync=True)

function_items = List().tag(sync=True)
function_selected = Unicode('Sum').tag(sync=True)
filename = Unicode().tag(sync=True)
extracted_spec_available = Bool(False).tag(sync=True)
overwrite_warn = Bool(False).tag(sync=True)

aperture_method_items = List(['exact', 'subpixel', 'center']).tag(sync=True)
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
aperture_method_selected = Unicode('exact').tag(sync=True)
kecnry marked this conversation as resolved.
Show resolved Hide resolved

# export_enabled controls whether saving to a file is enabled via the UI. This
# is a temporary measure to allow server-installations to disable saving server-side until
# saving client-side is supported
Expand Down Expand Up @@ -113,6 +120,12 @@
selected='function_selected',
manual_options=['Mean', 'Min', 'Max', 'Sum']
)
self.aperture_method = SelectPluginComponent(
self,
items='aperture_method_items',
selected='aperture_method_selected',
manual_options=['exact', 'subpixel', 'center']
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
)
self._set_default_results_label()
self.add_results.viewer.filters = ['is_spectrum_viewer']

Expand All @@ -135,13 +148,11 @@
@property
def user_api(self):
expose = ['function', 'spatial_subset', 'aperture',
'add_results', 'collapse_to_spectrum']
if self.dev_cone_support:
expose += ['wavelength_dependent', 'reference_wavelength']
'add_results', 'collapse_to_spectrum',
'wavelength_dependent', 'reference_wavelength',
'aperture_method']
if self.dev_bg_support:
expose += ['background', 'bg_wavelength_dependent']
if self.dev_subpixel_support:
expose += ['subpixel']

return PluginUserApi(self, expose=expose)

Expand Down Expand Up @@ -205,30 +216,43 @@
"""
spectral_cube = self._app._jdaviz_helper._loaded_flux_cube
uncert_cube = self._app._jdaviz_helper._loaded_uncert_cube
uncertainties = None

# This plugin collapses over the *spatial axes* (optionally over a spatial subset,
# defaults to ``No Subset``). Since the Cubeviz parser puts the fluxes
# and uncertainties in different glue Data objects, we translate the spectral
# cube and its uncertainties into separate NDDataArrays, then combine them:
if self.aperture.selected != self.aperture.default_text:
if self.aperture.selected != self.aperture.default_text and self.wavelength_dependent:
nddata = spectral_cube.get_subset_object(
subset_id=self.aperture.selected, cls=NDDataArray
)
uncertainties = uncert_cube.get_subset_object(
subset_id=self.aperture.selected, cls=StdDevUncertainty
if uncert_cube:
uncertainties = uncert_cube.get_subset_object(

Check warning on line 230 in jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py#L229-L230

Added lines #L229 - L230 were not covered by tests
subset_id=self.aperture.selected, cls=StdDevUncertainty
)
mask = self.cone_aperture()

Check warning on line 233 in jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py#L233

Added line #L233 was not covered by tests

elif self.aperture.selected != self.aperture.default_text:
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
nddata = spectral_cube.get_subset_object(
subset_id=self.aperture.selected, cls=NDDataArray
)
if uncert_cube:
uncertainties = uncert_cube.get_subset_object(
subset_id=self.aperture.selected, cls=StdDevUncertainty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is wrong unless the uncertainty type is normalized outside of the parser code. Here we allow at least 3 different types of uncertainty (inverse variance, variance, standard deviation):

uncert=['ivar', 'err', 'var', 'uncert'],

But looks like we just parse those in blindly as-is. How do we know for sure at this point that the uncertainty is always standard deviation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To this effect, we also need to double check that mask values are being used as intended. Usually telescope ship the MASK as DQ arrays on bitplane, not pure boolean. For display purpose, does not matter, but now that you are passing it into some sort of extraction, how is this mask actually used? Not all "bad" pixels have the same level of badness. Here are example bitplane values.

https://github.com/spacetelescope/stginga/blob/master/stginga/data/dqflags_jwst.txt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

)
mask = nddata.mask
else:
nddata = spectral_cube.get_object(cls=NDDataArray)
uncertainties = uncert_cube.get_object(cls=StdDevUncertainty)

if uncert_cube:
uncertainties = uncert_cube.get_object(cls=StdDevUncertainty)
mask = nddata.mask
# Use the spectral coordinate from the WCS:
if '_orig_spec' in spectral_cube.meta:
wcs = spectral_cube.meta['_orig_spec'].wcs.spectral
else:
wcs = spectral_cube.coords.spectral

flux = nddata.data << nddata.unit
mask = nddata.mask

nddata_reshaped = NDDataArray(
flux, mask=mask, uncertainty=uncertainties, wcs=wcs, meta=nddata.meta
Expand Down Expand Up @@ -284,6 +308,38 @@

return collapsed_spec

def cone_aperture(self):
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
if not self._app._jdaviz_helper._loaded_mask_cube:
snackbar_message = SnackbarMessage(

Check warning on line 313 in jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py#L313

Added line #L313 was not covered by tests
"Cannot create cone aperture without valid mask cube loaded.",
color="error",
sender=self)
self.hub.broadcast(snackbar_message)
return

Check warning on line 318 in jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py#L317-L318

Added lines #L317 - L318 were not covered by tests
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
# Retrieve mask cube and create array to represent the cone mask
mask_cube = self._app._jdaviz_helper._loaded_mask_cube.get_object(cls=Spectrum1D,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand why the mask handling here is different from the "not cone" case. Why the inconsistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use a different mask handling because the aperture of the cone is different at each slice, where as when using a spatial subset that mask is the same throughout the cube.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But mask cube was not even consider for the other case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the mask is provided by the spatial subset. The cone aperture just uses the center and radius from the subset and calculates the mask based on the mask cube.

statistic=None)
flux_cube = self._app._jdaviz_helper._loaded_flux_cube.get_object(cls=Spectrum1D,
statistic=None)
masks_boolean_values = np.zeros_like(mask_cube.flux.value)

# Center is reverse coordinates
center = (self.aperture.selected_spatial_region.center.y,
self.aperture.selected_spatial_region.center.x)
# TODO: Replace with code for retrieving display_unit in cubeviz when it is available
display_unit = flux_cube.spectral_axis.unit

# Loop through cube and create cone aperture at each wavelength. Then convert that to a
# mask using the selected aperture method and add that to a mask cube.
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
for index, wavelength in enumerate(mask_cube.spectral_axis):
radius = ((wavelength.to(display_unit).value / self.reference_wavelength) *
pllim marked this conversation as resolved.
Show resolved Hide resolved
self.aperture.selected_spatial_region.radius)
aperture = CircularAperture(center, r=radius)
slice_mask = aperture.to_mask(method=self.aperture_method_selected).to_image(
(len(mask_cube.flux), len(mask_cube.flux[0])))
masks_boolean_values[:, :, index] = ~(slice_mask > 0)
return masks_boolean_values

def vue_spectral_extraction(self, *args, **kwargs):
self.collapse_to_spectrum(add_data=True)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
hint="Select a spatial region to extract its spectrum."
/>

<v-row v-if="aperture_selected !== 'Entire Cube' && !aperture_selected_validity.is_aperture && dev_cone_support">
<v-row v-if="aperture_selected !== 'Entire Cube' && !aperture_selected_validity.is_aperture">
<span class="v-messages v-messages__message text--secondary">
{{aperture_selected}} does not support wavelength dependence (cone support): {{aperture_selected_validity.aperture_message}}.
</span>
</v-row>

<div v-if="aperture_selected_validity.is_aperture && dev_cone_support">
<div v-if="aperture_selected_validity.is_aperture">
<v-row>
<v-switch
v-model="wavelength_dependent"
Expand Down Expand Up @@ -56,7 +56,7 @@
<v-row justify="end">
<j-tooltip tooltipcontent="Select the slice nearest the reference wavelength">
<plugin-action-button :results_isolated_to_plugin="true" @click="goto_reference_wavelength">
Slice to Reference Wavelength
Slice to Wavelength
</plugin-action-button>
</j-tooltip>
</v-row>
Expand All @@ -80,16 +80,15 @@
</span>
</v-row>

<v-row v-if="bg_selected !== 'None' && !bg_selected_validity.is_aperture && dev_cone_support">
<v-row v-if="bg_selected !== 'None' && !bg_selected_validity.is_aperture">
<span class="v-messages v-messages__message text--secondary">
{{bg_selected}} does not support wavelength dependence (cone support): {{bg_selected_validity.aperture_message}}.
</span>
</v-row>

<div v-if="aperture_selected_validity.is_aperture
&& bg_selected_validity.is_aperture
&& wavelength_dependent
&& dev_cone_support">
&& wavelength_dependent">
<v-row>
<v-switch
v-model="bg_wavelength_dependent"
Expand Down Expand Up @@ -118,28 +117,30 @@
<div @mouseover="() => active_step='ext'">
<j-plugin-section-header :active="active_step==='ext'">Extract</j-plugin-section-header>

<v-row v-if="aperture_selected !== 'None' && !aperture_selected_validity.is_aperture && dev_subpixel_support">
<v-row v-if="aperture_selected !== 'None' && !aperture_selected_validity.is_aperture">
<span class="v-messages v-messages__message text--secondary">
Aperture: {{aperture_selected}} does not support subpixel: {{aperture_selected_validity.aperture_message}}.
</span>
</v-row>
<v-row v-if="bg_selected !== 'None' && !bg_selected_validity.is_aperture && dev_subpixel_support">
<v-row v-if="bg_selected !== 'None' && !bg_selected_validity.is_aperture">
<span class="v-messages v-messages__message text--secondary">
Background: {{bg_selected}} does not support subpixel: {{bg_selected_validity.aperture_message}}.
</span>
</v-row>


<div v-if="(aperture_selected === 'Entire Cube' || aperture_selected_validity.is_aperture)
&& (bg_selected === 'None' || bg_selected_validity.is_aperture)
&& dev_subpixel_support">
&& (bg_selected === 'None' || bg_selected_validity.is_aperture)">
<v-row>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<v-row>
<v-row v-if="aperture_selected !== 'Entire Cube'">

We should also include an in-line warning if !aperture_selected_validity.is_aperture conflicts with the selection here (for example a composite subset and "subpixel"), disable clicking the extract button, and have checks in the python method that raise an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it currently stands, if you have Subset 1 selected and then you make it a composite subset, the option to make a cone wavelength dependent is removed and you see the following message in the UI: "Subset 1 does not support wavelength dependence (cone support): composite subsets are not supported." Is that sufficient or do you mean to cover another case with this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right - I forgot I did that 😝 That's probably fine for now, and I'll make a note of this in the final UI/UX review (we might instead want to continue showing the dropdown and have an error so that there is a consistent workflow from the API perspective).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am no good with the vue stuff but now that cylindrical also use the same algorithm as cone, any checks here need updating?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should work with #2684. If anything there needs updating, please open a ticket.

<v-switch
v-model="subpixel"
label="Subpixel"
hint="Extract spectrum using a subpixel aperture in place of the subset mask"
persistent-hint>
</v-switch>
<v-select
:menu-props="{ left: true }"
attach
:items="aperture_method_items.map(i => i.label)"
v-model="aperture_method_selected"
label="Aperture masking method"
hint="Extract spectrum using an aperture masking method in place of the subset mask."
persistent-hint
></v-select>
</v-row>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,35 @@ def test_aperture_markers(cubeviz_helper, spectrum1d_cube):
extract_plg._obj.vue_adopt_slice_as_reference()
extract_plg._obj.vue_goto_reference_wavelength()
assert slice_plg.slice == 1


def test_cone_aperture(cubeviz_helper, spectrum1d_cube_largest):
cubeviz_helper.load_data(spectrum1d_cube_largest)
cubeviz_helper.load_regions([CirclePixelRegion(PixCoord(1, 1), radius=0.5)])

mask_cube = Spectrum1D(flux=np.ones_like(spectrum1d_cube_largest.flux),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does ones mean here? Are they masked out or not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set flux = 1 MJy/sr everywhere in a fake cube. Extracted flux should equal (lambda/lambda_ref) * pi * r_ref^2
I will try to do this in a notebook...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what r_ref is. A complete notebook would be nice. Thanks!

spectral_axis=spectrum1d_cube_largest.spectral_axis)
cubeviz_helper.load_data(mask_cube, override_cube_limit=True)
cubeviz_helper._loaded_mask_cube = cubeviz_helper.app.data_collection[-1]

extract_plg = cubeviz_helper.plugins['Spectral Extraction']
slice_plg = cubeviz_helper.plugins['Slice']

extract_plg.aperture = 'Subset 1'
extract_plg.wavelength_dependent = True
assert cubeviz_helper._loaded_mask_cube.get_object(cls=Spectrum1D, statistic=None)

slice_plg.slice = 1
extract_plg._obj.vue_adopt_slice_as_reference()
cone_aperture = extract_plg._obj.cone_aperture()
assert (cone_aperture.shape ==
cubeviz_helper._loaded_flux_cube.get_object(cls=Spectrum1D, statistic=None).shape)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just check against the original input?

Suggested change
cubeviz_helper._loaded_flux_cube.get_object(cls=Spectrum1D, statistic=None).shape)
spectrum1d_cube_largest.shape)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is not resolved.


# Make sure that the cone created when the reference slice is 988 is different
# to the cone made at reference slice 1.
slice_plg.slice = 988
extract_plg._obj.vue_adopt_slice_as_reference()
cone_aperture_2 = extract_plg._obj.cone_aperture()

with pytest.raises(AssertionError, match="Arrays are not equal"):
assert np.testing.assert_array_equal(cone_aperture, cone_aperture_2)
5 changes: 5 additions & 0 deletions jdaviz/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ def spectrum1d_cube_larger():
return _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy, shape=(SPECTRUM_SIZE, 2, 4))


@pytest.fixture
def spectrum1d_cube_largest():
return _create_spectrum1d_cube_with_fluxunit(fluxunit=u.Jy, shape=(1000, 2, 4))


@pytest.fixture
def spectrum1d_cube_custom_fluxunit():
return _create_spectrum1d_cube_with_fluxunit
Expand Down
Loading