From ea64213db5916fd5e61b830e7d204fbd5daf7b87 Mon Sep 17 00:00:00 2001
From: Pey Lian Lim <2090236+pllim@users.noreply.github.com>
Date: Fri, 22 Jan 2021 15:42:09 -0500
Subject: [PATCH 1/6] WIP: Initial layout
---
README.rst | 19 +-
docs/imviz/index.rst | 30 ++
docs/index.rst | 1 +
docs/quickstart.rst | 2 +-
jdaviz/__init__.py | 1 +
jdaviz/cli.py | 4 +-
jdaviz/configs/__init__.py | 1 +
jdaviz/configs/imviz/__init__.py | 2 +
jdaviz/configs/imviz/helper.py | 12 +
jdaviz/configs/imviz/imviz.ipynb | 38 ++
jdaviz/configs/imviz/imviz.yaml | 20 +
jdaviz/configs/imviz/plugins/__init__.py | 2 +
jdaviz/configs/imviz/plugins/parsers.py | 28 +
jdaviz/configs/imviz/plugins/viewers.py | 61 +++
jdaviz/configs/imviz/tests/__init__.py | 1 +
jdaviz/core/config.py | 2 +
.../concepts/Imviz concept notebook.ipynb | 69 +++
...grammatic_viewers_from_blank_default.ipynb | 505 +++---------------
setup.cfg | 2 +
19 files changed, 350 insertions(+), 450 deletions(-)
create mode 100644 docs/imviz/index.rst
create mode 100644 jdaviz/configs/imviz/__init__.py
create mode 100644 jdaviz/configs/imviz/helper.py
create mode 100644 jdaviz/configs/imviz/imviz.ipynb
create mode 100644 jdaviz/configs/imviz/imviz.yaml
create mode 100644 jdaviz/configs/imviz/plugins/__init__.py
create mode 100644 jdaviz/configs/imviz/plugins/parsers.py
create mode 100644 jdaviz/configs/imviz/plugins/viewers.py
create mode 100644 jdaviz/configs/imviz/tests/__init__.py
create mode 100644 notebooks/concepts/Imviz concept notebook.ipynb
diff --git a/README.rst b/README.rst
index aef4e0188a..7a09305471 100644
--- a/README.rst
+++ b/README.rst
@@ -25,14 +25,16 @@ repository.
``jdaviz`` provides data viewers and analysis plugins that can be flexibly
combined as desired to create interactive applications that fit your workflow.
-Three named preset configurations for common use cases are provided. **Specviz**
-is a tool for visualization and quick-look analysis of 1D astronomical spectra.
-**MOSviz** is a visualization tool for many astronomical spectra,
-typically the output of a multi-object spectrograph (e.g., JWST
-NIRSpec), and includes viewers for 1D and 2D spectra as well as
-contextual information like on-sky views of the spectrograph slit.
-**Cubeviz** provides a view of spectroscopic data cubes (like those to be
-produced by JWST MIRI), along with 1D spectra extracted from the cube.
+Several named preset configurations for common use cases are provided:
+
+* **Specviz**: Visualization and quick-look analysis of 1D astronomical spectra.
+* **MOSviz**: Visualization tool for many astronomical spectra,
+ typically the output of a multi-object spectrograph (e.g., JWST
+ NIRSpec), and includes viewers for 1D and 2D spectra as well as
+ contextual information like on-sky views of the spectrograph slit.
+* **Cubeviz**: View of spectroscopic data cubes (like those to be
+ produced by JWST MIRI), along with 1D spectra extracted from the cube.
+* **Imviz**: Visualization and quick-look analysis of 2D astronomical images.
Installing
@@ -41,7 +43,6 @@ For details on installing and using JDAViz, see the
`Jdaviz documentation `_.
-
License
-------
diff --git a/docs/imviz/index.rst b/docs/imviz/index.rst
new file mode 100644
index 0000000000..7888565620
--- /dev/null
+++ b/docs/imviz/index.rst
@@ -0,0 +1,30 @@
+(TODO: Nice logo here.)
+
+.. _imviz:
+
+#####
+Imviz
+#####
+
+Imviz is a tool for visualization and quick-look analysis of 2D astronomical
+images. Like the rest of `jdaviz`, it is written in the Python programming
+language, and therefore can be run anywhere Python is supported
+(see :doc:`../installation`). Imviz is built on top of the
+`astrowidgets `_ using
+`Ginga `_ backend, providing a visual,
+interactive interface to the analysis capabilities in that library.
+
+Imviz allows images to be easily displayed and examined. It supports WCS,
+GWCS, ASDF, and so on. (TODO: Add content.)
+
+
+Using Imviz
+-----------
+
+To run Imviz in a notebook::
+
+ from jdaviz import Imviz
+ imviz = Imviz()
+ imviz.app
+
+(TODO: Add content.)
diff --git a/docs/index.rst b/docs/index.rst
index f0be8c39ac..09bf661584 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -38,6 +38,7 @@ Using Jdaviz
specviz/index.rst
cubeviz/index.rst
mosviz/index.rst
+ imviz/index.rst
Reference/API
=============
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index 1a3dccfb35..2b3b0fab38 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -40,4 +40,4 @@ or simply start a new Jupyter notebook and run the following in a cell::
app
To learn more about the various ``jdaviz`` application configurations and loading data, see the :ref:`cubeviz`,
-:ref:`specviz`, or :ref:`mosviz` tools.
+:ref:`specviz`, :ref:`mosviz`, or :ref:`imviz` tools.
diff --git a/jdaviz/__init__.py b/jdaviz/__init__.py
index 3dfdf818a4..c22aa5bce1 100644
--- a/jdaviz/__init__.py
+++ b/jdaviz/__init__.py
@@ -12,3 +12,4 @@
from jdaviz.configs.specviz2d import Specviz2d # noqa
from jdaviz.configs.mosviz import MosViz # noqa
from jdaviz.configs.cubeviz import CubeViz # noqa
+from jdaviz.configs.imviz import Imviz # noqa
diff --git a/jdaviz/cli.py b/jdaviz/cli.py
index 8901a0ec2b..34541dd49d 100644
--- a/jdaviz/cli.py
+++ b/jdaviz/cli.py
@@ -18,8 +18,8 @@
default='default',
nargs=1,
show_default=True,
- type=click.Choice(['default', 'cubeviz', 'specviz', 'mosviz'],
- case_sensitive=False),
+ type=click.Choice(['default', 'cubeviz', 'specviz', 'mosviz',
+ 'imviz'], case_sensitive=False),
help="Configuration to use on application startup")
def main(filename, layout='default'):
"""
diff --git a/jdaviz/configs/__init__.py b/jdaviz/configs/__init__.py
index 0870d2aedc..957cbeb45f 100644
--- a/jdaviz/configs/__init__.py
+++ b/jdaviz/configs/__init__.py
@@ -2,3 +2,4 @@
from .specviz import * # noqa
from .default import * # noqa
from .mosviz import * # noqa
+from .imviz import * # noqa
diff --git a/jdaviz/configs/imviz/__init__.py b/jdaviz/configs/imviz/__init__.py
new file mode 100644
index 0000000000..1abedfa2a4
--- /dev/null
+++ b/jdaviz/configs/imviz/__init__.py
@@ -0,0 +1,2 @@
+from .plugins import * # noqa
+from .helper import Imviz # noqa
diff --git a/jdaviz/configs/imviz/helper.py b/jdaviz/configs/imviz/helper.py
new file mode 100644
index 0000000000..18524e62f7
--- /dev/null
+++ b/jdaviz/configs/imviz/helper.py
@@ -0,0 +1,12 @@
+from jdaviz.core.helpers import ConfigHelper
+
+__all__ = ['Imviz']
+
+
+class Imviz(ConfigHelper):
+ """Imviz helper class."""
+
+ _default_configuration = "imviz"
+
+ def show(self):
+ self.app
diff --git a/jdaviz/configs/imviz/imviz.ipynb b/jdaviz/configs/imviz/imviz.ipynb
new file mode 100644
index 0000000000..4c31883657
--- /dev/null
+++ b/jdaviz/configs/imviz/imviz.ipynb
@@ -0,0 +1,38 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from jdaviz import Imviz\n",
+ "\n",
+ "imviz = Imviz()\n",
+ "imviz.load_data('DATA_FILENAME')\n",
+ "imviz.app"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/jdaviz/configs/imviz/imviz.yaml b/jdaviz/configs/imviz/imviz.yaml
new file mode 100644
index 0000000000..15aeee4091
--- /dev/null
+++ b/jdaviz/configs/imviz/imviz.yaml
@@ -0,0 +1,20 @@
+settings:
+ configuration: imviz
+ data:
+ parser: imviz-image-parser
+ visible:
+ menu_bar: false
+ toolbar: false
+ tray: false
+ tab_headers: false
+ context:
+ notebook:
+ max_height: 600px
+viewer_area:
+ - container: col
+ children:
+ - container: row
+ viewers:
+ - name: Image
+ plot: imviz-image-viewer
+ reference: image-viewer
diff --git a/jdaviz/configs/imviz/plugins/__init__.py b/jdaviz/configs/imviz/plugins/__init__.py
new file mode 100644
index 0000000000..641aaeb153
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/__init__.py
@@ -0,0 +1,2 @@
+from .viewers import * # noqa
+from .parsers import * # noqa
diff --git a/jdaviz/configs/imviz/plugins/parsers.py b/jdaviz/configs/imviz/plugins/parsers.py
new file mode 100644
index 0000000000..a4aee0eecf
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/parsers.py
@@ -0,0 +1,28 @@
+import base64
+import pathlib
+import uuid
+
+from jdaviz.core.registries import data_parser_registry
+
+__all__ = ["imviz_image_parser"]
+
+
+@data_parser_registry("imviz-image-parser")
+def imviz_image_parser(app, data, data_label=None, show_in_viewer=True):
+ """Loads an image into Imviz"""
+ # If no data label is assigned, give it a unique identifier
+ if not data_label:
+ data_label = "imviz_data|" + str(
+ base64.b85encode(uuid.uuid4().bytes), "utf-8")
+
+ path = pathlib.Path(data)
+ if path.is_file():
+ # TODO: Support other image formats
+ from astropy.io import fits
+ data = fits.getdata(path)
+ else:
+ raise FileNotFoundError(f"No such file: {path}")
+
+ app.add_data(data, data_label)
+ if show_in_viewer:
+ app.add_data_to_viewer("image-viewer", data_label)
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
new file mode 100644
index 0000000000..ef09ea1d9d
--- /dev/null
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -0,0 +1,61 @@
+from astrowidgets.core import ImageWidget
+from ginga.misc.log import get_logger
+
+from jdaviz.core.registries import viewer_registry
+
+__all__ = ['ImvizImageView']
+
+
+class DummyLayout:
+ def __init__(self):
+ self.height = ''
+ self.width = ''
+
+
+class DummyModelID:
+ def __init__(self):
+ self.model_id = '1234'
+ self.layout = DummyLayout()
+
+
+class ImvizImageWidget(ImageWidget):
+ """Image widget for Imviz."""
+
+ # session is a glue thing
+ def __init__(self, session, *args, **kwargs):
+ # logger needs special handling because using default logger of None
+ # will crash Ginga internals.
+ kwargs['logger'] = get_logger('imviz', log_stderr=True, log_file=None,
+ level=30)
+ super().__init__(*args, **kwargs)
+
+ # More glue things
+
+ def register_to_hub(self, *args, **kwargs):
+ pass
+
+ @property
+ def toolbar_selection_tools(self):
+ class Dummy(DummyModelID):
+ def __init__(self):
+ super().__init__()
+ self.borderless = False
+
+ return Dummy()
+
+ @property
+ def figure_widget(self):
+ return DummyModelID()
+
+ @property
+ def layer_options(self):
+ return DummyModelID()
+
+ @property
+ def viewer_options(self):
+ return DummyModelID()
+
+
+@viewer_registry("imviz-image-viewer", label="Image 2D (Imviz)")
+class ImvizImageView(ImvizImageWidget):
+ default_class = None
diff --git a/jdaviz/configs/imviz/tests/__init__.py b/jdaviz/configs/imviz/tests/__init__.py
new file mode 100644
index 0000000000..6bd08d5bf6
--- /dev/null
+++ b/jdaviz/configs/imviz/tests/__init__.py
@@ -0,0 +1 @@
+"""Tests for Imviz image viewer."""
diff --git a/jdaviz/core/config.py b/jdaviz/core/config.py
index d92484f340..ce45df7808 100644
--- a/jdaviz/core/config.py
+++ b/jdaviz/core/config.py
@@ -39,6 +39,8 @@ def read_configuration(path=None):
path = default_path / "mosviz" / "mosviz.yaml"
elif path == 'specviz2d':
path = default_path / "specviz2d" / "specviz2d.yaml"
+ elif path == 'imviz':
+ path = default_path / "imviz" / "imviz.yaml"
elif not os.path.isfile(path):
raise ValueError("Configuration must be path to a .yaml file.")
diff --git a/notebooks/concepts/Imviz concept notebook.ipynb b/notebooks/concepts/Imviz concept notebook.ipynb
new file mode 100644
index 0000000000..268977614a
--- /dev/null
+++ b/notebooks/concepts/Imviz concept notebook.ipynb
@@ -0,0 +1,69 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import warnings\n",
+ "\n",
+ "with warnings.catch_warnings():\n",
+ " warnings.simplefilter('ignore')\n",
+ "\n",
+ " from jdaviz import Imviz\n",
+ " imviz = Imviz()\n",
+ "\n",
+ "imviz.app"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from astropy.utils.data import download_file\n",
+ "\n",
+ "filename = download_file('http://data.astropy.org/photometry/spitzer_example_image.fits', cache=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "imviz.load_data(filename)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.8.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/notebooks/concepts/concept_programmatic_viewers_from_blank_default.ipynb b/notebooks/concepts/concept_programmatic_viewers_from_blank_default.ipynb
index e20da93081..80f8c82978 100644
--- a/notebooks/concepts/concept_programmatic_viewers_from_blank_default.ipynb
+++ b/notebooks/concepts/concept_programmatic_viewers_from_blank_default.ipynb
@@ -8,7 +8,7 @@
"Start with a blank default application and programmatically add views and data to those views\n",
"\n",
"### Use Case\n",
- "Progammatically load a single FITS file, e.g. for 2d spectroscopic data, into an \"image\" viewer. Or a 1d spectrum into a spectrum viewer. For cases that do not fit into a given pre-made configuration. \n",
+ "Programmatically load a single FITS file, e.g. for 2d spectroscopic data, into an \"image\" viewer. Or a 1d spectrum into a spectrum viewer. For cases that do not fit into a given pre-made configuration. \n",
"\n",
"### MAST Use Case\n",
"MAST auto-generates notebooks that when users run, needs to download the data, create the relevant jdaviz application / viewers, and load the data by default. One click run gets the user back to where they were on the web."
@@ -16,22 +16,9 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- ""
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"from IPython.core.display import display, HTML\n",
"display(HTML(\"\"))"
@@ -39,7 +26,7 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -48,7 +35,7 @@
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -66,26 +53,11 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
"metadata": {
"scrolled": false
},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "b7949170270f421ba9429cab2477b53d",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "Application(components={'g-viewer-tab': '\\n \\n \u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# naively try image-viewer\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'image-viewer'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# also try\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m#app.get_viewer('g-image-viewer')\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36mget_viewer\u001b[0;34m(self, viewer_reference)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mviewer\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0minstance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m \"\"\"\n\u001b[0;32m--> 324\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mviewer_reference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 325\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 326\u001b[0m def get_data_from_viewer(self, viewer_reference, data_label=None,\n",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36m_viewer_by_reference\u001b[0;34m(self, reference)\u001b[0m\n\u001b[1;32m 750\u001b[0m \u001b[0mviewer_item\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_item_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 751\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 752\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_store\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mviewer_item\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'id'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 753\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 754\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_viewer_item_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not subscriptable"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# naively try to get \"image-viewer\". ; throws error\n",
"app.get_viewer('image-viewer')\n",
@@ -211,22 +133,9 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'NoneType' object is not subscriptable",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# let's try to add data anyways\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_data_to_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'image-viewer'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'SCI'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36madd_data_to_viewer\u001b[0;34m(self, viewer_reference, data_path, clear_other_data, ext)\u001b[0m\n\u001b[1;32m 618\u001b[0m \u001b[0mdata_id\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data_id_from_label\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata_label\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 620\u001b[0;31m \u001b[0mdata_ids\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mviewer_item\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'selected_data_items'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m\\\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 621\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mclear_other_data\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not subscriptable"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# let's try to add data anyways - throws same error\n",
"app.add_data_to_viewer('image-viewer', data, ext='SCI')"
@@ -241,20 +150,9 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 19,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# look in the viewer registry\n",
"from jdaviz.core.registries import tool_registry, viewer_registry\n",
@@ -263,37 +161,9 @@
},
{
"cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'cubeviz-image-viewer': {'label': 'Image 2D (CubeViz)',\n",
- " 'cls': jdaviz.configs.cubeviz.plugins.viewers.CubeVizImageView},\n",
- " 'g-profile-viewer': {'label': 'Profile 1D',\n",
- " 'cls': glue_jupyter.bqplot.profile.viewer.BqplotProfileView},\n",
- " 'g-image-viewer': {'label': 'Image 2D',\n",
- " 'cls': glue_jupyter.bqplot.image.viewer.BqplotImageView},\n",
- " 'g-table-viewer': {'label': 'Table',\n",
- " 'cls': glue_jupyter.table.viewer.TableViewer},\n",
- " 'specviz-profile-viewer': {'label': 'Profile 1D (Specviz)',\n",
- " 'cls': jdaviz.configs.specviz.plugins.viewers.SpecvizProfileView},\n",
- " 'mosviz-profile-viewer': {'label': 'Profile 1D (MOSViz)',\n",
- " 'cls': jdaviz.configs.mosviz.plugins.viewers.MOSVizProfileView},\n",
- " 'mosviz-image-viewer': {'label': 'Image 2D (MOSViz)',\n",
- " 'cls': jdaviz.configs.mosviz.plugins.viewers.MOSVizImageView},\n",
- " 'mosviz-profile-2d-viewer': {'label': 'Spectrum 2D (MOSViz)',\n",
- " 'cls': jdaviz.configs.mosviz.plugins.viewers.MOSVizProfile2DView},\n",
- " 'mosviz-table-viewer': {'label': 'Table (MOSViz)',\n",
- " 'cls': jdaviz.configs.mosviz.plugins.viewers.MOSVizTableViewer}}"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
"# I can find all viewers in the registry. But these dict keys are not reference names. \n",
"viewer_registry.members"
@@ -301,23 +171,9 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'NoneType' object is not subscriptable",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# oh I see my Image 2d == \"g-image-viewer\". Let me try that.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'g-image-viewer'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36mget_viewer\u001b[0;34m(self, viewer_reference)\u001b[0m\n\u001b[1;32m 322\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mviewer\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0minstance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 323\u001b[0m \"\"\"\n\u001b[0;32m--> 324\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mviewer_reference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 325\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 326\u001b[0m def get_data_from_viewer(self, viewer_reference, data_label=None,\n",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36m_viewer_by_reference\u001b[0;34m(self, reference)\u001b[0m\n\u001b[1;32m 750\u001b[0m \u001b[0mviewer_item\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_item_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 751\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 752\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_viewer_store\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mviewer_item\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'id'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 753\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 754\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_viewer_item_by_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not subscriptable"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# oh I see my \"Image 2D\" == \"g-image-viewer\". That must be the reference name. Let me try that, to get the viewer.\n",
"app.get_viewer('g-image-viewer')"
@@ -332,20 +188,9 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'6501402f-bb03-4fd5-b8da-1b4241daf66b': }"
- ]
- },
- "execution_count": 22,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# look up the viewer store. I see my viewer with a viewer id. \n",
"app._viewer_store"
@@ -353,20 +198,9 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 23,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# examine the application stack of items\n",
"app.state.stack_items"
@@ -374,28 +208,9 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "item dict_keys(['id', 'container', 'children', 'viewers'])\n",
- "viewer dict_keys(['id', 'name', 'widget', 'tools', 'layer_options', 'viewer_options', 'selected_data_items', 'collapse', 'reference', 'tab'])\n",
- "id 6501402f-bb03-4fd5-b8da-1b4241daf66b\n",
- "name Unnamed Viewer\n",
- "widget IPY_MODEL_2000302c0e344576b421f3f18cf8ba6e\n",
- "tools IPY_MODEL_f4c490d6cc2e4b31893e6c2b4c4f5062\n",
- "layer_options IPY_MODEL_75dae667d8454464a286b39ff444a678\n",
- "viewer_options IPY_MODEL_4772c7d7dddd428a9533f6877ac18183\n",
- "selected_data_items \n",
- "collapse True\n",
- "reference None\n",
- "tab 0\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# loop over all the items in the application stack and print the data\n",
"for i in app.state.stack_items:\n",
@@ -408,20 +223,9 @@
},
{
"cell_type": "code",
- "execution_count": 43,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# now I have the viewer, I think. The repr here should be improved to more obvious.\n",
"viewer"
@@ -429,7 +233,7 @@
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -439,22 +243,9 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'NoneType' object is not subscriptable",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# try to add data by id\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_data_to_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mid\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlabel\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36madd_data_to_viewer\u001b[0;34m(self, viewer_reference, data_path, clear_other_data, ext)\u001b[0m\n\u001b[1;32m 618\u001b[0m \u001b[0mdata_id\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data_id_from_label\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata_label\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 620\u001b[0;31m \u001b[0mdata_ids\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mviewer_item\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'selected_data_items'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m\\\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 621\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mclear_other_data\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not subscriptable"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# try to add data by id. Still same error as above.\n",
"app.add_data_to_viewer(id, label)"
@@ -462,20 +253,9 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 27,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# I notice in the stack that no reference name is indicated. Let's add one.\n",
"view = app._viewer_item_by_id(id)\n",
@@ -485,7 +265,7 @@
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -495,22 +275,9 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "AttributeError",
- "evalue": "'BqplotImageView' object has no attribute 'default_class'",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# can I access the data back out\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_data_from_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'image-viewer'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36mget_data_from_viewer\u001b[0;34m(self, viewer_reference, data_label, cls, include_subsets)\u001b[0m\n\u001b[1;32m 364\u001b[0m \"\"\"\n\u001b[1;32m 365\u001b[0m \u001b[0mviewer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mviewer_reference\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 366\u001b[0;31m \u001b[0mcls\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mviewer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefault_class\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcls\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'default'\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 367\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 368\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcls\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misclass\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mAttributeError\u001b[0m: 'BqplotImageView' object has no attribute 'default_class'"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# can I access the data back out? \n",
"app.get_data_from_viewer('image-viewer')"
@@ -526,24 +293,9 @@
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "114e532d0e944ecc8845b0c5adeb06e9",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "Application(components={'g-viewer-tab': '\\n \\n }"
- ]
- },
- "execution_count": 34,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"# look for the viewer in the store\n",
"app._viewer_store"
@@ -663,22 +367,9 @@
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'NoneType' object is not subscriptable",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mapp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_data_to_viewer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'image-viewer'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mext\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'SCI'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/Work/git/havok2063/jdaviz/jdaviz/app.py\u001b[0m in \u001b[0;36madd_data_to_viewer\u001b[0;34m(self, viewer_reference, data_path, clear_other_data, ext)\u001b[0m\n\u001b[1;32m 618\u001b[0m \u001b[0mdata_id\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_data_id_from_label\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata_label\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 619\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 620\u001b[0;31m \u001b[0mdata_ids\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mviewer_item\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'selected_data_items'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m\\\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 621\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mclear_other_data\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 'NoneType' object is not subscriptable"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# attempt to add the data with naive reference name\n",
"app.add_data_to_viewer('image-viewer', data, ext='SCI') "
@@ -686,25 +377,9 @@
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "id c3906bad-0c1f-4e80-8be2-83984a01d3ed\n",
- "name Unnamed Viewer\n",
- "widget IPY_MODEL_288b6451c3784849a16055ef99d44e41\n",
- "tools IPY_MODEL_b01dcb73142d4970a285fe0f48a3d39d\n",
- "layer_options IPY_MODEL_a4ee8df437514ba784c3342839b0fa63\n",
- "viewer_options IPY_MODEL_19604f2888394ef195438de35ea9134e\n",
- "selected_data_items \n",
- "collapse True\n",
- "reference None\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# grab the viewer information\n",
"id = next(iter(app._viewer_store))\n",
@@ -715,7 +390,7 @@
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -725,7 +400,7 @@
},
{
"cell_type": "code",
- "execution_count": 38,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -743,31 +418,9 @@
},
{
"cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'settings': {'visible': {'menu_bar': False,\n",
- " 'toolbar': True,\n",
- " 'tray': True,\n",
- " 'tab_headers': True},\n",
- " 'context': {'notebook': {'max_height': '600px'}}},\n",
- " 'toolbar': ['g-data-tools', 'g-viewer-creator', 'g-subset-tools'],\n",
- " 'tray': ['g-gaussian-smooth'],\n",
- " 'viewer_area': [{'container': 'col',\n",
- " 'children': [{'container': 'row',\n",
- " 'viewers': [{'name': 'Image',\n",
- " 'plot': 'g-image-viewer',\n",
- " 'reference': 'image-viewer'}]}]}]}"
- ]
- },
- "execution_count": 39,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
"from jdaviz.core.helpers import ConfigHelper\n",
"from jdaviz.core.config import get_configuration\n",
@@ -792,55 +445,31 @@
},
{
"cell_type": "code",
- "execution_count": 40,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "21d269258cd84446ac013628373e76e1",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "Application(components={'g-viewer-tab': '\\n \\n =0.5
asteval
+ astrowidgets
# vispy is an indirect dependency, but older vispy's don't play nice with jdaviz install
vispy>=0.6.5
@@ -60,6 +61,7 @@ jdaviz_plugins =
cubeviz = jdaviz.configs.cubeviz
specviz = jdaviz.configs.specviz
mosviz = jdaviz.configs.mosviz
+ imviz = jdaviz.configs.imviz
[tool:pytest]
testpaths = "jdaviz" "docs"
From b713f80c856368be183a8653099c6f4cd142635b Mon Sep 17 00:00:00 2001
From: Ricky O'Steen
Date: Mon, 25 Jan 2021 15:11:43 -0500
Subject: [PATCH 2/6] Load as CCDData for Glue compatibility
---
jdaviz/app.py | 4 ++++
jdaviz/configs/imviz/plugins/parsers.py | 5 +++--
jdaviz/configs/imviz/plugins/viewers.py | 6 ++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/jdaviz/app.py b/jdaviz/app.py
index ee21c7573e..d5a6c99d7b 100644
--- a/jdaviz/app.py
+++ b/jdaviz/app.py
@@ -912,6 +912,10 @@ def _update_selected_data_items(self, viewer_id, selected_items):
sender=self)
self.hub.broadcast(add_data_message)
+ # Temporary workaround since ImageWidget doesn't have a state attribute
+ if not hasattr(viewer, "state"):
+ return
+
# Remove any deselected data objects from viewer
viewer_data = [layer_state.layer
for layer_state in viewer.state.layers
diff --git a/jdaviz/configs/imviz/plugins/parsers.py b/jdaviz/configs/imviz/plugins/parsers.py
index a4aee0eecf..5548ed8bb8 100644
--- a/jdaviz/configs/imviz/plugins/parsers.py
+++ b/jdaviz/configs/imviz/plugins/parsers.py
@@ -2,6 +2,8 @@
import pathlib
import uuid
+from astropy.nddata import CCDData
+
from jdaviz.core.registries import data_parser_registry
__all__ = ["imviz_image_parser"]
@@ -18,8 +20,7 @@ def imviz_image_parser(app, data, data_label=None, show_in_viewer=True):
path = pathlib.Path(data)
if path.is_file():
# TODO: Support other image formats
- from astropy.io import fits
- data = fits.getdata(path)
+ data = CCDData.read(path)
else:
raise FileNotFoundError(f"No such file: {path}")
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
index ef09ea1d9d..2b5c6eca9e 100644
--- a/jdaviz/configs/imviz/plugins/viewers.py
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -1,5 +1,6 @@
from astrowidgets.core import ImageWidget
from ginga.misc.log import get_logger
+from glue.core import Data
from jdaviz.core.registries import viewer_registry
@@ -34,6 +35,11 @@ def __init__(self, session, *args, **kwargs):
def register_to_hub(self, *args, **kwargs):
pass
+ def add_data(self, data):
+ if type(data) == Data:
+ data = data.get_object()
+ self.load_nddata(data)
+
@property
def toolbar_selection_tools(self):
class Dummy(DummyModelID):
From bc339fad373a551acfd38b99e78788a1817f5c40 Mon Sep 17 00:00:00 2001
From: Pey Lian Lim <2090236+pllim@users.noreply.github.com>
Date: Thu, 28 Jan 2021 14:05:24 -0500
Subject: [PATCH 3/6] WIP: Some clean up but no work
---
jdaviz/app.py | 4 ----
jdaviz/configs/imviz/imviz.yaml | 2 +-
jdaviz/configs/imviz/plugins/parsers.py | 2 +-
jdaviz/configs/imviz/plugins/viewers.py | 21 +++++++++++++++++----
4 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/jdaviz/app.py b/jdaviz/app.py
index d5a6c99d7b..ee21c7573e 100644
--- a/jdaviz/app.py
+++ b/jdaviz/app.py
@@ -912,10 +912,6 @@ def _update_selected_data_items(self, viewer_id, selected_items):
sender=self)
self.hub.broadcast(add_data_message)
- # Temporary workaround since ImageWidget doesn't have a state attribute
- if not hasattr(viewer, "state"):
- return
-
# Remove any deselected data objects from viewer
viewer_data = [layer_state.layer
for layer_state in viewer.state.layers
diff --git a/jdaviz/configs/imviz/imviz.yaml b/jdaviz/configs/imviz/imviz.yaml
index 15aeee4091..d0033d6939 100644
--- a/jdaviz/configs/imviz/imviz.yaml
+++ b/jdaviz/configs/imviz/imviz.yaml
@@ -17,4 +17,4 @@ viewer_area:
viewers:
- name: Image
plot: imviz-image-viewer
- reference: image-viewer
+ reference: imviz-image-viewer
diff --git a/jdaviz/configs/imviz/plugins/parsers.py b/jdaviz/configs/imviz/plugins/parsers.py
index 5548ed8bb8..e429bf95a2 100644
--- a/jdaviz/configs/imviz/plugins/parsers.py
+++ b/jdaviz/configs/imviz/plugins/parsers.py
@@ -26,4 +26,4 @@ def imviz_image_parser(app, data, data_label=None, show_in_viewer=True):
app.add_data(data, data_label)
if show_in_viewer:
- app.add_data_to_viewer("image-viewer", data_label)
+ app.add_data_to_viewer("imviz-image-viewer", data_label, clear_other_data=True)
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
index 2b5c6eca9e..1c8f2a33f0 100644
--- a/jdaviz/configs/imviz/plugins/viewers.py
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -19,9 +19,18 @@ def __init__(self):
self.layout = DummyLayout()
-class ImvizImageWidget(ImageWidget):
+class DummyState:
+ def __init__(self):
+ self.layers = []
+
+
+@viewer_registry("imviz-image-viewer", label="Image 2D (Imviz)")
+class ImvizImageView(ImageWidget):
"""Image widget for Imviz."""
+ default_class = None
+ state = DummyState()
+
# session is a glue thing
def __init__(self, session, *args, **kwargs):
# logger needs special handling because using default logger of None
@@ -61,7 +70,11 @@ def layer_options(self):
def viewer_options(self):
return DummyModelID()
+ def set_plot_axes(self, *args, **kwargs):
+ pass
-@viewer_registry("imviz-image-viewer", label="Image 2D (Imviz)")
-class ImvizImageView(ImvizImageWidget):
- default_class = None
+ def data(self, cls=None):
+ return [layer_state.layer
+ for layer_state in self.state.layers
+ if hasattr(layer_state, 'layer') and
+ isinstance(layer_state.layer, BaseData)]
From 6d8269b11df56edc1935dea04eb86870e2b7bdf2 Mon Sep 17 00:00:00 2001
From: Mario Buikhuizen
Date: Tue, 16 Feb 2021 18:01:52 +0100
Subject: [PATCH 4/6] fix: display astrowidget in imviz
figure_widget, layer_options, viewer_options need to return real
ipywidgets.
---
jdaviz/configs/imviz/plugins/viewers.py | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
index 1c8f2a33f0..aa992a1d45 100644
--- a/jdaviz/configs/imviz/plugins/viewers.py
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -1,22 +1,15 @@
from astrowidgets.core import ImageWidget
from ginga.misc.log import get_logger
from glue.core import Data
+import ipywidgets as widgets
from jdaviz.core.registries import viewer_registry
__all__ = ['ImvizImageView']
-class DummyLayout:
- def __init__(self):
- self.height = ''
- self.width = ''
-
-
-class DummyModelID:
- def __init__(self):
- self.model_id = '1234'
- self.layout = DummyLayout()
+class DummyModelID(widgets.Label):
+ pass
class DummyState:
@@ -60,7 +53,7 @@ def __init__(self):
@property
def figure_widget(self):
- return DummyModelID()
+ return self
@property
def layer_options(self):
From e1e6bdfddff032cfbc48cb4bec4a2c8018afa444 Mon Sep 17 00:00:00 2001
From: Pey Lian Lim <2090236+pllim@users.noreply.github.com>
Date: Wed, 24 Feb 2021 14:59:17 -0500
Subject: [PATCH 5/6] WIP: Glupyter astrowidgets jdaviz turducken
in a working state but not feature-complete.
---
docs/imviz/index.rst | 6 +-
jdaviz/configs/imviz/plugins/parsers.py | 6 +-
jdaviz/configs/imviz/plugins/viewers.py | 61 +++++++++----------
.../concepts/Imviz concept notebook.ipynb | 61 +++++++++++++++++++
setup.cfg | 1 -
5 files changed, 94 insertions(+), 41 deletions(-)
diff --git a/docs/imviz/index.rst b/docs/imviz/index.rst
index 7888565620..3dae4002a3 100644
--- a/docs/imviz/index.rst
+++ b/docs/imviz/index.rst
@@ -11,11 +11,11 @@ images. Like the rest of `jdaviz`, it is written in the Python programming
language, and therefore can be run anywhere Python is supported
(see :doc:`../installation`). Imviz is built on top of the
`astrowidgets `_ using
-`Ginga `_ backend, providing a visual,
+`Glupyter `_ backend, providing a visual,
interactive interface to the analysis capabilities in that library.
-Imviz allows images to be easily displayed and examined. It supports WCS,
-GWCS, ASDF, and so on. (TODO: Add content.)
+Imviz allows images to be easily displayed and examined. It supports WCS
+and so on. (TODO: Add content.)
Using Imviz
diff --git a/jdaviz/configs/imviz/plugins/parsers.py b/jdaviz/configs/imviz/plugins/parsers.py
index e429bf95a2..e260835698 100644
--- a/jdaviz/configs/imviz/plugins/parsers.py
+++ b/jdaviz/configs/imviz/plugins/parsers.py
@@ -1,6 +1,4 @@
-import base64
import pathlib
-import uuid
from astropy.nddata import CCDData
@@ -14,8 +12,8 @@ def imviz_image_parser(app, data, data_label=None, show_in_viewer=True):
"""Loads an image into Imviz"""
# If no data label is assigned, give it a unique identifier
if not data_label:
- data_label = "imviz_data|" + str(
- base64.b85encode(uuid.uuid4().bytes), "utf-8")
+ from astrowidgets.glupyter import _gen_random_label
+ data_label = _gen_random_label(prefix="imviz_data|")
path = pathlib.Path(data)
if path.is_file():
diff --git a/jdaviz/configs/imviz/plugins/viewers.py b/jdaviz/configs/imviz/plugins/viewers.py
index aa992a1d45..7e3de5b368 100644
--- a/jdaviz/configs/imviz/plugins/viewers.py
+++ b/jdaviz/configs/imviz/plugins/viewers.py
@@ -1,55 +1,39 @@
-from astrowidgets.core import ImageWidget
-from ginga.misc.log import get_logger
-from glue.core import Data
-import ipywidgets as widgets
+from astrowidgets.glupyter import ImageWidget
+from glue.core import BaseData
from jdaviz.core.registries import viewer_registry
__all__ = ['ImvizImageView']
-class DummyModelID(widgets.Label):
- pass
-
-
-class DummyState:
- def __init__(self):
- self.layers = []
-
-
@viewer_registry("imviz-image-viewer", label="Image 2D (Imviz)")
class ImvizImageView(ImageWidget):
"""Image widget for Imviz."""
default_class = None
- state = DummyState()
# session is a glue thing
def __init__(self, session, *args, **kwargs):
- # logger needs special handling because using default logger of None
- # will crash Ginga internals.
- kwargs['logger'] = get_logger('imviz', log_stderr=True, log_file=None,
- level=30)
+
super().__init__(*args, **kwargs)
+ self._viewer._session = session
# More glue things
def register_to_hub(self, *args, **kwargs):
- pass
+ self._viewer.register_to_hub(*args, **kwargs)
def add_data(self, data):
- if type(data) == Data:
- data = data.get_object()
- self.load_nddata(data)
+ self._viewer.add_data(data)
+ self._link_image_to_cb()
+
+ def remove_data(self, data):
+ self._viewer.remove_data(data)
+ self.viewer.interaction = None
@property
def toolbar_selection_tools(self):
- class Dummy(DummyModelID):
- def __init__(self):
- super().__init__()
- self.borderless = False
-
- return Dummy()
+ return self._viewer.toolbar_selection_tools
@property
def figure_widget(self):
@@ -57,17 +41,28 @@ def figure_widget(self):
@property
def layer_options(self):
- return DummyModelID()
+ return self._viewer.layer_options
@property
def viewer_options(self):
- return DummyModelID()
+ return self._viewer.viewer_options
+
+ @property
+ def state(self):
+ return self._viewer.state
+
+ def set_plot_axes(self):
+ self.viewer.axes[1].tick_format = None
+ self.viewer.axes[0].tick_format = None
+
+ self.viewer.axes[1].label = "y: pixels"
+ self.viewer.axes[0].label = "x: pixels"
- def set_plot_axes(self, *args, **kwargs):
- pass
+ # Make it so y axis label is not covering tick numbers.
+ self.viewer.axes[1].label_offset = "-50"
def data(self, cls=None):
return [layer_state.layer
- for layer_state in self.state.layers
+ for layer_state in self._viewer.state.layers
if hasattr(layer_state, 'layer') and
isinstance(layer_state.layer, BaseData)]
diff --git a/notebooks/concepts/Imviz concept notebook.ipynb b/notebooks/concepts/Imviz concept notebook.ipynb
index 268977614a..a5f48ae05e 100644
--- a/notebooks/concepts/Imviz concept notebook.ipynb
+++ b/notebooks/concepts/Imviz concept notebook.ipynb
@@ -1,5 +1,23 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Imviz\n",
+ "\n",
+ "Special software requirements:\n",
+ "\n",
+ "* Dev version of `glue-jupyter`\n",
+ "* Latest `bqplot-image-gl` might work though I used dev version too\n",
+ "* `astrowidgets` from https://github.com/astropy/astrowidgets/pull/131\n",
+ "\n",
+ "Known issues:\n",
+ "\n",
+ "* Mouse interaction for cursor info panel breaks when you use scroll/pan GUI from the toolbar.\n",
+ "* To regain mouse interaction, you need to go into Data layer to uncheck/check the data name, which resets everything."
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -37,6 +55,49 @@
"imviz.load_data(filename)"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This exposes the underlying `astrowidgets` API."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w = imviz.app.get_viewer('imviz-image-viewer')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w.set_colormap('viridis')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w.cuts = (0, 100)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "w.stretch = 'arcsinh'"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
diff --git a/setup.cfg b/setup.cfg
index 922880de73..c0ced3573f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -34,7 +34,6 @@ install_requires =
click
spectral-cube>=0.5
asteval
- astrowidgets
# vispy is an indirect dependency, but older vispy's don't play nice with jdaviz install
vispy>=0.6.5
From 0415f1320fb6e81535a55f8179d3e582e76f48fc Mon Sep 17 00:00:00 2001
From: Pey Lian Lim <2090236+pllim@users.noreply.github.com>
Date: Wed, 24 Feb 2021 17:13:37 -0500
Subject: [PATCH 6/6] Add new dependency
---
setup.cfg | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/setup.cfg b/setup.cfg
index c0ced3573f..8a102e98e0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -34,6 +34,7 @@ install_requires =
click
spectral-cube>=0.5
asteval
+ astrowidgets
# vispy is an indirect dependency, but older vispy's don't play nice with jdaviz install
vispy>=0.6.5
@@ -75,7 +76,7 @@ max-line-length = 100
# E126: continuation line over-indented for hanging indent
# E226: missing whitespace around arithmetic operator
# E402: Module level import not at top of file
-# W503: line break before binary operator
+# W503: line break before binary operator
# W504: line break after binary operator
ignore = E123,E126,E226,E402,W503,W504