Skip to content

Commit

Permalink
Merge pull request #762 from javerbukh/better_linking
Browse files Browse the repository at this point in the history
Link mosviz data as a batch after they are loaded
  • Loading branch information
pllim authored Sep 7, 2021
2 parents 21386eb + 592b3f6 commit 12ee274
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 15 deletions.
17 changes: 15 additions & 2 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from regions import RectanglePixelRegion, PixCoord
from specutils import Spectrum1D

from glue.core.exceptions import IncompatibleAttribute
from glue.config import data_translator
from glue.config import settings as glue_settings
from glue.core import BaseData, HubListener, Data, DataCollection
Expand Down Expand Up @@ -148,6 +149,10 @@ def __init__(self, configuration=None, *args, **kwargs):
# Parse the yaml configuration file used to compose the front-end UI
self.load_configuration(configuration)

# If true, link data on load. If false, do not link data to speed up
# data loading
self.auto_link = kwargs.pop('auto_link', True)

# Subscribe to messages indicating that a new viewer needs to be
# created. When received, information is passed to the application
# handler to generate the appropriate viewer instance.
Expand Down Expand Up @@ -244,6 +249,11 @@ def _link_new_data(self):
any components are compatible with already loaded data. If so, link
them so that they can be displayed on the same profile1D plot.
"""
# Allow for batch linking of data in the parser rather than on
# data load
if not self.auto_link:
return

new_len = len(self.data_collection)
# Can't link if there's no world_component_ids
wc_new = self.data_collection[new_len-1].world_component_ids
Expand Down Expand Up @@ -442,8 +452,11 @@ def get_data_from_viewer(self, viewer_reference, data_label=None,

if cls is not None:
handler, _ = data_translator.get_handler_for(cls)
layer_data = handler.to_object(layer_data,
statistic=statistic)
try:
layer_data = handler.to_object(layer_data,
statistic=statistic)
except IncompatibleAttribute:
continue

data[label] = layer_data

Expand Down
30 changes: 28 additions & 2 deletions jdaviz/configs/mosviz/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class MosViz(ConfigHelper):

_default_configuration = "mosviz"

def __init__(self):
super().__init__()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

spec1d = self.app.get_viewer("spectrum-viewer")
spec1d.scales['x'].observe(self._update_spec2d_x_axis)
Expand Down Expand Up @@ -211,6 +211,8 @@ def load_data(self, spectra_1d=None, spectra_2d=None, images=None,
``images``. Can be a list of strings representing data labels
for each item in ``data_obj`` if ``data_obj`` is a list.
"""
# Link data after everything is loaded
self.app.auto_link = False

