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

Plugin: spectral extraction #1514

Merged
merged 37 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
873e2e7
spectral extraction plugin - basic trace support
kecnry Jul 19, 2022
55c2984
add support for offsetting/shifting an existing trace
kecnry Jul 20, 2022
cd199c1
improved layer icon/label support for traces
kecnry Jul 20, 2022
208e069
remove plugin marks logic
kecnry Jul 20, 2022
270ece4
changes entry
kecnry Jul 20, 2022
2c138a8
minimal plugin test coverage
kecnry Jul 20, 2022
8726bce
barebones specviz2d plugin docs
kecnry Jul 20, 2022
a9fd4ca
add traitlet/widget for extraction window width
kecnry Jul 21, 2022
e555d8b
simple vs advanced mode: don't require outputting at intermediate steps
kecnry Jul 21, 2022
403fdc0
live-preview of trace/background/extraction regions
kecnry Jul 21, 2022
e8c92a1
hookup specreduce calls for background/extract steps
kecnry Jul 22, 2022
9d93e90
fix trace-offsetting
kecnry Jul 22, 2022
cf77854
data menu multiselect: trace objects are excluded from radio logic
kecnry Jul 22, 2022
8665e42
visual feedback of trace to silently ignore errors
kecnry Jul 22, 2022
1015506
test and docs coverage for background/extract steps
kecnry Jul 22, 2022
d4d2c36
show live-preview of extracted spectrum
kecnry Jul 22, 2022
4d2f370
use plugin for initial 1D spectrum (if not provided)
kecnry Jul 22, 2022
1425774
add spectral-extraction plugin to API docs
kecnry Jul 22, 2022
5c6fd37
use mouseover events to change active_step (controls visible marks)
kecnry Jul 25, 2022
9c78b8e
specviz2d: do not allow unloading original reference data
kecnry Jul 25, 2022
a09fba2
background/subtracted-background: fix linking from plugin output
kecnry Jul 25, 2022
0e6080c
simplify plugin logic
kecnry Jul 25, 2022
dfcd1d6
set correct spectral axis on extracted spectrum
kecnry Jul 26, 2022
6d2f465
remove support for peak_method
kecnry Jul 27, 2022
fb284c1
extraction to expose/plot in pixels
kecnry Jul 27, 2022
4f6eb1d
disable line lists and line analysis plugins when spectrum in pixels
kecnry Jul 27, 2022
4cc451a
fix failing tests
kecnry Jul 27, 2022
c5cdfd2
consistent default for add_data in API methods
kecnry Jul 28, 2022
10f9d63
API to display marks without having to manually open the plugin
kecnry Jul 28, 2022
5cd693c
update changelog
kecnry Aug 1, 2022
ed1c396
remove support for importing/exporting trace
kecnry Aug 1, 2022
0ac7c8b
fixed trace live-feedback updating when changing type
kecnry Aug 2, 2022
6550135
Apply suggestions from code review
kecnry Aug 2, 2022
31ff49e
remove white "shadows" from spectral extraction live-previews
kecnry Aug 2, 2022
74766f9
change buttons from Background/Subtract to Export
kecnry Aug 2, 2022
c42f1af
improve comment language
kecnry Aug 2, 2022
ffe90ea
fix two-sided to actually be two-sided
kecnry Aug 9, 2022
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
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Mosviz
Specviz
^^^^^^^

Specviz2d
^^^^^^^^^