directory = kwargs.pop('directory', None)
instrument = kwargs.pop('instrument', None)
Expand Down Expand Up @@ -258,9 +260,27 @@ def load_data(self, spectra_1d=None, spectra_2d=None, images=None,
msg = SnackbarMessage(msg, color='warning', sender=self)
self.app.hub.broadcast(msg)

self.link_table_data(None)

# Any subsequently added data will automatically be linked
# with data already loaded in the app
self.app.auto_link = True

# Load the first object into the viewers automatically
self.app.get_viewer("table-viewer").figure_widget.highlighted = 0

def link_table_data(self, data_obj):
"""
Batch link data in the Mosviz table rather than doing it on
data load.
Parameters
----------
data_obj : obj
Input for Mosviz data parsers.
"""
super().load_data(data_obj, parser_reference="mosviz-link-data")

def load_spectra(self, spectra_1d, spectra_2d):
"""
Load 1D and 2D spectra using lists or strings to represent each.
Expand Down Expand Up @@ -343,8 +363,14 @@ def load_2d_spectra(self, data_obj, data_labels=None):
data_labels=data_labels)

def load_niriss_data(self, data_obj, data_labels=None):
self.app.auto_link = False

super().load_data(data_obj, parser_reference="mosviz-niriss-parser")

self.link_table_data(data_obj)

self.app.auto_link = True

def load_images(self, data_obj, data_labels=None, share_image=0):
"""
Load and parse a set of image objects. If providing a file path, it
Expand Down
34 changes: 34 additions & 0 deletions jdaviz/configs/mosviz/plugins/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from astropy.wcs import WCS
from asdf.fits_embed import AsdfInFits
from pathlib import Path
from glue.core.link_helpers import LinkSame

import glob

__all__ = ['mos_spec1d_parser', 'mos_spec2d_parser', 'mos_image_parser']
Expand Down Expand Up @@ -116,6 +118,38 @@ def _fields_from_ecsv(fname, fields, delimiter=","):
return parsed_fields


@data_parser_registry("mosviz-link-data")
def link_data_in_table(app, data_obj=None):
"""
Batch links data in the mosviz table viewer.
Parameters
----------
app : `~jdaviz.app.Application`
The application-level object used to reference the viewers.
data_obj : None
Passed in in order to use the data_parser_registry, otherwise
not used.
"""
mos_data = app.session.data_collection['MOS Table']
wc_spec_ids = []

# Optimize linking speed through a) delaying link manager updates with a
# context manager, b) handling intra-row linkage of 1D and 2D spectra in a
# loop, and c) handling inter-row linkage after that in one fell swoop.
with app.data_collection.delay_link_manager_update():
for index in range(len(mos_data.get_component('1D Spectra').data)):
spec_1d = mos_data.get_component('1D Spectra').data[index]
spec_2d = mos_data.get_component('2D Spectra').data[index]

wc_spec_1d = app.session.data_collection[spec_1d].world_component_ids
wc_spec_2d = app.session.data_collection[spec_2d].world_component_ids

wc_spec_ids.append(LinkSame(wc_spec_1d[0], wc_spec_2d[0]))

app.session.data_collection.add_link(wc_spec_ids)


@data_parser_registry("mosviz-nirspec-directory-parser")
def mos_nirspec_directory_parser(app, data_obj, data_labels=None):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def _on_viewer_data_changed(self, msg=None):
if msg is not None and msg.viewer_id != self._viewer_id:
return

self._viewer_data = self.app.get_data_from_viewer('spectrum-viewer')
self._viewer_data = self.app.get_data_from_viewer('spectrum-viewer',
include_subsets=False)

self.dc_items = [data.label
for data in self.app.data_collection
Expand Down
8 changes: 6 additions & 2 deletions jdaviz/configs/specviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from glue.core.subset import Subset
from glue.config import data_translator
from glue_jupyter.bqplot.profile import BqplotProfileView
from glue.core.exceptions import IncompatibleAttribute

import astropy
from astropy.utils.introspection import minversion
Expand Down Expand Up @@ -66,8 +67,11 @@ def data(self, cls=None):

if _class is not None:
handler, _ = data_translator.get_handler_for(_class)
layer_data = handler.to_object(layer_data,
statistic=statistic)
try:
layer_data = handler.to_object(layer_data,
statistic=statistic)
except IncompatibleAttribute:
continue
data.append(layer_data)

return data
Expand Down
8 changes: 4 additions & 4 deletions notebooks/MosvizExample.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# MOSViz example notebook"
"# Mosviz example notebook"
]
},
{
Expand All @@ -28,7 +28,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This starts MOSViz."
"Next, start Mosviz."
]
},
{
Expand All @@ -51,7 +51,7 @@
"source": [
"But before we can use it, we need some data.\n",
"\n",
"The MOSViz parsers accept lists of `Spectrum1D`, `SpectralCube`, and `CCDData` for 1D, 2D, and image data, respectively. Alternatively, users can also provide lists of file paths and MOSViz will internally attempt to parse them as their respective data types."
"The Mosviz parsers accept lists of `Spectrum1D`, `SpectralCube`, and `CCDData` for 1D, 2D, and image data, respectively. Alternatively, users can also provide lists of file paths and Mosviz will internally attempt to parse them as their respective data types."
]
},
{
Expand Down Expand Up @@ -210,7 +210,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"If no images are provided, MOSViz can still display the spectra."
"If no images are provided, Mosviz can still display the spectra."
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions notebooks/MosvizNIRISSExample.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "2b2fcea7",
"metadata": {},
"source": [
"# MOSViz NIRISS example notebook"
"# Mosviz NIRISS example notebook"
]
},
{
Expand All @@ -32,7 +32,7 @@
"id": "e3d6f12f",
"metadata": {},
"source": [
"This starts MOSViz."
"Next, start Mosviz."
]
},
{
Expand All @@ -44,9 +44,9 @@
},
"outputs": [],
"source": [
"from jdaviz.configs.mosviz.helper import MosViz\n",
"from jdaviz.configs.mosviz.helper import MosViz as Mosviz\n",
"\n",
"mosviz = MosViz()\n",
"mosviz = Mosviz()\n",
"mosviz.app"
]
},
Expand Down

0 comments on commit 12ee274

Please sign in to comment.