- Spectral extraction plugin. [#1514]

API Changes
-----------

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Using Jdaviz
imviz/index.rst
specviz/index.rst
cubeviz/index.rst
specviz2d/index.rst
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to add specviz2d stuff to API docs too?

Also add new Specviz2D section to change log template in the release instructions?

On GitHub itself, should I create a new Specviz2D label and add corresponding Issue and Bug templates?

Copy link
Member Author

Choose a reason for hiding this comment

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

Since specviz2d is currently used by MAST (which links to a non-existent RTD page), I think we should... and we can always merge with mosviz later if we decide to go that route. Full docs are out-of-scope for this PR, I think/hope, but I just put the bare minimum so that all the plugin links point somewhere appropriate.

I added a specviz2d label in GitHub already (for this PR) and added a custom section in the change log (but not the template). The helper was already in the docs, but I'll add this plugin as well, thanks for catching that!

Copy link
Contributor

Choose a reason for hiding this comment

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

The book-keeping stuff (templates, release instructions) can be done after this is merged. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll let @rosteen decide if anything in JIRA needs updating to include specviz2d...

mosviz/index.rst
save_state.rst
display.rst
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ Plugins
.. automodapi:: jdaviz.configs.specviz.plugins.unit_conversion.unit_conversion
:no-inheritance-diagram:

.. automodapi:: jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction
:no-inheritance-diagram:

.. _jdaviz-api-nuts-bolts:

Nuts and Bolts
Expand Down
19 changes: 19 additions & 0 deletions docs/specviz2d/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.. image:: ../logos/specviz2d.svg
:width: 400

.. _specviz2d:

#########
Specviz2D
#########

Specviz2d is a tool for visualization and quick-look analysis of 2D astronomical spectra.

.. We do not want a real section here so navbar shows toc directly.

**Using Specviz**

.. toctree::
:maxdepth: 2

plugins
172 changes: 172 additions & 0 deletions docs/specviz2d/plugins.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
.. _specviz2d-plugins:

*********************
Data Analysis Plugins
*********************

The Specviz2D data analysis plugins are meant to aid quick-look analysis
of 2D spectroscopic data. All plugins are accessed via the :guilabel:`plugin`
icon in the upper right corner of the Specviz application.

.. _specviz2d-metadata-viewer:

Metadata Viewer
===============

.. seealso::

:ref:`Metadata Viewer <imviz_metadata-viewer>`
Imviz documentation on using the metadata viewer.

.. _specviz2d-plot-options:

Plot Options
============

.. seealso::

:ref:`Spectral Plot Options <specviz-plot-settings>`
Documentation on further details regarding the plot setting controls.

.. _specviz2d-subset-plugin:

Subset Tools
============

.. seealso::

:ref:`Subset Tools <imviz-subset-plugin>`
Imviz documentation describing the concept of subsets in Jdaviz.

.. _specviz2d-spectral-extraction:

Spectral Extraction
===================

The Spectral Extraction plugin exposes `specreduce <https://specreduce.readthedocs.io>`_
methods for tracing, background subtraction, and spectral extraction from 2D spectra.

Trace
-----

The first section of the plugin allows for creating and visualizing
`specreduce Trace <https://specreduce.readthedocs.io/en/latest/#module-specreduce.tracing>`_
objects.

Once you interact with any of the inputs in the extract step or hover over that area
of the plugin, the live visualization will change to show the trace as a solid line.

To create a new trace in the plugin, choose the desired "Trace Type" and edit any input arguments.
A preview of the trace will update in real time in the 2D spectrum viewer.

To export the trace as a data object into the 2D spectrum viewer (to access via the API or to
adjust plotting options), open the "Export Trace" panel, choose a label for the new data entry,
and click "Create". Note that this step is not required to create an extraction with simple
workflows.

Trace objects created outside of jdaviz can be loaded into the app via::

viz.app.add_data(my_trace)

and then added to the viewer through the data menu.

Once trace objects are loaded into the app, they can be offset (in the cross-dispersion direction)
by selecting the trace label, entering an offset, and overwriting the existing data entry (or
creating a new one) with the modified trace.

Background
----------

The background step of the plugin allows for creating background and background-subtracted
images via `specreduce.background <https://specreduce.readthedocs.io/en/latest/#module-specreduce.background>`_.

Once you interact with any of the inputs in the background step or hover over that area
of the plugin, the live visualization will change to show the center (dotted line) and edges
(solid lines) of the background region(s). Choose between creating the background
around the trace defined in the Trace section, or around a "Manual" flat trace.

To visualize the resulting background or background-subtracted image, click on the respective panel,
and choose a label for the new data entry. The exported images will now appear in the data dropdown
menu in the 2D spectrum viewer. To refine the trace based on the background-subtracted image, return
to the Trace step and select the exported background-subtracted image as input.

Extract
-------

The extraction step of the plugin extracts a 1D spectrum from an input 2D spectrum via
`specreduce.extract <https://specreduce.readthedocs.io/en/latest/#module-specreduce.extract>`_.

Once you interact with any of the inputs in the extract step or hover over that area
of the plugin, the live visualization will change to show the center (dotted line) and
edges (solid lines) of the extraction region.```

The input 2D spectrum defaults to "From Plugin", which will use the settings defined in the Background
step to create a background-subtracted image without needing to export it into the app itself.
To use a different 2D spectrum loaded in the app (or exported from the Background step), choose
that from the dropdown instead. To skip background subtraction, choose the original 2D spectrum
as input.

To visualize or export the resulting 2D spectrum, provide a data label and click "Extract". The
resulting spectrum object can be accessed from the API in the same way as any other
data product in the spectrum viewer.


.. _specviz2d-gaussian-smooth:

Gaussian Smooth
===============

.. seealso::

:ref:`Gaussian Smooth <gaussian-smooth>`
Specviz documentation on Gaussian Smooth.

.. _specviz2d-model-fitting:

Model Fitting
=============

.. seealso::

:ref:`Model Fitting <specviz-model-fitting>`
Specviz documentation on Model Fitting.


.. _specviz2d-unit-conversion:

Unit Conversion
===============

.. seealso::

:ref:`Unit Conversion <unit-conversion>`
Specviz documentation on Unit Conversion.


.. _specviz2d-line-lists:

Line Lists
==========

.. seealso::

:ref:`Line Lists <line-lists>`
Specviz documentation on Line Lists.


.. _specviz2d-line-analysis:

Line Analysis
=============

.. seealso::

:ref:`Line Analysis <line-analysis>`
Specviz documentation on Line Analysis.

.. _specviz2d-export-plot:

Export Plot
===========

This plugin allows exporting the plot in a given viewer to various image formats.
32 changes: 28 additions & 4 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,18 @@ def _link_new_data(self, reference_data=None, data_to_be_linked=None):
ref_data = dc[reference_data] if reference_data else dc[0]
linked_data = dc[data_to_be_linked] if data_to_be_linked else dc[-1]

if linked_data.meta.get('Plugin', None) == 'SpectralExtraction':
if 'Trace' in linked_data.meta:
links = [LinkSame(linked_data.components[2], ref_data.components[0]),
LinkSame(linked_data.components[0], ref_data.components[1])]
dc.add_link(links)
return
else:
links = [LinkSame(linked_data.components[0], ref_data.components[0]),
LinkSame(linked_data.components[1], ref_data.components[1])]
dc.add_link(links)
return

# The glue-astronomy SpectralCoordinates currently seems incompatible with glue
# WCSLink. This gets around it until there's an upstream fix.
if isinstance(linked_data.coords, SpectralCoordinates):
Expand Down Expand Up @@ -623,7 +635,9 @@ def get_data_from_viewer(self, viewer_reference, data_label=None,
if cls is not None:
# If data is one-dimensional, assume that it can be
# collapsed via the defined statistic
if cls == Spectrum1D:
if 'Trace' in layer_data.meta:
layer_data = layer_data.get_object()
elif cls == Spectrum1D:
layer_data = layer_data.get_object(cls=cls,
statistic=statistic)
else:
Expand Down Expand Up @@ -1238,8 +1252,13 @@ def vue_data_item_visibility(self, event):

replace = event.get('replace', False)
selected_items = viewer_item['selected_data_items']

if replace and visible:
selected_items = {id: 'visible' if id == item_id else 'hidden' for id in selected_items.keys()} # noqa
# trace items remain selected, even if the mode is in replace
keep_selected = [k for k, v in viewer_item['selected_data_items'].items()
if v != 'hidden' and
self._get_data_item_by_id(k).get('type') == 'trace']
selected_items = {id: 'visible' if id == item_id or id in keep_selected else 'hidden' for id in selected_items.keys()} # noqa
else:
selected_items[item_id] = 'visible' if visible else 'hidden'

Expand All @@ -1261,6 +1280,10 @@ def vue_call_viewer_method(self, event):
kwargs = event.get('kwargs', {})
return getattr(self._viewer_store[viewer_id], method)(*args, **kwargs)

def _get_data_item_by_id(self, data_id):
return next((x for x in self.state.data_items
if x['id'] == data_id), None)

def _update_selected_data_items(self, viewer_id, selected_items):
# Find the active viewer
viewer_item = self._viewer_item_by_id(viewer_id)
Expand All @@ -1275,8 +1298,7 @@ def _update_selected_data_items(self, viewer_id, selected_items):

# Include any selected data in the viewer
for data_id, visibility in selected_items.items():
label = next((x['name'] for x in self.state.data_items
if x['id'] == data_id), None)
label = self._get_data_item_by_id(data_id)['name']

if label is None:
warnings.warn(f"No data item with id '{data_id}' found in "
Expand Down Expand Up @@ -1370,6 +1392,8 @@ def _create_data_item(data):
component_ids = [str(c) for c in data.component_ids()]
if data.label == 'MOS Table':
typ = 'table'
elif 'Trace' in data.meta:
typ = 'trace'
elif ndims == 1:
typ = '1d spectrum'
elif ndims == 2 and wcsaxes is not None:
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/components/plugin_dataset_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
<template slot="selection" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
Copy link
Member Author

Choose a reason for hiding this comment

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

this just makes the left of the entries with and without icons line up better. I also applied this across all other instances, even though not all dropdowns use "manual entries".

{{ data.item.label }}
</span>
</div>
</template>
<template slot="item" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/components/plugin_layer_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
<div class="single-line" style="width: 100%">
<v-chip v-if="multiselect" style="width: calc(100% - 20px)">
<span>
<v-icon style='margin-left: -10px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-left: -10px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</v-chip>
<span v-else>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/components/plugin_viewer_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
<div class="single-line" style="width: 100%">
<v-chip v-if="multiselect" style="width: calc(100% - 20px)">
<span>
<v-icon style='margin-left: -10px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-left: -10px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</v-chip>
<span v-else>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
<v-icon v-if="data.item.icon" style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand Down
8 changes: 6 additions & 2 deletions jdaviz/components/viewer_data_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ module.exports = {
if (['image-viewer', 'spectrum-2d-viewer'].indexOf(this.$props.viewer.reference) !== -1) {
multi_select = false
}
} else if (this.$props.viewer.config === 'specviz2d') {
if (this.$props.viewer.reference === 'spectrum-2d-viewer') {
multi_select = false
}
}
return {
// default to passed values, whenever value or uncertainty are changed
Expand Down Expand Up @@ -161,9 +165,9 @@ module.exports = {
}
} else if (this.$props.viewer.config === 'specviz2d') {
if (this.$props.viewer.reference === 'spectrum-viewer') {
return item.ndims === 1 && this.dataItemInViewer(item, returnExtraItems)
return item.ndims === 1 && item.type!=='trace' && this.dataItemInViewer(item, returnExtraItems)
} else if (this.$props.viewer.reference === 'spectrum-2d-viewer') {
return item.ndims === 2 && this.dataItemInViewer(item, returnExtraItems)
return (item.ndims === 2 || item.type==='trace') && this.dataItemInViewer(item, returnExtraItems)
}
}
// for any situation not covered above, default to showing the entry
Expand Down
Loading