Jdaviz#

jdaviz is a package of astronomical data analysis visualization tools based on the Jupyter platform. These GUI-based tools link data visualization and interactive analysis. They are designed to work within a Jupyter notebook cell, as a standalone desktop application, or as embedded windows within a website – all with nearly identical user interfaces.

jdaviz applications currently include tools for interactive visualization of spectroscopic and imaging data. Imviz is a tool for visualization and quick-look analysis for 2D astronomical images. Specviz is a tool for visualization and quick-look analysis of 1D astronomical spectra. Cubeviz provides a view of spectroscopic data cubes (like those to be produced by JWST MIRI), along with 1D spectra extracted from the cube. 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.

Warning

As of jdaviz version 3.10, please use Python 3.10 or greater to get the latest bug fixes and feature additions for jdaviz.

Note

jdaviz is one tool that is part of STScI’s larger Data Analysis Tools Ecosystem.

Note

The offline version of this documentation can be downloaded from Jdaviz zipped HTML downloads page.

Note

Recordings and instructional notebooks from live Jdaviz tutorials can be found at the JWebbinar website under the “Materials and Videos” expandable section. Scroll down to the bottom of that section to find materials from the most recent session (JWebbinar 24, March 2023).

Using Jdaviz#

User Guide#

Installation#

Note

jdaviz is undergoing constant development. We encourage users to always update to the latest version. In general, it is good practice to install the development version following the instructions below as full released versions may lag behind.

User Installation#
Windows-Specific Dependencies#

Some of our dependencies require C++ compilers to install properly. These are usually included with macOS and most Linux distributions, but are not included by default in Windows. Microsoft provides these tools as part of their Build Tools for Visual Studio, which can be found under “Tools for Visual Studio” towards the bottom of the page.

Create Your Local Environment#

Some of Jdaviz’s dependencies require non-Python packages to work (particularly the front-end stack that is part of the Jupyter ecosystem). We recommend using Miniconda to easily manage a compatible Python environment for jdaviz; it should work with most modern shells, except CSH/TCSH.

You may want to consider installing jdaviz in a new virtual or conda environment to avoid version conflicts with other packages you may have installed, for example:

conda create -n jdaviz-env python=3.11
conda activate jdaviz-env
Pip Install#

As noted above, we typically recommend installing the latest development version:

pip install git+https://github.com/spacetelescope/jdaviz --upgrade

A normal install will also work by installing the latest release version:

pip install jdaviz --upgrade
Common Issues#

If you encounter problems while following these installation instructions, please consult known installation issues.

Note that jdaviz requires Python 3.10 or newer. If your pip corresponds to an older version of Python, it will raise an error that it cannot find a valid package.

Users occasionally encounter problems running the pure pip install above. For those using conda, some problems may be resolved by pulling the following from conda instead of pip:

conda install bottleneck
conda install -c conda-forge notebook
conda install -c conda-forge jupyterlab
conda install -c conda-forge voila

You might also want to enable the ipywidgets notebook extension, as follows:

jupyter nbextension enable --py widgetsnbextension
Developer Installation#

If you wish to contribute to Jdaviz, please fork the project to your own GitHub account. The following instructions assume your have forked the project and have connected your GitHub to SSH and username is your GitHub username. This is a one-setup setup:

git clone git@github.com:username/jdaviz.git
cd jdaviz
git remote add upstream git@github.com:spacetelescope/jdaviz.git
git fetch upstream main
git fetch upstream --tags

To work on a new feature or bug-fix, it is recommended that you build upon the latest dev code in a new branch (e.g., my-new-feature). You also need the up-to-date tags for proper software versioning:

git checkout -b my-new-feature
git fetch upstream --tags
git fetch upstream main
git rebase upstream/main

For the rest of contributing workflow, it is very similar to how to make a code contribution to astropy, including setting up virtual environments, git basics, and more.

An exception is the change log; if your patch requires a change log, see CHANGES.rst for examples.

One option is to enable the hot reloading of Vue.js templates, install watchdog:

pip install watchdog

After installing watchdog, to use it, add the following to the top of a notebook:

from jdaviz import enable_hot_reloading
enable_hot_reloading()

Another option is to enable magic commands for Python autoreloading, to use it, add the following to the top of a notebook:

%load_ext autoreload
%autoreload 2

To install jdaviz for development or from source in an editable mode (i.e., changes to the locally checked out code would reflect in runtime after you restarted the Python kernel):

pip install -e .

Note: It is recommended to install the package without -e flag initially to ensure that the template files are copied correctly.

Quickstart#

Once installed, jdaviz can be run either in a Jupyter notebook or as a standalone web application. Detailed workflows are given within the documentation, but some quick-start tips are given below.

In a Jupyter Notebook#

The power of Jdaviz is that it can integrated into your Jupyter notebook workflow:

from jdaviz import Imviz

imviz = Imviz()
imviz.show()
imviz.load_data('filename.fits', data_label='MyData')

Jdaviz also provides a directory of sample notebooks to test the application, located in the notebooks sub-directory of the Git repository. ImvizExample.ipynb is provided as an example that loads two 47 Tucanae exposures taken with HST/ACS WFC detectors with the Imviz configuration. To run the provided example, start the Jupyter kernel with the notebook path:

jupyter notebook /path/to/jdaviz/notebooks/ImvizExample.ipynb

Alternately, if you are using Jupyter Lab:

jupyter lab /path/to/jdaviz/notebooks/ImvizExample.ipynb
As a Standalone Application#

jdaviz provides a command-line tool to start the standalone desktop application in a browser. To see the syntax and usage, from a terminal, type:

jdaviz --help

Typical usage to load a file into a desired configuration:

jdaviz --layout=[imviz|specviz|cubeviz|mosviz|specviz2d] /path/to/data/file

For example, to load a FITS image into Imviz:

jdaviz --layout=imviz my_image.fits

To learn more about the various jdaviz application configurations and loading data, see the Imviz, Specviz, Cubeviz, Mosviz, or Specviz2D tools.

The command jdaviz without any additional input will run a launcher. After launching jdaviz, the user can select a file from the file picker. The launcher will identify the best configuration according to the file type. Alternatively, the user can select the desired configuration by clicking one of the buttons without specifying a file. A blank configuration will open and the IMPORT button will be available to select a file from the file picker.

Jdaviz Launcher

imviz_logo Imviz#

Introductory video tour of the Imviz configuration and its features

Imviz is a tool for visualization and analysis of 2D astronomical images. It incorporates visualization tools with analysis capabilities, such as Astropy regions and photutils packages. Users can interact with their data from within the tool. Imviz also provides programmatic access to its viewers using Astrowidgets API; see AstrowidgetsImageViewerMixin for available functionality. Data can be both imported into and exported out of the tool so users can continue their desired workflow within the notebook. This documentation provides details on the various capabilities, demo videos, and example notebooks.

Using Imviz

Importing Data into Imviz#

Imviz can load data in the form of a filename (FITS, JPEG, or PNG), an NDData object, or a NumPy array if the data is 2D. See jdaviz.configs.imviz.helper.Imviz.load_data() for more information.

Note

Loading too many datasets will cause performance problems due to the number of links necessary; see The linking framework for more information.

Importing data through the Command Line#

When running the Imviz application via the command line, you may provide a path to a compatible file, which will be loaded into the app on initialization. Multiple data files may be provided:

jdaviz --layout=imviz /my/image/data1.fits /my/image/data2.fits
Importing data through the GUI#

You can load your data into the Imviz application by clicking the Import Data button at the top left of the application’s user interface. This opens a dialogue where the user can select a file that can be parsed as a NDData, HDUList, or ImageHDU in the text field.

After clicking Import, the data file will be parsed and loaded into the application. A notification will appear to let users know if the data import was successful. Afterward, the new data set can be found in the Data tab of each viewer’s options menu as described in Selecting a Data Set.

Once data is loaded, you may use the Import Data button again to load regions from a .reg file; also see Importing regions via the API.

Importing data via the API#

Alternatively, users who work in a coding environment like a Jupyter notebook can access the Imviz helper class API. Using this API, users can load data into the application through code with the load_data() method, which takes as input either the name of a local file or an NDData, HDUList, or ImageHDU object.

FITS Files#

The example below loads the first science extension of the given FITS file into Imviz:

from jdaviz import Imviz
imviz = Imviz()
imviz.load_data("/path/to/data/image.fits")
imviz.show()
Creating Your Own Array#

You can create your own array to load into Imviz:

import numpy as np
from jdaviz import Imviz

arr = np.arange(100).reshape((10, 10))
imviz = Imviz()
imviz.load_data(arr, data_label='my_array')
imviz.show()
JWST datamodels#

If you have a stdatamodels.datamodels object, you can load it into Imviz as follows:

import numpy as np
from astropy.nddata import NDData
from jdaviz import Imviz

# mydatamodel is a jwst.datamodels object
ndd = NDData(np.array(mydatamodel.data), wcs=mydatamodel.get_fits_wcs())
imviz = Imviz()
imviz.load_data(ndd, data_label='my_data_model')
imviz.show()
Roman datamodels#

You can also load Nancy Grace Roman Space Telescope (hereafter, Roman) data products, which are provided as ASDF files. If an ASDF file has a roman attribute, Jdaviz will open it with roman-datamodels. You must run pip install roman-datamodels separately as it is not automatically installed by Jdaviz.

from jdaviz import Imviz

imviz = Imviz()
imviz.load_data("WFI01_cal.asdf")
imviz.show()
Batch Loading Multiple Images#

To save on performance while loading multiple images into Imviz, you can optionally use batch_load() to parse all of the data first (within a for loop or multiple calls to load_data, for example), and defer the linking and loading of the new data entries into the viewer until after the parsing is complete:

from jdaviz import Imviz
imviz = Imviz()
with imviz.batch_load():
    for filepath in filepaths:
        imviz.load_data(filepath)
imviz.show()
Importing catalogs via the API#

If you have a catalog file supported by astropy.table.Table, you can load the catalog into Imviz and add markers to Imviz viewers to show positions from the catalog. These markers are different than Imviz spatial regions as they are only meant to mark catalog positions. Loading markers can be done with the following commands:

viewer = imviz.default_viewer
viewer.marker = {'color': 'green', 'alpha': 0.8, 'markersize': 10, 'fill': False}
my_markers = Table.read('my_catalog.ecsv')
coord_i2d = Table({'coord': [SkyCoord(ra=my_catalog['sky_centroid'].ra.degree,
                                      dec=my_catalog['sky_centroid'].dec.degree,
                                      unit="deg")]})
viewer.add_markers(coord_i2d, use_skycoord=True, marker_name='my_markers')

If you have a large catalog, you might want to filter your table to the marks of interest before adding them to Imviz, in order to avoid performance issues associated with adding large numbers of markers. For instance, if your image has FITS WCS, you could use astropy.wcs.WCS.footprint_contains if you only want the marks within a footprint. Alternately, you could filter by relevant columns in your catalogs, such as brightness, distance, etc.

And to remove those markers:

viewer.remove_markers(marker_name='my_markers')
Importing regions via the API#

If you have a region file supported by Reading/Writing Region Files, you can load the regions into Imviz as follows:

imviz.load_regions_from_file("/path/to/data/myregions.reg")

Unsupported regions will be skipped and trigger a warning. Those that failed to load, if any, can be returned as a list of tuples of the form (region, reason):

bad_regions = imviz.load_regions_from_file("/path/to/data/myregions.reg", return_bad_regions=True)

You could also define Region Shapes programmatically and load them; e.g.:

from regions import CirclePixelRegion, PixCoord
aper_1 = CirclePixelRegion(center=PixCoord(x=42, y=43), radius=4.2)
aper_2 = CirclePixelRegion(center=PixCoord(x=10, y=20), radius=3)
imviz.load_regions([aper_1, aper_2])

For more details on the API, please see load_regions_from_file() and load_regions() methods in Imviz.

Displaying Images#

Imviz uses image viewers to visualize data from supported formats. Much of the functionality is available both from the application GUI and from the Jupyter notebook using API calls. The Toolbar below gives you several image display options. Right-click will open a dropdown with access to different options for each button.

Imviz Toolbar
Selecting a Data Set#

Data can be selected and de-selected in each viewer’s data menu, opened by clicking the data select icon button in the top left of the viewer. Here, you can click a checkbox to the left of the listed data to make the data visible (checked) or invisible (unchecked). The datasets available in each viewer are filtered to include only compatible data, so you may not see all loaded data in the menu for every viewer. For example, 1D spectra will not be available in the image viewers.

In addition to selecting and de-selecting data to toggle its visibility in the viewer, you can also unload the data from the viewer completely by clicking the X to the right of the data label. Any data that still exists in Imviz but has been unloaded from the viewer is listed in a separate section that is hidden by default but can can be expanded by clicking on the section header:

_images/imviz_removed_data.png

This section can be hidden by clicking the section header again. Unloaded data will be available to re-load into the viewer (by clicking the + icon) or remove permanently from the app (by clicking the trashcan icon).

Warning

Deleting the first image that was loaded into Imviz may be slow, as deleting this image requires Imviz to re-link any remaining data together and redefine any existing subsets.

Cursor Information#

By moving your cursor along the image viewer, you will be able to see information on the cursor’s location in pixel space (X and Y), the RA and Dec at that point, and the value of the data there. This information is displayed in the top bar of the UI, on the middle-right side.

By default, the cursor information will correspond to the top image layer in the viewer. To change to a specific data-layer, click the layer-icon in the top bar to cycle between “auto”, “cursor”, or specific data layers.

Notes on GWCS#

If your reference data has GWCS with a bounding box, any coordinates transformation outside that bounding box is less reliable. This still applies even when you are looking at some other data that is not the reference data if they are linked by WCS because all transformations in glue go through the reference data. Such a situation is indicated by the affected coordinates becoming gray.

If your data of interest also has a GWCS with a bounding box, only the mouseover data where it overlaps with the reference data’s bounding box is completely reliable. Unreliable coordinates transformation here will also gray out in a similar fashion as above.

To avoid inaccurate transforms, consider one of the following workflows:

  • Make sure your reference data’s GWCS has a bounding box that encompasses all the other data you are trying to visualize together.

  • If the above is not possible, avoid overlaying different data with GWCS that do not overlap.

Warning

If you rely on the GWCS bounding box, it will be set to None when you data is loaded into Imviz, but the original bounding box, if available, is now in a hidden _orig_bounding_box attribute of the GWCS object. You can restore the bounding box by assigning the value of _orig_bounding_box back to its bounding_box attribute.

Note that FITS WCS has no similar concept of bounding box.

Home#

This button will reset your zoom and panning to display the entire image.

Previous zoom is also available by right-clicking on the home icon and selecting the previous zoom icon. This will revert to the last saved zoom state. Zoom states are saved when beginning a zoom selection or when activating a pan/zoom tool.

Box Zoom and Linked Box Zoom#

Linked Box Zoom is an Imviz-specific feature enabled only when there are multiple viewers that allows the user to zoom images in multiple different viewers simultaneously, not unlike Pan/Zoom and Linked Pan/Zoom.

Single-viewer Box Zoom is also available and is used in a similar way as in other Jdaviz tools. To access this option when there are multiple viewers, right-click on the Linked Box Zoom button and left-click on the second option down to select it.

Pan/Zoom and Linked Pan/Zoom#

Linked Pan/Zoom is an Imviz-specific feature enabled only when there are multiple viewers that allows the user to pan and zoom images in multiple different viewers simultaneously. This works by matching images based on the way they are linked together. Images are linked by pixels on load time, but you can re-link them via WCS using Orientation.

Single-viewer Pan/Zoom is also available and is used in a similar way as in other Jdaviz tools. To access this option when there are multiple viewers, right-click on the Linked Pan/Zoom button and left-click on the second option down to select it.

When in either of these modes, clicking on the image will recenter the image to the location under cursor.

From the API#

From the API, you can programmatically zoom in and out. Zoom level:

  • 1 - real-pixel-size

  • 2 - zoomed in by a factor of 2

  • 0.5 - zoomed out by a factor of 2

  • 'fit' - zoomed to fit the whole image width into display

For example:

viewer = imviz.default_viewer
viewer.zoom_level
viewer.zoom_level = 1  # Set the zoom level directly.
viewer.zoom(2)  # Set the relative zoom based on current zoom level.
Defining Spatial Regions#

Spatial regions allow users to select subsets of the data array for use in specific analysis functions in the plugin toolbar, for example in the Aperture Photometry plugin. Users can create spatial regions either in Imviz or the Jupyter notebook.

Regions can be created by first clicking the circular region icon icon (to draw a circular region), then clicking and dragging (using the mouse) until the desired region is covered by a colored shape, after which you release the mouse button. If you want to draw other shapes, right click on the icon to see a dropdown of supported shapes and left click on it to choose the shape, then draw as mentioned above.

Once you have completed the action of clicking and dragging, there is an opportunity to reposition the region of interest by clicking on it and moving the region to a different location in the image viewer. If you are satisfied with the positioning of your region of interest, simply click another part of the viewer to lock it in place.

There are other options available for region of interest. At the top of the user interface, there is a section that says either “+ No selection (create new)” or “Subset n” where n is an integer that tells you which Subset is currently selected. To the right of this area, are red circles that allow you to change the method of region selection. The options are:

  • replace: will remove the previously created selection and place the newly created subset.

  • add: allows you to create another subset that extends the existing subset.

  • and: only leaves behind the overlapping region between the existing subset and any additional subsets.

  • xor: only leaves behind the non-overlapping region between the existing subset and any additional subsets.

  • remove: will de-select any parts of the existing subset that overlaps with any additional subsets.

You can use these options to further adjust the region of interest and adapt it to your use case.

See also

Importing Spatial Regions

Importing regions from within the Jupyter notebook.

See also

Exporting Spatial Regions

Exporting regions from within the Jupyter notebook.

You can import and export regions from the API.

See also

Defining subsets using glue

Glueviz documentation on defining and refining subsets. Slightly different UI but same approach.

There are options available in the Layer tab under the settings sliders icon icon to make subsets visible or invisible, to change their color, and to change their opacity.

Single-Pixel Selection#

This tool is no longer available as of Jdaviz v3.9; use Markers plugin instead.

Blinking#

Blinking is an Imviz-specific functionality that allows a user to quickly switch between viewing two or more images, as long as they are linked (see Pan/Zoom and Linked Pan/Zoom for more on linking behavior). This can be done by selecting the blink icon icon (only available if there are more than one image loaded in the viewer) and then left-clicking on the image to blink forward; right-clicking would blink backwards.

You can also blink forward by pressing the “b” key on your keyboard while moused over the image. If you press Shift + “b” (“B”), you may blink backwards.

From the API#

From the API within the Jupyter notebook:

viewer = imviz.default_viewer
viewer.blink_once()

And to blink backwards:

viewer.blink_once(reversed=True)
Contrast/Bias#

In addition to changing Contrast and Bias in the Display Settings, Imviz has a white to black icon button under the blink icon menu that can also adjust those values.

After right-clicking on the blink icon, left click on the constrast/bias icon to activate it. Now you can click and drag on the image viewer to change to change the contrast and bias. Moving along the X-axis will change the bias and moving along the Y-axis will change the contrast. If you would like to reset to the default contrast and bias settings, you can double-click on the display while the mode is active.

Display Settings#

To access all of the different display settings for an image viewer, click the settings sliders icon icon in the viewer toolbar or open the Plot Options plugin. Changing the display settings DOES NOT change the underlying data, only the visualization of that data.

Imviz Plot Options

If you wish to access plot options via API (also see PlotOptions), you can use the following generic example. More specific examples are given later in this Section.

plot_options = imviz.plugins['Plot Options']
plot_options.layer = 'my file'
plot_options.image_colormap = 'Plasma'
plot_options.stretch_function = 'Arcsinh'
plot_options.stretch_vmin = 0.05
plot_options.stretch_vmax = 1.0
Layer#

This option allows you to change which layer you are changing the settings for.

Show image#

This option selects whether to show or hide the image in the viewer.

Color mode#

This option allows you to choose whether to use a colormap or or a single color to visualize the image. The colormap can be selected from a dropdown within the Layer tab. In monochromatic mode, the color can be chosen from a color picker under “Image Color” within the Layer tab.

In monochromatic mode, the option “Assign RGB presets” appears. This will automatically assign colors spanning from blue to red to the available layers and will adjust opacity and stretch to produce a composite color image (also known as RGB image). You will then be able to fine tune all options within each Layer tab.

From the API#

The colormap for just the image being displayed can be set using the Astrowidgets API:

viewer = imviz.default_viewer
viewer.colormap_options
viewer.set_colormap('Viridis')

Or it can be set using the Plugin API (in this example, the colormap is being set for all the images at once):

plot_options = imviz.plugins['Plot Options']
plot_options.select_all()
plot_options.image_colormap = 'Viridis'
Adding Custom Colormap#

A custom colormap can only be added when Imviz is run in a notebook, not from the command line. The custom colormap must be added to glue before starting Imviz. The example below adds a random colormap generated by photutils into glue:

from glue.config import colormaps
from photutils.utils import make_random_cmap

randcmap = make_random_cmap(ncolors=256)
randcmap.colors[0] = 0.  # To make your background black
colormaps.add('photutils_cmap', randcmap)

Only after the above is done can you start Imviz and use the custom colormap:

imviz = Imviz()
imviz.load_data('myimage.fits')
imviz.default_viewer.set_colormap('photutils_cmap')
Opacity#

Change the translucence of the image.

Contrast#

Change the luminance of the color in the image.

Bias#

Set a constant to subtract from every point in the data array before applying the conversion between data value and displayed pixel saturation. The bias slider center position is 0 bias, such that a user can apply negative bias values by sliding it left.

Stretch#

The Stretch Function allows you to change the equation that is used to convert data values between min and max to the 0 to 1 scale of pixel saturation on the image. The Percentile can be used to set the min and max values based on percentiles of the data. An interactive histogram is available. It shows vertical lines representing the stretch_vmin and stretch_vmax values, and a colorbar on top. The stretch “curve” is plotted on the histogram to represent how pixel values are mapped to the colorbar and can be toggled on and off in the plugin. The collapsed menu “More stretch options” includes a toggle to limit the histogram to the current zoom limits (which is not on by default) and fields to set min and max manually.

From the API#

The stretch function for just the image being displayed (the acceptable values are as defined by glue backend) can be set using the Astrowidgets API:

viewer = imviz.default_viewer
viewer.stretch_options
viewer.stretch = 'sqrt'

Or it can be set using the Plugin API for a single image or all the images at once (the acceptable values are the same as the GUI menu options and can be accessed with plot_options.stretch_function.choices):

plot_options = imviz.plugins['Plot Options']
plot_options.select_all()
plot_options.stretch_function = 'Square Root'

The stretch curve on the histogram can also be toggled using the Plugin API:

plot_options = imviz.plugins['Plot Options']
plot_options.stretch_curve_visible = True

The percentile for just the image being displayed can be set using the Astrowidgets API:

viewer = imviz.default_viewer
viewer.cuts = '95%'  # Preset
viewer.cuts = (0, 1000)  # Custom

Or it can be set using the Plugin API for one image or all the images at once:

plot_options = imviz.plugins['Plot Options']
plot_options.select_all()

# Preset
plot_options.stretch_preset = '95%'

# Custom
plot_options.stretch_preset = 'Custom'
plot_options.stretch_vmin = 0
plot_options.stretch_vmax = 1000
Contour#

This option selects whether to show or hide contours. It is off by default and can be turned on by clicking the eye icon. The Contours of a second image can be plotted over a first image or cube. The contours of the second image will appear superimposed on the first image. If contours are overplotted on a cube, the contours will remain unchanged as you scrub through the cube. Please note that this feature is in development and will be improved in the future.

Adding New Viewers#

In the toolbar towards the top of the UI, there is a picture with a plus icon icon that when clicked will add new viewers to the application. You can then select from the data that has been loaded into the application to be visualized in these additional viewers. You can then utilize some of the Imviz-specific features, like Pan/Zoom and Linked Pan/Zoom.

From the API#

From the API within the Jupyter notebook:

viewer_2_name = 'Window 2'
viewer_2 = imviz.create_image_viewer(viewer_name=viewer_2_name)
imviz.app.add_data_to_viewer(viewer_2_name, 'MyImportedData')

where 'MyImportedData' is a data set that has already been imported into Imviz.

Data Analysis Plugins#

The Imviz data analysis plugins are meant to aid quick-look analysis of 2D image data. All plugins are accessed via the plugin icon in the upper right corner of the Imviz application.

Imviz Plugins
Metadata Viewer#

This plugin allows viewing of any metadata associated with the selected data.

If the data is loaded from multi-extension FITS that contains a primary header, you will also see a Show primary header toggle, when enabled, would display just the primary header metadata.

Plot Options#

This plugin gives access to per-viewer and per-layer plotting options.

See also

Display Settings

Documentation on various display settings in the Jdaviz viewers.

Subset Tools#

This plugin allows you to select an existing subset to modify, or to select Create new to create a new subset by selecting and using the region selector in the spectrum viewer toolbar. You can also choose the operation that will be applied by the selector tool. Note that these are synched with the subset tools in the app-level toolbar. It might not show some static regions loaded via the API unless an interactive region is drawn after.

If an existing subset is selected, the parameters of the subset will also be shown. Note that in addition to parameters for compound regions (e.g., a subset with multiple disjoint regions) being displayed, the logical operations joining them (OR, AND, etc.) are shown as well for each region. This shows how all regions are added together to create the subset shown in the viewer.

For a simple subset or group of subsets in Imviz only, you can choose to recenter based on the selected Data. To switch to multiselect mode, click the icon in the top right of the plugin and select multiple subsets from the drop-down menu. The centroid is calculated by photutils.aperture.ApertureStats.centroid, which is the center-of-mass of the data within the aperture. No background subtraction is performed. Click Recenter to change its parameters and move it to the calculated centroid. This may take multiple iterations to converge.

Note

If you want accurate centroid calculations, it is recommended that you use a background-subtracted image. Alternately, you could calculate the centroid outside of Jdaviz (e.g., using photutils) and then manually edit the subset (see below) or load your own aperture object (Importing regions via the API).

For a simple subset, you can edit its parameters by changing the values in the corresponding editable text fields. Once you have entered the new value(s), click Update to apply. You should see the subset parameters, shape, and orientation (if applicable) all update concurrently.

Angle is counter-clockwise rotation around the center in degrees.

Markers#

This plugin allows for interactively creating markers in any viewer and logging information about the location of that marker along with the applicable data and viewer labels into a table.

With the plugin open in the tray, mouse over any viewer and press the “m” key to log the information displayed in the app toolbar into the table. The markers remain at that fixed pixel-position in the viewer they were created (regardless of changes to the underlying data or linking) and are only visible when the plugin is opened.

In Imviz, the table also exposed columns labeled “pixel:unreliable”, “world:unreliable”, and “value:unreliable”. These will be logged as True in cases where the information is outside the bounds of the reference image’s WCS (noted in the mouseover display by the information showing as grayed).

From the API#

To export the table into the notebook via the API:

markersplugin = imviz.plugins['Markers']
markersplugin.export_table()
Orientation#

Note

This plugin was previous called “Links Control”.

This plugin is used to align image layers by pixels or sky (WCS). All images are automatically linked by pixels on load but you can use it to re-link by pixels or WCS as needed.

For WCS linking, the “fast approximation” option uses an affine transform to represent the offset between images, if possible. It is much more performant at the cost of accuracy but should be accurate to within a pixel for most cases. If approximation fails, WCS linking still automatically falls back to full transformation.

Since Jdaviz v3.9, when linking by WCS, a hidden reference data layer without distortion (labeled “Default orientation”) will be created and all the data would be linked to it instead of the first loaded data. As a result, working in pixel space when linked by WCS is not recommended. Additionally, any data with distorted WCS would show as distorted on the display. Furthermore, any data without WCS can no longer be shown in WCS linking mode.

For the best experience, it is recommended that you decide what kind of link you want and set it at the beginning of your Imviz session, rather than later.

For more details on linking, see Linking of datasets in glue.

From the API#

From the API within the Jupyter notebook (if linking by WCS):

imviz.link_data(link_type='wcs')
Orientation: Image Rotation#

When linked by WCS, sky rotation is also possible. You can choose from presets (N-up, E-left/right) or provide your own sky angle.

Warning

Each rotation request created a new reference data layer in the background. Just as in Importing Data into Imviz, the performance would be impacted by the number of active rotation layers you have; Only keep the desired rotation layer. Note that the “default orientation” layer cannot be removed.

Compass#

For an image with a valid WCS, the compass will show directions to North (N) and East (E) for ICRS sky coordinates. It also shows the currently displayed data label, the X and Y directions, and the zoom box.

Note that when the axes canvas is rotated (by Canvas Rotation), the zoom box corresponds to the set zoom limits, not the extent of the viewer. Instead, the compass image itself is shown rotated/flipped to the same orientation.

When you have multiple viewers created in Imviz, use the Viewer dropdown menu to change the active viewer that it tracks.

Line Profiles#

This plugin plots line profiles across X and Y for the pixel under cursor when l key is pressed on the image viewer. You can also manually type in the values of X and Y, and then press the PLOT button. The top visible image, the same one displayed under Compass, will be used for these plots.

This plugin only considers pixel locations, not sky coordinates.

Aperture Photometry#

Warning

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

This plugin performs simple aperture photometry and plots a radial profile for one object within an interactively selected region. A typical workflow is as follows:

  1. Load image(s) in Imviz (see Importing Data into Imviz).

  2. Draw a region over the object of interest (see Defining Spatial Regions).

  3. Select the desired image using the Data dropdown menu.

  4. Select the desired region using the Subset dropdown menu. You can use the Subset Tools plugin to center it first on the object of interest using its center of mass, if you wish. Depending on the object, it may take several iterations for re-centering to converge, or it may never converge at all.

    Note

    You cannot use annulus region as aperture (an exception will be thrown) but you may use it for background (see below).

  5. If you want to subtract background before performing photometry, you have the following 3 options. Otherwise if your image is already background subtracted, choose “Manual” and leave the background set at 0:

  • Manual: Enter the background value in the Background value field. This value must be in the same unit as display data, if applicable.

  • Subset: Define a region for background calculation (median) using Subset draw tool and select that region using the Background dropdown menu. Only regions created with the replace option are acceptable as background regions (see Defining Spatial Regions).

  1. For some JWST and HST images, pixel area in arcsec squared is automatically populated in the Pixel area field from image metadata. If it does not auto-populate for you, you can manually enter a value but it must be in the unit of arcsec squared. This field is only used if per steradian is detected in display data unit. Otherwise, it is only informational. If this field is not applicable for you, leave it at 0. This field resets every time Data selection changes if auto-population not possible.

    Warning

    If your data is in surface brightness units and pixels on the image have varying sky area, you should first convert your data from surface brightness to flux units before using this plugin. This is because, for performance reasons, the plugin multiplies by the area after the aperture sum is calculated.

  2. If you also want photometry result in the unit of counts, you can enter a conversion factor in the Counts conversion factor field. The value must be in the unit of display data unit per counts. This is used to convert linear flux unit (e.g., MJy/sr) to counts. This field is only used if data has a valid unit. If this field is not applicable for you, leave it at 0. This field resets every time Data selection changes.

  3. If you also want photometry result in magnitude unit, you can enter a flux scaling factor in the Flux scaling field. Flux scaling is populated for JWST images if MJy/sr data unit is detected and pixel area is given to factor out the per-steradian unit. The value used, if this is the case, is the scaling to convert MJy to AB magnitude. Otherwise, the value must be in the same unit as display data unit. A magnitude is then calculated using -2.5 * log(flux / flux_scaling). This calculation only makes sense if your display data unit is already in linear flux unit. Setting this to 1 is equivalent to not applying any scaling. This field is only used if data has a valid unit. If this field is not applicable for you, leave it at 0. This field resets every time Data selection changes.

  4. Select the desired radial profile plot type using the Plot Type dropdown menu:

  • Curve of Growth: sum (sum of flux in the aperture) across radii from center out to the edge of the aperture. This is calculated in the same way as the final aperture sum in the output table, which is explained farther down on this page.

  • Radial Profile: Binned average as a function of radius from the center of the region.

  • Radial Profile (Raw): Raw image data points as a function of radius from the center of the region. Caution: having too many data points may cause performance issues with this feature. The exact limitations depend on your hardware.

  1. Toggle Fit Gaussian on to fit a Gaussian1D model to the radial profile data. This is disabled for curve-of-growth.

  2. Once all inputs are populated correctly, click on the CALCULATE button to perform simple aperture photometry.

Note

The shape you see drawn from Defining Spatial Regions is not exactly the aperture mask being used by photutils. This is because photutils uses fractional pixels and this is not reflected in the display.

Masking and weights by uncertainty are currently not supported. However, if NaN exists in data, it will be treated as 0.

When calculation is complete, a plot would show the radial profile of the background subtracted data and the photometry and model fitting (if requested) results are displayed under the CALCULATE button.

Imviz radial profile plot.

Radial profile.#

Imviz radial profile plot (raw).

Radial profile (raw).#

See also

Export Photometry

Documentation on exporting photometry results.

Footprints#

This plugin supports loading and overplotting instrument footprint overlays on the image viewers. Any number of overlays can be plotted simultaneously from any number of the available preset instruments (requires pysiaf to be installed) or by loading an Astropy regions object from a file.

The top dropdown allows renaming, adding, and removing footprint overlays. To modify the display and input parameters for a given overlay, select it in the dropdown, and modify the choices in the plugin to change its color, opacity, visibilities in any image viewer in the app, or to select between various preset instruments and change the input options (position on the sky, position angle, offsets, etc).

To import a file, choose “From File…” from the presets dropdown and select a valid file (must be able to be parsed by regions.Regions.read).

To import a regions file or object from the API:

fp = imviz.plugins['Footprints']
fp.open_in_tray()
fp.add_overlay('my imported overlay')  # or fp.rename_overlay to rename an existing entry
fp.import_region(region)
Canvas Rotation#

Note

This plugin is deprecated in favor of rotation via Orientation and will be removed in a future release.

The canvas rotation plugin allows rotating and horizontally flipping the image to any arbitrary value by rotating the canvas axes themselves. Note that this does not affect the underlying data, and exporting data to the notebook via the API will therefore not exhibit the same rotation.

The Compass will also rotate (and flip) accordingly, but will show the zoom box corresponding to the zoom limits, not the region shown in the viewer itself.

Presets are provided to reset the orientation as well as to set north up and east either to the right or the left, as well as a slider and input to set the angle and a switch to set whether the axes should be flipped horizontally after applying the rotation (a vertical flip can be achieved via a 180 deg rotation and a horizontal flip).

Due to browser limitations, Canvas Rotation is only available on Chromium-based browsers.

Export#

This plugin allows exporting:

  • the plot in a given viewer to a PNG or SVG file,

  • a table in a plugin to ecsv

  • subsets as a region to .fits or .reg file.

Exporting Data from Imviz#
Spatial Regions#

You can extract supported spatial regions as follows:

regions = imviz.get_interactive_regions()
regions
Aperture Photometry#

If you opted to fit a Gaussian1D to the radial profile, the last fitted model parameters will be displayed under the radial profile plot. The model itself can be obtained as follows. See Models and Fitting (astropy.modeling) on how to manipulate the model:

my_gaussian1d = imviz.app.fitted_models['phot_radial_profile']

The bottom of the plugin shows a table of past results, along with the subset and data used to compute them. These results can be exported as an QTable as follows, assuming imviz is the instance of your Imviz application:

results = imviz.get_aperture_photometry_results()

When multiple calculations are done in the same session (e.g., calculating aperture photometry for the same region across different images or for different regions on the same image), imviz.get_aperture_photometry_results() will return all the calculations in the same table, if possible. However, if the newest result is incompatible with the existing ones (e.g., two images have very different units), only the newest is kept in the table. When you are unsure, save the results after each calculation as different variables in your Python session.

The output table contains the results you see in the plugin and then some. The columns are as follow:

  • id: ID number assigned to the row, starting from 1.

  • xcenter, ycenter: Center of the aperture (0-indexed).

  • sky_center: SkyCoord associated with the center. If WCS is not available, this field is None.

  • background: The value from Background value, with unit attached.

  • sum: Sum of flux in the aperture. If per steradian is in input data unit, total pixel area covered in steradian is already multiplied here, if applicable, so there will be no per steradian in its unit. Otherwise, it has the same unit as input data. For more details on how the photometry is done, see Aperture Photometry (photutils.aperture).

  • sum_aper_area: The pixel area covered by the region. Partial coverage is reported as fraction.

  • pixarea_tot: If per steradian is in input data unit and pixel area is provided, this contains the conversion factor for the sum to take out the steradian unit. Otherwise, it is None.

  • aperture_sum_counts: This is the aperture sum converted to counts, if Counts conversion factor was set. Otherwise, it is None. This calculation is done without taking account of pixarea_tot, even when it is available.

  • aperture_sum_counts_err: This is the Poisson uncertainty (square root) for aperture_sum_counts. Other uncertainty factors like readnoise are not included. In the plugin, it is displayed within parenthesis next to the value for aperture_sum_counts, if applicable.

  • counts_fac: The value from Counts conversion factor, with unit attached, if applicable. Otherwise, it is None.

  • aperture_sum_mag: This is the aperture sum converted to magnitude, if Flux scaling was set. Otherwise, it is None. This calculation is done without taking account of pixarea_tot, even when it is available.

  • flux_scaling: The value from Flux scaling, with unit attached, if applicable. Otherwise, it is None.

  • min, max, mean, median, mode, std, mad_std, var, biweight_location, biweight_midvariance: Basic statistics from the aperture.

  • fwhm, semimajor_sigma, semiminor_sigma, orientation, eccentricity: Properties of a 2D Gaussian function that has the same second-order central moments as the source.

  • data_label: Data label of the image used.

  • subset_label: Subset label of the region used.

  • timestamp: Timestamp of when the photometry was performed as Time.

Note

Aperture sum and statistics are done on the originally drawn aperture only. You can use the Subset Tools plugin to center it first on the object of interest, if you wish.

Once you have the results in a table, you can further manipulated them as documented in Data Tables (astropy.table).

Markers Table#

All mouseover information in the markers plugin can be exported to an astropy table by calling export_table() (see Accessing Plugin APIs):

markers_plugin = imviz.plugins["Markers"]
markers_table = markers_plugin.export_table()
Examples#

Below is a quick introductory tour of the Imviz configuration and its features. To get started, we recommend cloning the Jdaviz repo and running the ImvizExample notebook.

See also

Example notebooks

A number of additional example notebooks.

Open Image Data#
Overplotting a Catalog#
Aligning Images#
Exploring the Plugin Toolbar#
Aperture Photometry#

specviz_logo Specviz#

Introductory video tour of the Specviz configuration and its features

Specviz is a tool for visualization and quick-look analysis of 1D astronomical spectra. It incorporates visualization tools with analysis capabilities, such as Astropy regions and specutils packages. Users can interact with their data from within the tool.

Specviz allows spectra to be easily plotted and examined. It supports flexible spectral unit conversions, custom plotting attributes, interactive selections, multiple plots, and other features. Specviz notably includes a measurement tool for spectral lines which enables the user, with a few mouse actions, to perform and record measurements. It has a model fitting capability that enables the user to create simple (e.g., single Gaussian) or multi-component models (e.g., multiple Gaussians for emission and absorption lines in addition to regions of flat continua).

A typical data-analysis workflow might involve data exploration using Specviz and then scripting to create more complex measurements or modeling workflows using specutils. Data can be both imported into and exported out of the tool so users can continue their desired workflow within the notebook. This documentation provides details on its various capabilities alongside demo videos and example notebooks.

Using Specviz

Importing Data Into Specviz#

By design, Specviz only supports data that can be parsed as Spectrum1D objects, as that allows the Python-level interface and parsing tools to be defined in specutils instead of being duplicated in Jdaviz. Spectrum1D objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page Creating Jdaviz-readable Products.

See also

Reading from a File

Specutils documentation on loading data as Spectrum1D objects.

Importing data through the Command Line#

You can load your data into the Specviz application through the command line. Specifying a data file is optional, and multiple data files may be provided:

jdaviz --layout=specviz /my/directory/spectrum1.fits /my/directory/spectrum2.fits
Importing data through the GUI#

You can load your data into the Specviz application by clicking the Import Data button at the top left of the application’s user interface. This opens a dialogue where the user can select a file that can be parsed as a Spectrum1D.

After clicking Import, the data file will be parsed and loaded into the application. A notification will appear to let users know if the data import was successful. Afterward, the new data set can be found in the Data tab of each viewer’s options menu as described in Selecting a Data Set.

Importing data via the API#

Alternatively, users who work in a coding environment like a Jupyter notebook can access the Specviz helper class API. Using this API, users can load data into the application through code with the load_data() method, which takes as input a Spectrum1D object.

FITS Files#

The example below loads a FITS file into Specviz:

from specutils import Spectrum1D
spec1d = Spectrum1D.read("/path/to/data/file")
specviz = Specviz()
specviz.load_data(spec1d, data_label="my_spec")
specviz.show()

You can also pass the path to a file that Spectrum1D understands directly to the load_data() method:

specviz.load_data("path/to/data/file")
Creating Your Own Array#

You can create your own array to load into Specviz:

import numpy as np
import astropy.units as u
from specutils import Spectrum1D
from jdaviz import Specviz

flux = np.random.randn(200) * u.Jy
wavelength = np.arange(5100, 5300) * u.AA
spec1d = Spectrum1D(spectral_axis=wavelength, flux=flux)
specviz = Specviz()
specviz.load_data(spec1d, data_label="my_spec")
specviz.show()
JWST datamodels#

If you have a stdatamodels.datamodels object, you can load it into Specviz as follows:

from specutils import Spectrum1D
from jdaviz import Specviz

# mydatamodel is a jwst.datamodels.MultiSpecModel object
a = mydatamodel.spec[0]
flux = a.spec_table['FLUX']
wave = a.spec_table['WAVELENGTH']

spec1d = Spectrum1D(flux=flux, spectral_axis=wave)
specviz = Specviz()
specviz.load_data(spec1d, data_label="MultiSpecModel")
specviz.show()

There is no plan to natively load such objects until datamodels is separated from the jwst pipeline package.

Importing a SpectrumList#

The load_data() also accepts a SpectrumList object, in which case it will both load the individual Spectrum1D objects in the list and additionally attempt to stitch together the spectra into a single data object so that they can be manipulated and analyzed in the application as a single entity:

from specutils import SpectrumList
spec_list = SpectrumList([spec1d_1, spec1d_2])
specviz.load_data(spec_list)
specviz.show()

In the screenshot below, the combined spectrum is plotted in gray, and one of the single component spectra are also selected and plotted in red. Note that the “stitching” algorithm to combine the spectra is a simple concatenation of data, so in areas where the wavelength ranges of component spectra overlap you may see the line plot jumping between points of the two spectra, as at the beginning and end of the red region in the screenshot below:

_images/spectrumlist_combined.png

This functionality is also available in limited instances by providing a directory path to the load_data() method. Note that the read method of SpectrumList is only set up to handle directory input in limited cases, for example JWST MIRI MRS data, and will throw an error in other cases. In cases that it does work, only files in the directory level specified will be read, with no recursion into deeper folders.

The load_data() method also takes an optional keyword argument concat_by_file. When set to True, the spectra loaded in the SpectrumList will be concatenated together into one combined spectrum per loaded file, which may be useful for MIRI observations, for example.

Displaying Spectra#

Because of its use of glue as the underlying data-handling layer and its applicability in several different contexts, Specviz takes a modular approach to displaying data that has been loaded.

The first spectrum you load will be automatically displayed in the viewer with the view window set by the extent of the spectrum. Additional spectra may not be fully shown if they exceed the bounds of the plotted area, which are set based on the first displayed spectrum. The bounds can be changed via the Pan/Zoom tool or by deselecting the current spectra and selecting a different spectrum for display.

Much of the Specviz functionality can be handled within the tool or the Jupyter notebook using an API. The Toolbar below gives you several spectroscopic display options. Right click will open a dropdown with access to different options for each button.

Specviz Toolbar
Selecting/Showing Data Sets#

Data can be selected and de-selected in each viewer’s data menu, opened by clicking the data select icon button in the top left of the viewer. Here, you can click a checkbox next to the listed data to make the data visible (checked) or invisible (unchecked).

_images/data_tab.png

In addition to toggling the visibility of a data layer, the data can be unloaded from a viewer by clicking the X button on the right. Data unloaded from the viewer will also be excluded as options from dataset dropdown menus in the various plugins. Unloaded data will be available to re-load into the viewer (by clicking the + icon) or remove permanently from the app (by clicking the trashcan icon) from an expandable section in the data menu:

_images/specviz_remove_data.png
Cursor Information#

By moving your cursor along the spectrum viewer, you will be able to see information on the cursor position as well as the spectral axis value, pixel, and flux of the closest data point to the cursor. This information is displayed in the top bar of the UI, on the middle-right side.

By default, the cursor information will correspond to the closest data layer to the cursor. To change to a specific data-layer, click the layer-icon in the top bar to cycle between “auto”, “cursor”, or specific data layers.

Home#

This button will reset your zoom and panning to display the entire image.

Previous zoom is also available by right-clicking on the home icon and selecting the previous zoom icon. This will revert to the last saved zoom state. Zoom states are saved when beginning a zoom selection or when activating a pan/zoom tool.

Box Zoom#

The box zoom icon (box) and xrange zoom icon (x-range) zoom tools allow you to zoom by clicking and dragging with your mouse. The box zoom tool adjusts both the x and y range of the plot, whereas the x-range tool zooms only the x-axis to the selected region. While clicking and dragging you will see the selected region as a gray box, as below.

You can switch between the x-range zoom tool and the plot tool by right-clicking (or your trackpad equivalent) on the currently selected zoom icon on the viewer toolbar, which will open a menu of choices as in the screenshot below.

Pan Zoom#

There are several ways to pan around a spectrum or zoom in on features of interest. Right click will open a dropdown with access to different options described below.

Interactive Pan/Zoom (Desktop or Notebook Interface)#

You can find the following Pan/Zoom tools available in the viewer toolbar on the top right of the viewer.

2D Bidirectional Pan/Zoom#

The 2D zoom/pan icon icon allows you to zoom using the scroll wheel. The window will zoom into the area around your cursor. To pan, simply click and drag the window.

Horizontal/Vertical Zoom#

The horizontal zoom/pan icon (horizontal) and vertical zoom/pan icon (vertical) Zoom tools allow you to zoom along each axis, while locking the other. You can also zoom by scrolling.

Setting Viewer Bounds#

The limits of the x and y axes can be set in the Plot Option plugin using the expandable menu “Viewer bounds”.

Imviz Plot Options viewer bounds
From the API#

The Specviz helper contains a set of convenience methods to programmatically define the view of the spectrum viewer. You may instantiate a Specviz Helper via:

.. code-block:: python

from jdaviz import Specviz # Instantiate an instance of Specviz specviz = Specviz() # Display Specviz specviz.show()

Limit methods#

You can use the methods x_limits() and y_limits() to modify the field of view of Specviz. You can provide a scalar (which assumes the units of the loaded spectra), a Quantity, or 'auto' to automatically scale:

from astropy import units as u
specviz.x_limits()
specviz.x_limits(650*u.nm,750*u.nm)
specviz.y_limits('auto', 110.0)

Additionally, you can provide the limit methods with a SpectralRegion. Specviz shall set the bounds the upper and lower bounds of the SpectralRegion:

from specutils import SpectralRegion
bounds = SpectralRegion(0.45*u.nm, 0.6*u.nm)
specviz.x_limits(bounds)
Autoscale methods#

You can also quickly return to the default zoom using autoscale_x() and autoscale_y().

Axis Orientation methods#

To quickly flip an axis to change to and from ascending/descending, use flip_x() and flip_y().

Defining Spectral Regions#

Spectral regions can be defined by clicking on the horizontal region icon icon at the right of the viewer toolbar.

To select a region of interest, move the cursor to one of the end points (in wavelength) of the region you want to select, and drag it to the other end point. The selected region background will display in light gray color, and the spectral trace in color, coded to subset number and listed under the subsets dropdown.

Clicking on that selector, you can add more regions by selecting the “create new” entry.

From the API#

You can define a spectral region programmatically, by using the glue XRangeROI method and specifying the bounds of the spectral region (xmin, xmax).

from glue.core.roi import XRangeROI
sv = specviz.app.get_viewer('spectrum-viewer')
sv.toolbar_active_subset.selected = []
sv.apply_roi(XRangeROI(xmin, xmax))

To extract the properties of the defined spectral regions, you can use the get_spectral_regions() method:

_images/spectral_region_5.png
Line Selection#

This button will allow you to click and select a vertical line when multiple lines from a line list are over-plotted. Further analysis can be performed on this line of interest.

See also

Line Lists

Documentation on using line lists within Specviz.

Plot Settings#

To access plot settings for a particular viewer (including the spectrum viewer), click the settings sliders icon icon in the viewer toolbar or open the Plot Options plugin.

Layer#

The top section of the Layer tab contains options to change the color of the spectrum (click the color square icon icon to see a color change menu and a default color palette), change visibility of the spectrum (eye icon icon), and a dropdown box to select which layer will have its settings changed.

Line Width#

Width of the line for the spectrum in pixels. Larger values are thicker lines on the plot.

Line Opacity#

Opacity of the line. Maximum (1) is fully opaque and minimum (0) is fully transparent.

Plot profile as steps#

Toggle on to view the spectrum as a continuous line or a step function.

Plot uncertainties#

Toggle on to view uncertainties attached to the spectrum, if any.

From the API#

Here is an example on how to set the plot options from the API.

plot_options = specviz.plugins['Plot Options']
plotopt.line_color = 'blue'
plotopt.line_width = 3
plot_options.uncertainty_visible = True
Data Analysis Plugins#

The Specviz data analysis plugins are meant to aid quick-look analysis of 1D spectroscopic data. All plugins are accessed via the plugin icon in the upper right corner of the Specviz application. These plugins are built upon :ref:specutils to do the actual analysis work

Specviz Plugins

Any spectra generated by plugins (e.g., Gaussian Smooth) will generally be automatically displayed in the spectral viewer, and one can always see the spectra available and toggle their visibility in the data selection dropdown menu (see Selecting Data Set for more detail). If you are working in the notebook, you can also enable more reproducible analysis by using the Python API.

Metadata Viewer#

See also

Metadata Viewer

Imviz documentation on using the metadata viewer.

Plot Options#

See also

Spectral Plot Options

Documentation on further details regarding the plot setting controls.

Subset Tools#

See also

Subset Tools

Imviz documentation describing the concept of subsets in Jdaviz. Subsets in Specviz are strictly spectral subsets and do not support rotation or recentering.

Markers#

See also

Markers

Imviz documentation describing the markers plugin.

Gaussian Smooth#

Gaussian Smooth is performed on a Spectrum1D data object. The spectrum is convolved with a Gaussian function. The Gaussian standard deviation in pixels must be entered into the Standard deviation field in the plugin.

A new Spectrum1D object is generated and is added to the spectrum viewer. It can be selected and shown in the viewer via the Data icon in the viewer toolbar.

Model Fitting#
Model Fitting plugin

Astropy models can be fit to a spectrum via the Model Fitting plugin. Model components are selected via the Model Component pulldown menu. The Add Component button adds a Model Components block.

Model Parameters are automatically initialized with a guess. These starting values can be edited by the user. They may also be fixed by selecting the checkbox, so that they are not fit or changed by the model fitting.

A mathematical expression must be entered into the Equation Editor to specify the mathematical combination of models. This is also necessary even if there is only one model component. The model components are specified by their labels and the equation defaults to the sum of all created components, but can be modified to exclude some of components without needing to delete them entirely or to change to subtraction, for example.

After fitting, the expandable menu for each component model will update to show the fitted value of each parameter rather than the initial value, and will additionally show the standard deviation uncertainty of the fitted parameter value if the parameter was not set to be fixed to the initial value and if the spectrum uncertainty was loaded.

From the API#

The model fitting plugin can be run from the API:

# Open model fitting plugin
plugin_mf = specviz.plugins['Model Fitting']
plugin_mf.open_in_tray()
# Input the appropriate dataset and subset
plugin_mf.dataset = 'my spectrum'
plugin_mf.spectral_subset = 'Subset 1'
# Input the model components
plugin_mf.create_model_component(model_component='Linear1D',
                                 model_component_label='L')
plugin_mf.create_model_component(model_component='Gaussian1D',
                                 model_component_label='G')
# Set the initial guess of some model parameters
plugin_mf.set_model_component('G', 'stddev', 0.002)
plugin_mf.set_model_component('G', 'mean', 2.2729)
# Model equation gets populated automatically, but can be overwritten
plugin_mf.equation = 'L+G'
# Calculate fit
plugin_mf.calculate_fit()

Parameter values for each fitting run are stored in the plugin table. To export the table into the notebook, call export_table() (see Accessing Plugin APIs).

See also

Export Models

Documentation on exporting model fitting results.

Unit Conversion#

The spectral flux density and spectral axis units can be converted using the Unit Conversion plugin.

Select the frequency, wavelength, or energy unit in the New Spectral Axis Unit pulldown (e.g., Angstrom, Hertz, erg).

Select the flux density unit in the New Flux Unit pulldown (e.g., Jansky, W/(Hz/m2), ph/(Angstrom cm2 s)).

Note that this affects the default units in all viewers and plugins, where applicable, but does not affect the underlying data.

From the API#

The Unit Conversion plugin can be called from the API:

unitconv_pl = specviz.plugins['Unit Conversion']
unitconv_pl.spectral_unit = 'Angstrom'
Line Lists#

Line wavelengths can be plotted in the spectrum viewer using the Line Lists plugin.

Line lists (e.g. Common Stellar, SDSS, CO) can be selected from Preset Line Lists via the Available Line Lists pulldown. They are loaded and displayed by pressing Load List. Each loaded list is shown under Loaded Lines. Loaded line lists may be removed by pressing the circled-x button.

_images/line_lists.png

The Loaded Lines include a Custom line list which is automatically created, but populated with no lines. Lines may be added to the Custom line list by entering Line Name, Rest Value, and Unit for the spectral axis and pressing Add Line. Selected lines may be hidden by deselecting the associated check box.

The color of each line list may be adjusted with the color and saturation sliders. Entire line lists may be hidden in the display via Show All and Hide All, located at the bottom of each list. Similarly, all of the line lists may be shown or hidden via Plot All and Erase All, located at the bottom of the plugin.

Importing Custom Line Lists#

Jdaviz comes with curated line lists built by the scientific community. If you cannot find the lines you need, you can add your own by constructing an astropy table; For example:

from astropy.table import QTable
from astropy import units as u

my_line_list = QTable()
my_line_list['linename'] = ['Hbeta','Halpha']
my_line_list['rest'] = [4851.3, 6563]*u.AA

viz.load_line_list(my_line_list)
# Show all imported line lists
viz.spectral_lines
Redshift Slider#

Warning

Using the redshift slider with many active spectral lines causes performance issues. If the shifting of spectral lines lag behind the slider, try plotting less lines. You can deselect lines using, e.g., the “Erase All” button in the line lists UI.

The plugin also contains a redshift slider which shifts all of the plotted lines according to the provided redshift/RV. The slider applies a delta-redshift, snaps back to the center when releasing, and has limits that default based on the x-limits of the spectrum viewer. This provides a convenient method to fine-tune the position of the redshifted lines to the observed lines in the spectrum.

From the API#

The range and step size of the slider can be set from a notebook cell using the set_redshift_slider_bounds() method in Specviz by specifying the range or step keywords, respectively. Setting either keyword to 'auto' means its value will be calculated automatically based on the x-limits of the spectrum plot.

The redshift itself can be set from the notebook using the set_redshift method.

Any set redshift values are applied to spectra output using the get_spectra() helper method. Note that using the lower-level app data retrieval (e.g., specviz.get_data()) will return the data as originally loaded, with the redshift unchanged.

Line Analysis#
Line Analysis plugin

The Line Analysis plugin returns specutils analysis for a single spectral line. The line is selected via the region tool in the spectrum viewer to select a spectral subset. Note that you can have multiple subsets in Specviz, but the plugin will only show statistics for the selected subset.

A linear continuum is fitted and subtracted (divided for the case of equivalenth width) before computing the line statistics. By default, the continuum is fitted to a region surrounding the select line. The width of this region can be adjusted, with a visual indicator shown in the spectrum plot while the plugin is open. The thick line shows the linear fit which is then interpolated into the line region as shown by a thin line. Alternatively, a custom secondary region can be created and selected as the region to fit the linear continuum.

The properties returned include the line centroid, gaussian sigma width, gaussian FWHM, total flux, and equivalent width. Uncertainties on the derived properties are also returned. For more information on the algorithms used, refer to the specutils documentation.

The line flux results are automatically converted to Watts/meter^2, when appropriate.

From the API#

The Line Analysis plugin can be run from the API:

# Open line analysis plugin
plugin_la = specviz.plugins['Line Analysis']
plugin_la.open_in_tray()
# Input the appropriate spectrum and region
plugin_la.dataset = 'my spectrum'
plugin_la.spectral_subset = 'Subset 2'
# Input the values for the continuum
plugin_la.continuum = 'Subset 3'
# Return line analysis results
plugin_la.get_results()
Redshift from Centroid#

Following the table of statistics, the centroid can be used to set the redshift by assigning the centroid value to a line added in the Line List Plugin. Select the corresponding line from the dropdown, or by locking the selection to the identified line and using the line select icon (line selector) tool in the spectrum viewer.

Export#

This plugin allows a given viewer’s plot to be exported to various image formats.

Exporting Data From Specviz#
1D Spectra#

After data have been manipulated or analyzed, it is possible to export those data currently back into your Jupyter notebook:

specviz.get_spectra()

which yields a either a single specutils.Spectrum1D object or a dictionary of specutils.Spectrum1D (if there are multiple displayed spectra) that you can manipulate however you wish. You can then load the modified spectrum back into the notebook via the API described in Importing data via the API.

Alternatively, if you want more control over Specviz, you can access it the via the get_data method of the Specviz helper class. This method always returns a single spectrum; if there are multiple spectra loaded you must supply a label to the data_label argument. For example:

specviz.get_data(data_label='Spectrum 1')

To extract a spectrum with a spectral subset applied:

specviz.get_data(spectral_subset='Subset 1')

In this case, the returned specutils.Spectrum1D object will have a mask attribute, where True corresponds to the region outside the selected subset (i.e., the region that has been masked out). You could load back in a copy of the spectrum containing only your subset by running:

spec = specviz.get_data(spectral_subset='Subset 1')
subset_spec = Spectrum1D(flux=spec.flux[~spec.mask],
                         spectral_axis=spec.spectral_axis[~spec.mask])
specviz.load_data(subset_spec)

See also

Export From Plugins

Calculations (i.e., not spectroscopic data) from the plugins can also be exported back into the Jupyter notebook in some cases.

Spectral Regions#

If you have spectral region subsets, you can extract the parameters of these subsets as a specutils spectral region. For a list of available spectral regions to extract, you can type:

regions = specviz.get_spectral_regions()
regions

To extract the spectral region you want:

myregion = regions["Subset 2"]
Model Fits#

For a list of model labels:

models = specviz.get_models()
models

Once you know the model labels, to get a specific model:

mymodel = specviz.get_models(model_label="ModelLabel")

To extract all of the model parameters:

myparams = specviz.get_model_parameters(model_label="ModelLabel")
myparams

where the model_label parameter identifies which model should be returned.

Alternatively, the table of logged parameter values in the model fitting plugin can be exported to an astropy table by calling export_table() (see Accessing Plugin APIs):

model_fitting = specviz.plugins['Model Fitting']
model_fitting.export_table()
Markers Table#

All mouseover information in the markers plugin can be exported to an astropy table by calling export_table() (see Accessing Plugin APIs).

Examples#

Below is a quick introductory tour of the Specviz configuration and its features. To get started, we recommend cloning the Jdaviz repo and running the SpecvizExample notebook.

See also

Example notebooks

A number of additional example notebooks.

Open a Spectrum#
Model Fitting#
Line Analysis#

cubeviz_logo Cubeviz#

Introductory video tour of the Cubeviz configuration and its features

Cubeviz is a visualization and analysis toolbox for data cubes from integral field units (IFUs). It is built as part of the glue visualization tool. Cubeviz is designed to work with data cubes from the NIRSpec and MIRI instruments on JWST, and will work with IFU data cubes. It uses the specutils package from Astropy .

Cubeviz incorporates visualization tools with analysis capabilities, such as Astropy regions and specutils packages. Users can interact with their data from within the tool. Cubeviz allows spectra of regions within the cube to be easily plotted and examined, offering all the same capabilities as Specviz.

In addition, Cubeviz also allows users to interact with their cube to:

  • view the wavelength slices (RA, DEC),

  • view flux and error or data quality cubes simultaneously,

  • view spectra from selected spatial (RA, DEC) regions,

  • smooth cubes spatially (RA, DEC) and spectrally (wavelength),

  • create and display contour maps,

  • collapse cubes over selected wavelength regions,

  • fit spectral lines,

  • create moment maps, including line flux and kinematic maps (rotation velocity and velocity dispersion),

  • overlay spectral line lists,

  • save edited cubes,

  • save figures,

  • fit models to every spaxel

Using Cubeviz

Importing Data into Cubeviz#

By design, Cubeviz only supports data that can be parsed as Spectrum1D objects. Despite the name, Spectrum1D supports 3D cubes and allows the Python-level interface and parsing tools to be defined in specutils instead of being duplicated in Jdaviz. Spectrum1D objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page Creating Jdaviz-readable Products.

Cubeviz will automatically parse the data into the multiple viewers as described in Displaying Cubes. For the best experience, data loaded into Cubeviz should contain valid WCS keywords. For more information on how Spectrum1D uses WCS, please go to the Spectrum1D defining WCS section. To check if your FITS file contains valid WCS keywords, please use Astropy WCS validate. For an example on loading a cube with valid WCS keywords, please see the Importing data via the API section below.

Loading data without WCS is also possible as long as they are compatible with Spectrum1D. However, not all plugins will work with this data.

In Cubeviz, two image viewers at the top display your data:

Top Left: flux-viewer
Top Right: uncert-viewer

There is also a third viewer called spectrum-viewer at the bottom that will display the collapsed spectrum from flux-viewer.

Note

Only a single cube can be displayed in an instance of Cubeviz at a given time. To open a second cube, you must first initiate a second instance of Cubeviz.

To then extract your data from Cubeviz, please see the Exporting Data from Cubeviz section.

Importing data through the Command Line#

You can load your data into the Cubeviz application through the command line. Specifying a data product is optional:

jdaviz --layout=cubeviz /my/directory/cube.fits
Importing data through the GUI#

Users may load data into the Cubeviz application by clicking the Import Data button at the top left of the application’s user interface. This opens a dialogue with a prompt to select a file that can be parsed as a Spectrum1D object.

After clicking Import, the data file will be parsed and loaded into the application. A notification will appear to confirm whether the data import was successful. Afterward, the new data set can be found in the Data tab of each viewer’s options menu as described in Selecting a Data Set.

Importing data via the API#

Alternatively, users who work in a coding environment like a Jupyter notebook can access the Cubeviz helper class API. Using this API, users can load data into the application through code with the load_data() method, which takes as input a Spectrum1D object.

FITS Files#

The example below loads a FITS file into Cubeviz:

from jdaviz import Cubeviz
cubeviz = Cubeviz()
cubeviz.load_data("/path/to/data/file.fits")
cubeviz.show()
Spectrum1D (from file)#

For cases where the built-in parser is unable to understand your file format, you can try the Spectrum1D parser directly and then pass the object to the load_data() method:

from specutils import Spectrum1D
from jdaviz import Cubeviz
spec3d = Spectrum1D.read("/path/to/data/file.fits")
cubeviz = Cubeviz()
cubeviz.load_data(spec3d, data_label='My Cube')
cubeviz.show()
Spectrum1D (from array)#

You can create your own Spectrum1D object by hand to load into Cubeviz:

import numpy as np
from astropy import units as u
from astropy.wcs import WCS
from specutils import Spectrum1D
from jdaviz import Cubeviz

flux = np.arange(16).reshape((2, 2, 4)) * u.Jy
wcs_dict = {"CTYPE1": "WAVE-LOG, "CTYPE2": "DEC--TAN", "CTYPE3": "RA---TAN",
            "CRVAL1": 4.622e-7, "CRVAL2": 27, "CRVAL3": 205,
            "CDELT1": 8e-11, "CDELT2": 0.0001, "CDELT3": -0.0001,
            "CRPIX1": 0, "CRPIX2": 0, "CRPIX3": 0}
w = WCS(wcs_dict)

cube = Spectrum1D(flux=flux, wcs=w)
cubeviz = Cubeviz()
cubeviz.load_data(cube, data_label='My Cube')
cubeviz.show()
JWST datamodels#

If you have a stdatamodels.datamodels object, you can load it into Cubeviz as follows:

import numpy as np
from astropy.wcs import wcs
import astropy.units as u
from specutils import Spectrum1D
from jdaviz import Cubeviz
from jwst import datamodels

file = "/path/to/data/file.fits"
mydatamodel = datamodels.open(file)

# mydatamodel is a jwst.datamodels object
# Due to current schema in jwst.datamodels, you'll need to create your own WCS object before you create your Spectrum1D object
wcs_dict = {"CTYPE1": mydatamodel.meta.wcsinfo.ctype3, "CTYPE2": mydatamodel.meta.wcsinfo.ctype2,
        "CTYPE3": mydatamodel.meta.wcsinfo.ctype1,
        "CRVAL1": mydatamodel.meta.wcsinfo.crval3, "CRVAL2": mydatamodel.meta.wcsinfo.crval2,
        "CRVAL3": mydatamodel.meta.wcsinfo.crval1,
        "CDELT1": mydatamodel.meta.wcsinfo.cdelt3, "CDELT2": mydatamodel.meta.wcsinfo.cdelt2,
        "CDELT3": mydatamodel.meta.wcsinfo.cdelt1,
        "CRPIX1": mydatamodel.meta.wcsinfo.crpix3, "CRPIX2": mydatamodel.meta.wcsinfo.crpix2,
        "CRPIX3": mydatamodel.meta.wcsinfo.crpix1}
my_wcs = WCS(wcs_dict)

# Next, you need to make sure your spectral axis is the 3rd dimension
data = mydatamodel.data * (u.MJy / u.sr)
data = np.swapaxes(data, 0, 1)
data = np.swapaxes(data, 1, 2)

# Create your spectrum1
spec3d = Spectrum1D(data, wcs=my_wcs)
cubeviz = Cubeviz()
cubeviz.load_data(spec3d, data_label='My Cube')
cubeviz.show()

There is no plan to natively load such objects until datamodels is separated from the jwst pipeline package.

Numpy array#

To load a plain Numpy array without WCS:

import numpy as np
from jdaviz import Cubeviz
flux = np.arange(16).reshape((2, 2, 4))  # x, y, z
cubeviz.load_data(flux, data_label='My Cube')
cubeviz.show()
Importing regions via the API#

If you have a region file supported by Reading/Writing Region Files, you can load the regions into Cubeviz as follows:

cubeviz.load_regions_from_file("/path/to/data/myregions.reg")

Unsupported regions will be skipped and trigger a warning. Those that failed to load, if any, can be returned as a list of tuples of the form (region, reason):

bad_regions = cubeviz.load_regions_from_file("/path/to/data/myregions.reg", return_bad_regions=True)

Note

Sky regions are currently unsupported in Cubeviz, unlike Imviz.

For more details on the API, please see load_regions_from_file() and load_regions() methods in Cubeviz.

Displaying Cubes#

The Cubeviz layout includes two image viewers (at the top of the app) and one spectrum viewer (at the bottom of the app), which it attempts to populate automatically when the first dataset is loaded. By default, Cubeviz attempts to parse and display the flux in the top left viewer and the uncertainty in the top right viewer. The spectrum viewer is populated by default by collapsing the spatial axes using the “Sum” function. The indicators that the load machinery looks for in each HDU to populate the viewers are below (note that in all cases, header values are converted to lower case):

  • Flux viewer: hdu.name is in the set ['flux', 'sci']

  • Uncertainty viewer: hdu.header.keys() includes “errtype” or hdu.name is in the set ['ivar', 'err', 'var', 'uncert']

  • Loaded but not displayed: hdu.data.dtype is int, numpy.uint or numpy.uint32, or hdu.name is in the set ['mask', 'dq']

The next section describes how to manually select data in cases where a viewer is not automatically populated or a user wants to change the data displayed. Different statistics for collapsing the spectrum displayed in the spectrum viewer can be chosen as described in Display Settings. Note that any spatial subsets will also be collapsed into a spectrum using the same statistic and displayed in the spectrum viewer along with the spectrum resulting from collapsing all the data in each spectral slice.

Much of the Cubeviz functionality can be handled within the tool or the Jupyter notebook using an API. The Toolbar below gives you several spectroscopic display options. Right click will open a dropdown with access to different options for each button.

Cubeviz Toolbar
Selecting a Data Set#

If you have already imported data into Cubeviz, you can select and deselect data within a viewer.

See also

Selecting a Data Set

Documentation on selecting data sets in the Jdaviz viewers.

Home#

This button will reset your zoom and panning to display the entire image.

Box Zoom and Linked Box Zoom#

See also

Box Zoom and Linked Box Zoom in Imviz

Documentation on panning and zooming in Imviz.

Pan/Zoom and Linked Pan/Zoom#

See also

Pan/Zoom and Linked Pan/Zoom in Imviz

Documentation on panning and zooming in Imviz.

Note

Pan/Zoom API and click-to-center feature in Imviz is not yet available on Cubeviz.

Defining Spatial Regions#

See also

Defining Spatial Regions

Documentation on defining spatial regions in an image viewer.

Spatial regions allow users to select subsets of the data array for specific analysis function in the plugin toolbar. Users can create spatial regions either in Cubeviz or the Jupyter notebook. Once a region is selected, the cube will be collapsed in wavelength space over the region, and the resulting spectrum will be displayed in the 1D spectrum viewer at the bottom of the UI.

Subset creation in Cubeviz
Spectrum At Spaxel#

This tool allows the user to create a single-spaxel subset in an image viewer. This subset will then be visualized in the spectrum viewer by showing the spectrum at that spaxel. While this tool is active, hovering over a pixel in the image viewer will show a preview of the spectrum at that spaxel in the spectrum viewer, and left-clicking will create a new subset at that spaxel. Click again to move the region to a new location under the cursor. Holding down the alt key (Alt key on Windows, Option key on Mac) while clicking on a spaxel creates a new subset at that point instead of moving the previously created region. You can then compare spectra at different spaxels using the spectrum viewer. You can also use the subset modes that are explained in the Spatial Regions section above in the same way you would with the other subset selection tools.

Note that moving the cursor outside of the image viewer or deactivating the spectrum-at-spaxel tool will revert the spectrum viewer zoom limits from the zoomed-in preview view to the limits set prior to using the tool. Thus it may be necessary to reset the zoom to see any single-spaxel subset spectra created using the tool.

Display Settings#

See also

Display Settings

Documentation on various display settings in the jdaviz viewers.

To access all of the different display settings for an image viewer, click the settings sliders icon icon in the viewer toolbar or open the Plot Options plugin. Changing the display settings does not change the underlying data, only the visualization of that data.

Displaying Spectra#

A collapsed spectrum of the cube displayed in the upper-left viewer automatically appears in the 1D spectrum viewer, using the set collapse function. The collapse function can be changed in the Line tab of the Plot Options plugin, which can be reached by clicking the settings sliders icon icon in the spectrum viewer. Additional spectra can be loaded into the spectrum viewer, as detailed in the linked documentation below.

See also

Displaying Spectra (Specviz)

Documentation on displaying spectra in a 1D spectrum viewer.

There is one important difference when using the API to access Specviz from within Cubeviz. The functionality of the jdaviz.configs.specviz.helper.Specviz API can be accessed in Cubeviz via the specviz attribute, e.g. cubeviz.specviz.get_spectra().

Data Analysis Plugins#

The Cubeviz data analysis plugins are meant to aid quick-look analysis of 2D image data. All plugins are accessed via the plugin icon in the upper right corner of the Cubeviz application.

Cubeviz Plugins

The data analysis plugins are meant to aid quick-look analysis of both 3D and 1D spectroscopic data. In many cases, functions can be applied to Spectrum1D objects, which include both 3D and 1D datasets. Plugins that are specific to 1D spectra are described in more detail under Specviz: Data Analysis Plugins. In many cases, these capabilities can be further applied on a per spaxel basis within a cube.

Metadata Viewer#

See also

Metadata Viewer

Documentation on using the metadata viewer.

Plot Options#

This plugin gives access to per-viewer and per-layer plotting options. To show axes on image viewers, toggle on the “Show axes” option at the bottom of the plugin.

See also

Image Plot Options

Documentation on Imviz display settings in the Jdaviz viewers.

See also

Spectral Plot Options

Documentation on Specviz display settings in the Jdaviz viewers.

Subset Tools#

See also

Subset Tools

Imviz documentation describing the concept of subsets in Jdaviz.

Markers#

See also

Markers

Imviz documentation describing the markers plugin.

Slice#

The slice plugin provides the ability to select the slice of the cube currently visible in the image viewers, with the corresponding wavelength highlighted in the spectrum viewer.

To choose a specific slice, enter an approximate wavelength (in which case the nearest slice will be selected and the wavelength entry will “span” to the exact value of that slice). The snapping behavior can be disabled in the plugin settings to allow for smooth scrubbing, in which case the closest slice will still be displayed in the cube viewer.

The spectrum viewer also contains a tool to allow clicking and dragging in the spectrum plot to choose the currently selected slice. When the slice tool is active, clicking anywhere on the spectrum viewer will select the nearest slice across all viewers, even if the indicator is off-screen.

For your convenience, there are also player-style buttons with the following functionality:

  • Jump to first

  • Previous slice

  • Play/Pause

  • Next slice

  • Jump to last

Gaussian Smooth#

Gaussian smoothing can be applied either to the spectral or spatial dimensions of a cube.

See also

Gaussian Smooth

Specviz documentation on gaussian smoothing in the spectral dimension of 1D spectra.

Collapse#
_images/collapse_plugin.png

The Collapse plugin collapses a spectral cube along the wavelength axis to create a 2D spatial image. For spatial axes, the full extent of the selected dimension is included in the collapse. For the spectral axis, a wavelength range for collapse can be specified using a spectral subset or by entering the wavelength range manually.

To make a 2D image, first go to the Collapse plugin and select the cube dataset using the Data pulldown. Next, select the method for collapse (Mean, Median, Min, Max, or Sum) in the Method pulldown. To collapse a limited spectral subregion, you can either create and select a Region in the spectrum viewer, or enter the lower and upper spectral bounds manually. When you APPLY the Collapse, a 2D image is created. You can load this into any image viewer pane to inspect the result. For example, the Collapse Sum over an emission line is shown in the middle image viewer of the above figure.

Model Fitting#

See also

Model Fitting

Specviz documentation on fitting spectral models.

For Cubeviz, there is an additional option to fit the model over each individual spaxel by enabling the Cube Fit toggle before pressing Fit Model. The best-fit parameters for each spaxel are stored in planes and saved in a data structure. The resulting model itself is saved with the label specified in the Output Data Label field.

See also

Export Models

Documentation on exporting model fitting results.

Unit Conversion#

See also

Unit Conversion

Specviz documentation on unit conversion.

Line Lists#

See also

Line Lists

Specviz documentation on line lists.

Line Analysis#

See also

Line Analysis

Specviz documentation on line analysis.

Currently the Line Analysis plugin in Cubeviz will calculate statistics for spectral features in the collapsed spectrum, which is visualized in the spectrum viewer. The propagation of uncertainties from the uncertainty cube to the collapsed spectrum is still work in progress. As a result, uncertainties on values provided by the Line Analysis plugin are not provided.

Moment Maps#
_images/moment1_map.png

The Moment Maps plugin can be used to create a 2D image from a data cube. Mathematically, a moment is an integral of a 1D curve multiplied by the abscissa to some power. The plugin integrates the flux density along the spectral axis to compute a moment map. The order of the moment map (0, 1, 2, …) indicates the power-law index to which the spectral axis is raised. A ‘moment 0’ map gives the integrated flux over a spectral region. Similarly, ‘moment 1’ is the flux-weighted centroid (e.g., line center) and ‘moment 2’ is the dispersion (e.g., wavelength or velocity dispersion) along the spectral axis. Moments 3 and 4 are less commonly utilized, but correspond to the skewness and kurtosis of a spectral feature.

To make a moment map, first go to the Moment Maps plugin and select the cube dataset using the Data pulldown. To specify the spectral feature of interest, you can either create and select a Region in the spectrum viewer, or enter the lower and upper spectral bounds manually in the plugin. Next, enter the Moment index to specify the order of the moment map. When you press CALCULATE, a 2D moment map is created. You can load this into any image viewer pane to inspect the result. You can also save the result to a FITS format file by pressing SAVE AS FITS.

For example, the right image viewer in the screenshot above shows the Moment 2 map for a continuum-subtracted cube. Note that the cube should first be continuum-subtracted in order to create continuum-free moment maps of an emission line. Moment maps of continuum emission can also be created, but moments other than moment 0 may not be physically meaningful. Also note that by default, the units in the moment 1 and moment 2 maps reflect the units of the spectral axis (microns in this case). For moments higher than 0, the output units can instead be converted to velocity (e.g., m/s for moment 1, m2/s2 for moment 2, etc.) by selecting the Velocity radio button under Output Units and providing a reference wavelength, commonly that of the spectral line of interest.

Line or Continuum Maps#
_images/moment0_line_map.png

There are at least three ways to make a line map using one of three Cubeviz plugins: Collapse, Moment Maps, or Model Fitting. Line maps created using the first two methods require an input data cube that is already continuum-subtracted. Continuum maps can be created in a similar way for data that is not continuum-subtracted.

To make a line or continuum map using the Collapse Plugin, first import a data cube into Cubeviz. Next, go to the Collapse plugin and select the input data using the Data pulldown. Then set the Axis to the wavelength axis (e.g. 0 for JWST data) and the method to ‘Sum’ (or any other desired method). Next either create and select a Region in the spectrum viewer, or enter the lower and upper spectral bounds manually. When you Apply the Collapse, a 2D image of the spectral region is created. You can load this line map in any image viewer pane to inspect the result.

A line map can also be created using the Moment Maps Plugin using a similar workflow. Select the (continuum-subtracted) dataset in the Plugin using the Data pulldown. Then either select a subset in the Spectral Region pulldown or enter the lower and upper spectral bounds. Enter ‘0’ for Moment and press Calculate to create the moment 0 map. The resultant 2D image is the flux integral of the cube over the selected spectral region, and may be displayed in any image viewer, as shown in the middle image viewer in the figure above.

The third method to create a map is via the Model Fitting Plugin. First create and fit a model (e.g. a Gaussian plus continuum model) to an individual spectrum. Next, fit this model to every spaxel in your data cube. The resultant model parameter cube can be retrieved in a notebook. The line or continuum flux in each spatial pixel can then be computed by integrating over the line or continuum spectral region of interest.

Spectral Extraction#
_images/cubeviz_spectral_extraction.png

Note

Spectral Extraction requires at least version 5.3.2 of astropy.

The Spectral Extraction plugin produces a 1D spectrum from a spectral cube. The 1D spectrum can be computed via the sum, mean, minimum, or maximum of the spatial dimensions in the spectral cube. Select an extraction operation from the Function dropdown, and optionally choose a Spatial region, if you have one. Click EXTRACT to produce a new 1D spectrum dataset from the spectral cube, which has uncertainties propagated by astropy.nddata.

If using a simple subset (currently only works for a circular subset applied to data with spatial axis units in wavelength) 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. The formula for a circular aperture is (for other shapes, radius is replaced by appropriate shape attributes):

radii = ((all_wavelengths / reference_wavelength) *
    aperture.selected_spatial_region.radius)

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

The method of aperture masking can also be changed using the Aperture masking method dropdown. To see a description for each of these options, please see Aperture and Pixel Overlap. Using the exact aperture method with the min or max functions is not supported.

Aperture Photometry#

Cubeviz allows aperture photometry on some 3D and 2D data, as long as they have valid flux units. For 3D data, the current Slice is used.

See also

Imviz Aperture Photometry

Imviz documentation describing the concept of aperture photometry in Jdaviz.

Export#

This plugin allows exporting:

  • the plot in a given viewer to a PNG or SVG file,

  • a table in a plugin to ecsv

  • subsets as a region to .fits or .reg file.

Movie#

Note

For MPEG-4, this feature needs opencv-python to be installed; see [opencv-python on PyPI](https://pypi.org/project/opencv-python/).

Expand the “Export to video” section, then enter the desired starting and ending slice indices (inclusive), the frame rate in frames per second (FPS), and the filename. If a path is not given, the file will be saved to current working directory. Any existing file with the same name will be silently replaced.

When you are ready, click the Export to MP4 button. The movie will be recorded at the given FPS. While recording is in progress, it is highly recommended that you leave the app alone until it is done.

While recording, there is an option to interrupt the recording when something goes wrong (e.g., it is taking too long or you realized you entered the wrong inputs). Click on the stop icon next to the Export to MP4 button to interrupt it. Doing so will result in no output video.

Exporting Data from Cubeviz#

After data have been manipulated or analyzed, it is possible to export those data currently back into your Jupyter notebook.

Spatial Regions#

See also

Export Spatial Regions

Documentation on how to export spatial regions.

Since Specviz can be accessed from Cubeviz, the following line of code can be used to extract the spectrum of a spatial subset named “Subset 1”:

subset1_spec1d = cubeviz.specviz.get_spectra(spectral_subset="Subset 1")

An example without accessing Specviz:

subset1_spec1d = cubeviz.get_data(data_label=flux_data_label,
                                  spatial_subset="Subset 1",
                                  function="mean")

Note that in the above example, the function keyword is used to tell Cubeviz how to collapse the flux cube down to a one dimensional spectrum - this is not necessarily equivalent to the collapsed spectrum in the spectrum viewer, which may have used a different collapse function.

To get all subsets from the spectrum viewer:

subset1_spec1d = cubeviz.specviz.app.get_subsets()

To access the spatial regions themselves:

regions = cubeviz.get_interactive_regions()
regions
1D Spectra and Spectral Regions#

See also

Export Spectra

Documentation on how to export data from the spectrum-viewer.

The following line of code can be used to extract a spectral subset named “Subset 2”:

subset2_spec1d = cubeviz.specviz.get_spectra("Subset 2")
3D Data Cubes#

To extract the entire cube, you can run the following code (replace “data_name” with the name of the data you want to extract):

mydata = cubeviz.get_data(data_label="data_name")

The data is returned as a 3D specutils.Spectrum1D object.

To write out a specutils.Spectrum1D cube from Cubeviz (e.g., a fitted cube from Model Fitting), where the mask (if available) is as defined in Spectrum1D masks:

mydata.write("mydata.fits", format="jdaviz-cube")

Data can also be accessed directly from data_collection using the following code:

cubeviz.app.data_collection[0]

Which is returned as a Data object. The DataCollection object can be indexed to return all available data (i.e., not just using 0 like in the previous example).

Model Fits#

For a list of model labels:

models = cubeviz.get_models()
models

Once you know the model labels, to get a specific model:

mymodel = cubeviz.get_models(model_label="ModelLabel", x=10)

To extract all of the model parameters:

myparams = cubeviz.get_model_parameters(model_label="ModelLabel", x=x, y=y)
myparams

where the model_label parameter identifies which model should be returned and the x and y parameters identify specifically which spaxel fits are to be returned, for models applied to every spaxel using the Apply to Cube button. Leaving x or y as None will mean that the models fit to every spaxel across that axis will be returned.

Markers Table#

All mouseover information in the markers plugin can be exported to an astropy table by calling export_table() (see Accessing Plugin APIs).

Aperture Photometry#

Cubeviz can export photometry output table like Imviz:

results = cubeviz.get_aperture_photometry_results()

See also

Imviz Aperture Photometry

Imviz documentation describing exporting of aperture photometry results in Jdaviz.

In addition to the columns that Imviz Aperture Photometry would provide, the table from Cubeviz has this extra column after data_label:

  • slice_wave: Wavelength value at the selected slice of the cube used for computation. If a 2D data (e.g., collapsed cube) is selected, the value would be NaN instead.

Examples#

Below is a quick introductory tour of the Cubeviz configuration and its features. To get started, we recommend cloning the Jdaviz repo and running the CubevizExample notebook.

See also

Example notebooks

A number of additional example notebooks.

Open and Explore a Cube#
Selecting Subsets#
Model Fitting#
Line Analysis#

specviz2d_logo Specviz2D#

Introductory video tour of the Specviz2d configuration and its features

Specviz2d is a tool for visualization and quick-look analysis of 2D astronomical spectra. It incorporates visualization tools with analysis capabilities, such as Astropy regions and specreduce and specutils packages. In particular, it features interactive spectral extraction of 2D spectra.

Using Specviz2D

Importing Data Into Specviz2D#

By design, Specviz2D only supports data that can be parsed as Spectrum1D objects, as that allows the Python-level interface and parsing tools to be defined in specutils instead of being duplicated in Jdaviz. Spectrum1D objects are very flexible in their capabilities, however, and hence should address most astronomical spectrum use cases. If you are creating your own data products, please read the page Creating Jdaviz-readable Products.

See also

Reading from a File

Specutils documentation on loading data as Spectrum1D objects.

Specviz2D can either take both a 2D and 1D spectrum as input, or can automatically extract a 1D spectrum if only a 2D spectrum is provided. To view the extraction parameters and override the extraction, see the spectral extraction plugin.

Importing data through the Command Line#

You can load your data into the Specviz2D application through the command line. Providing a data file is optional and multiple data files are supported (NOTE: this currently only supports passing a 2D spectrum object and will automatically extract the 1D spectrum):

jdaviz --layout=specviz2d /my/directory/spectrum1.fits /my/directory/spectrum2.fits
Importing data through the GUI#

You can load your data into the Specviz2D application by clicking the Import Data button at the top left of the application’s user interface. This opens a dialogue where the user can select a file that can be parsed as a Spectrum1D.

After clicking Import, the data file will be parsed and loaded into the application.

Importing data via the API#

Alternatively, users who work in a coding environment like a Jupyter notebook can access the Specviz2D helper class API. Using this API, users can load data into the application through code with the load_data() method, which takes as input a Spectrum1D object or filename for the 2D spectrum and (optionally) the 1D spectrum.

specviz2d = Specviz2d()
specviz2d.load_data('/my/directory/2dspectrum.fits', '/my/directory/1dspectrum.fits')
specviz2d.show()

By default, extension 1 of the 2D file is loaded, but you can specify another extension by providing an integer to the ext keyword. In case you want to load an uncalibrated spectrum that is dispersed vertically, you can also set the transpose keyword to flip the spectrum to be horizontal:

specviz2d.load_data(filename, ext=7, transpose=True)
Displaying Spectra#

Specviz2D consists of a 2D spectrum viewer and a 1D spectrum viewer, with linked x-axes. Each viewer window contains a toolbar, including a data menu.

See also

Specviz: Displaying Spectra

Specviz documentation on the spectrum viewer.

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 plugin icon in the upper right corner of the Specviz2d application.

Metadata Viewer#

See also

Metadata Viewer

Imviz documentation on using the metadata viewer.

Plot Options#

See also

Plot Options

Specviz documentation on the plot options plugin.

Subset Tools#

See also

Subset Tools

Imviz documentation describing the concept of subsets in Jdaviz.

Markers#

See also

Markers

Imviz documentation describing the markers plugin.

Spectral Extraction#

The Spectral Extraction plugin exposes specreduce methods for tracing, background subtraction, and spectral extraction from 2D spectra.

To interact with the plugin via the API in a notebook, access the plugin object via:

sp_ext = specviz2d.plugins['Spectral Extraction']
Trace#

The first section of the plugin allows for creating and visualizing specreduce.tracing.Trace 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 in the 2D spectrum viewer.

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.

Suppose you have 2D spectra of an extended source, and you have already created a trace that follows the bright central region of the source. It is possible to create a new trace, with the same 2D shape as the trace of the central region, but offset in the spatial direction. This might be useful for extracting spectra from the faint outer regions of the extended source, while using a trace computed from the brighter inner region. You can create a new trace based on the existing trace by clicking the “Trace” dropdown and selecting the existing trace. Then, offset it in the spatial direction by clicking or entering the spatial offset, and save it by creating a new trace or overwriting the existing trace entry.

From the API#

Trace parameters can be set from the notebook by accessing the plugin.

sp_ext.trace_type = 'Polynomial'
sp_ext.trace_order = 2
sp_ext.trace_window = 10
sp_ext.trace_peak_method = 'Gaussian'

To export and access the specreduce Trace object defined in the plugin, call export_trace():

trace = sp_ext.export_trace()

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

specviz2d.load_trace(my_trace, data_label="my trace")

or directly into the plugin as

sp_ext.import_trace(my_trace)
Background#

The background step of the plugin allows for creating background and background-subtracted images via 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 in the 2D spectrum viewer will change to show the center (dotted line) and edges (solid lines) of the background region(s). The 1D representation of the background will also be visualized in the 1D spectrum viewer (thin, solid line).

Backgrounds can either be created around the trace defined in the earlier Trace section or around a new, flat trace by selecting “Manual” in the Background Type dropdown.

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.

From the API#

Background parameters can be set from the notebook by accessing the plugin.

sp_ext.bg_type = 'TwoSided'
sp_ext.bg_separation = 8
sp_ext.bg_width = 6

To export and access the specreduce Background object defined in the plugin, call export_bg():

bg = sp_ext.export_bg()

To access the background image, background spectrum, or background-subtracted image as a Spectrum1D object, call export_bg_img(), export_bg_spectrum(), or export_bg_sub(), respectively.

To import the parameters from a specreduce Background object into the plugin, whether it’s new or was exported and modified in the notebook, call import_bg():

sp_ext.import_bg(bg)
Extract#

The extraction step of the plugin extracts a 1D spectrum from an input 2D spectrum via 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.

From the API#

Extraction parameters can be set from the notebook by accessing the plugin.

sp_ext.ext_type = 'Boxcar'
sp_ext.ext_width = 8

To export and access the specreduce extraction object defined in the plugin, call export_extract():

ext = sp_ext.export_extract()

To access the extracted spectrum as a Spectrum1D object, call export_extract_spectrum().

To import the parameters from a specreduce extraction object (either a new object, or an exported one modified in the notebook) into the plugin, call import_extract():

sp_ext.import_extract(ext)

Note

Horne extraction uses uncertainties on the input 2D spectrum. If the spectrum uncertainties are not explicitly assigned a type, they are assumed to be standard deviation uncertainties. If no uncertainty is provided, it is assumed to be an array of ones.

Gaussian Smooth#

See also

Gaussian Smooth

Specviz documentation on Gaussian Smooth.

Model Fitting#

See also

Model Fitting

Specviz documentation on Model Fitting.

Unit Conversion#

See also

Unit Conversion

Specviz documentation on Unit Conversion.

Line Lists#

Note

The line lists plugin is currently disabled if the 1D spectrum’s x-axis is in pixels.

See also

Line Lists

Specviz documentation on Line Lists.

Line Analysis#

Note

The line analysis plugin is currently disabled if the 1D spectrum’s x-axis is in pixels.

See also

Line Analysis

Specviz documentation on Line Analysis.

Export#

This plugin allows exporting the plot in a given viewer to various image formats.

Exporting Data From Specviz2D#
2D Spectra#

Images in the 2D spectrum viewer can be exported as specutils.Spectrum1D objects into the notebook (replace “2D data” with the label of the desired data):

specviz2d.get_data(data_label="2D data")
1D Spectra#

Similarly, the 1D spectrum data objects can be exported into the notebook:

specviz2d.get_data(data_label='1D data')

An instance of Specviz can also be accessed, which exposes some helper methods from Specviz:

specviz2d.specviz.get_spectra()

See also

Specviz: Export Data

Specviz documentation on exporting spectra.

Markers Table#

All mouseover information in the markers plugin can be exported to an astropy table by calling export_table() (see Accessing Plugin APIs).

mosviz_logo Mosviz#

Introductory video tour of the Mosviz configuration and its features

Mosviz is a quick-look analysis and visualization tool for multi-object spectroscopy (MOS). It is designed to work with pipeline output: spectra and associated images, or just with spectra. Mosviz is created to work with data from any telescope/instrument, but is built with the micro-shutter assembly (MSA) on the JWST/NIRSpec spectrograph and the JWST/NIRCam imager in mind. As such, Mosviz has some features specific to NIRSpec and NIRCam data.

The NIRSpec MSA can produce ~100 spectra per pointing. Many users will perform surveys with the MSA that will result in data sets containing many spectra. This tool allows users to inspect the locations of astronomical sources within shutters, the location of background apertures in the observed field, the quality of the 2D spectra, and the quality of the 1D extracted spectra. It also often involves simple interactive measurements of quantities such as wavelengths, velocities, line fluxes, widths.

Quickstart#

To load a sample NIRISS Nirspec Data Set into Mosviz in the standalone app, unzip the downloaded zip file and run:

jdaviz --layout=mosviz /path/to/mosviz_nirspec_data_0.3/level3

Or to load in a Jupyter notebook, see the MosvizExample notebook or MosvizNIRISSExample notebook.

Using Mosviz#
Importing Data into Mosviz#

Mosviz provides two different ways to load data:

Automatic Directory Loading#

Mosviz provides instrument-specific directory parsers for select instruments. At this time, Mosviz supports automatic parsing for the following instruments:

In a Jupyter context (notebook or Lab), you must specify the instrument with a directory as such:

from jdaviz import Mosviz
mosviz = Mosviz()
mosviz.load_data(directory="path/to/my/data", instrument="nirspec")
mosviz.show()

or for NIRISS:

mosviz.load_data(directory="path/to/my/data", instrument="niriss")

Similarly, an instrument keyword can be specified by the command line. For NIRSpec:

jdaviz --layout=mosviz /path/to/my/data --instrument=nirspec

and for NIRISS:

jdaviz --layout=mosviz /path/to/my/data --instrument=niriss

Specifying a data directory and an instrument are required to start Mosviz from the command line. If a directory is entered without specifying an instrument, Mosviz will raise an error.

JWST NIRSpec (levels 2 and 3)#

The NIRSpec parser expects a directory with either level 2 files:

  • *_i2d.fits : Cutout images (see below).

  • *_s2d.fits : Single file containing level 2 2D spectra for all objects.

  • *_x1d.fits : Single file containing level 2 1D spectra for all objects.

or level 3 files:

  • *_s2d.fits : N files containing level 3 2D spectra, where N is the number of objects.

  • *_x1d.fits : N files containing level 3 1D spectra, where N is the number of objects.

In either the level 2 or 3 case, the NIRSpec data directory may contain a sub-directory named images, cutouts, or mosviz_cutouts. This sub-directory should contain FITS files containing images corresponding to each target, which may be sourced from a non-JWST telescope. If it only contains a single image, the same image would be used for all the spectra.

JWST NIRISS#

The NIRISS parser expects a directory with the following types of files:

  • *_i2d.fits : Level 3 2D images from the calwebb_image3 imaging pipeline

  • *_cat.ecsv : Level 3 source catalog from the calwebb_image3 imaging pipeline (For best performance, it’s recommended that your directory only contain one.)

  • *_cal.fits : Level 2 2D spectra in vertical (R) and horizontal (C) orientations from the calwebb_spec2 spectroscopic pipeline (C spectra are shown first in 2D viewer by default.)

  • *_x1d.fits : Level 2 1D spectra in vertical (R) and horizontal (C) orientations from the calwebb_spec2 spectroscopic pipeline (C spectra are shown first in 1D viewer by default.)

JWST NIRCam#

The NIRCam parser expects *_cal.fits and *_x1d files in the same format as the NIRISS parser.

Manual Loading#

If an automatic parser is not provided yet for your data, Mosviz provides manual loading by specifying which files are which, and the associations between them. This is done by generating three lists containing the filenames for the 1D spectra, 2D spectra, and images in your dataset (if you are creating your own data products, please read the page Creating Jdaviz-readable Products). These three lists are taken as arguments by load_data(). The association between files is assumed to be the order of each list (e.g., the first object consists of the first filename specified in each list, the second target is the second in each list, and so forth).

Currently, manual loading is supported in the Jupyter context only.

An example is given below, where file_dir is a directory that contains all the files for the dataset to be loaded:

from jdaviz import Mosviz
mosviz = Mosviz()
spectra_1d = ['target1_1d.fits', 'target2_1d.fits']
spectra_2d = ['target1_2d.fits', 'target2_2d.fits']
images = ['target1_img.fits', 'target2_img.fits']
mosviz.load_data(spectra_1d=spectra_1d, spectra_2d=spectra_2d, images=images)
mosviz.show()

Alternatively, if you want all the spectra to share a single image (e.g., a mosaic):

from jdaviz import Mosviz
mosviz = Mosviz()
spectra_1d = ['target1_1d.fits', 'target2_1d.fits']
spectra_2d = ['target1_2d.fits', 'target2_2d.fits']
image = 'mymosaic.fits'
mosviz.load_data(spectra_1d=spectra_1d, spectra_2d=spectra_2d, images=image)
mosviz.show()
Displaying Spectra#

The spectra linked to the source selected in the table viewer will be automatically displayed in the viewers, with 2d spectra populating the top right viewer, and 1d spectra populating the viewer 2nd from top on the right.

See also

Display Spectra

Specviz documentation on displaying spectra.

The functionality of the Specviz API can be accessed in Mosviz via the specviz attribute, e.g., mosviz.specviz.get_spectra().

Pan/Zoom#

For an overview on general pan/zoom functionality, please see Pan/Zoom and Linked Pan/Zoom

Synchronous Spectral Pan/Zoom#

Mosviz assumes the 1D and 2D spectra objects share a relationship in spectral space. As a result, the 1D and 2D spectral viewers have their spectral axes (the horizontal x-axis) linked. As you pan and zoom in spectral space (horizontally) in either of the two spectral viewers, the other will follow, simultaneously panning and zooming by the same amounts.

Warning

If you pan too far away from the bounds of the dataset provided in the 1D or 2D spectral viewers, a warning will be displayed to notify the user. If you go too far, there is a risk of desynchronizing the two viewers.

Defining Spectral Regions#

For an overview on spectral regions, please see Defining Spectral Regions

Plot Settings#

Plot settings for the 1d spectrum viewer can be found in the Specviz section.

See also

Plot Settings

Specviz documentation on plot settings for a 1d spectrum viewer.

Display settings for the 2d spectrum viewer can be found in the Cubeviz section.

See also

Display Settings

Cubeviz documentation on display settings for an image viewer (2d spectrum viewer in this case).

Data Analysis Plugins#

The Mosviz data analysis plugins include operations on both 2D images and Spectrum1D one dimensional datasets. Plugins that are specific to 1D spectra are described in more detail under Specviz:Data Analysis Plugins. All plugins are accessed via the plugin icon in the upper right corner of the Mosviz application.

Metadata Viewer#

This plugin allows viewing of any metadata associated with the selected data.

If the data is loaded from multi-extension FITS that contains a primary header, you will also see a Show primary header toggle, when enabled, would display just the primary header metadata.

Export#

This plugin allows exporting the plot in a given viewer to various image formats.

Plot Options#

This plugin gives access to per-viewer and per-layer plotting options.

Subset Tools#

See also

Subset Tools

Imviz documentation describing the concept of subsets in Jdaviz.

Markers#

See also

Markers

Imviz documentation describing the markers plugin.

Gaussian Smooth#

Gaussian smoothing of a spectrum is described under Specviz:Data Analysis Plugins:Gaussian Smoothing.

See also

Gaussian Smooth

Specviz documentation on gaussian smoothing of 1D spectra.

Model Fitting#

The Model Fitting plugin is described in more detail by the Specviz:Data Analysis Plugins:Model Fitting documentation.

See also

Model Fitting

Specviz documentation on fitting spectral models.

Line Lists#

See also

Line Lists

Specviz documentation on line lists.

Redshift Slider#

Warning

Using the redshift slider with many active spectral lines causes performance issues. If the shifting of spectral lines lag behind the slider, try plotting less lines. You can deselect lines using, e.g., the “Erase All” button in the line lists UI.

As in Specviz, the Line Lists Plugin includes a slider to adjust the redshift or radial velocity. In Mosviz, this is applied to the current row in the table and is stored (and shown) in a column of the table.

See also

Setting Redshift/RV

Setting Redshift/RV from the Notebook in Mosviz.

Line Analysis#

See also

Line Analysis

Specviz documentation on line analysis.

Slit Overlay#

A slit can be added to the image viewer by opening the Slit Overlay plugin and clicking the Apply button. The Remove button can be used to remove a slit once it has been applied to the image viewer.

In order to plot a slit onto the image viewer, we need WCS information from an image and slit position from a 2D spectrum. The slit position is calculated using the S_REGION header extension value, located in the meta attribute of the Spectrum1D object that is active in the 2D spectrum viewer.

Setting Redshift/RV#

The Line Lists Plugin contains a redshift slider as well as the ability to view and set the redshift and/or radial velocity.

Additionally, the Line Analysis Plugin includes the capability to compute and assign the redshift based on the measured centroid of a line.

From the notebook#

In the notebook, the value of the Redshift column can be changed for all rows or a single row using update_column().

The 1D and 2D spectrum objects can be retrieved (with redshift optionally applied) using get_spectrum_1d() and get_spectrum_2d(), respectively.

See the notebooks/MosvizNIRISSExample.ipynb notebook in the repository to see examples of manipulating MOS Table data, including the redshift.

Using Mosviz in a Jupyter Notebook#

To initialize an instance of the Mosviz app in a Jupyter notebook, simply run the following code in a cell of the notebook:

from jdaviz import Mosviz
mosviz = Mosviz()
mosviz.show()

After running the code above, you can interact with the Mosviz application from subsequent notebook cells via the API methods attached to the Mosviz object, for example loading data into the app as described in Importing Data into Mosviz.

See also

Cubeviz data export

Cubeviz documentation on data exporting.

The Mosviz helper class can be used similarly to how Cubeviz is used in Exporting Data from Cubeviz. The viewers in Mosviz that can be used that way are image-viewer, spectrum-viewer, and spectrum-2d-viewer.

It is also possible to extract the contents of the table viewer using to_csv:

mosviz.to_csv(filename="MOS_data.csv", selected=False)

Which will save the data from the Mosviz table into the given CSV filename. If the selected keyword is set to True, only the checked rows in the table will be output. A previous CSV file of the same name can be overwritten by setting the overwrite keyword to True. The contents of table-viewer can also be extracted to a notebook cell by running to_table():

mosviz.to_table()

Accessing Plugin APIs#

Each plugin object is wrapped by a public user API which enables interacting with the plugin from the notebook directly. The plugin API object for each plugin is accessible through viz.plugins. For example:

plugin = viz.plugins['Plot Options']
plugin.open_in_tray()
plugin.show('popout')

Saving the State of Your Jdaviz Session#

While Jdaviz has no Save button, the various data products created within Jdaviz can be exported to the notebook and, ultimately, saved locally using standard Python write commands. This is the suggested workflow to ensure reproducibility in your analysis without having to retrace your steps in Jdaviz each time you run a notebook. We also encourage users to manually record steps in their Jupyter notebook (or anywhere of convenience) with any details that may be of interest when running Jdaviz.

Customizing Notebook Display Layout#

By default, calling show() will display your visualization tool inline in your notebook, that is the tool will show underneath the notebook cell it was called from:

from jdaviz import Imviz

imviz = Imviz()
imviz.show()
imviz.load_data('filename.fits')

The height of the application in the notebook can be changed by passing an integer specifying the height in pixels to the height argument of show, for example:

imviz.show(height=800)

You can additionally specify the location with the loc argument. For example, inline can be specified manually with:

imviz.show(loc='inline')
Detached Popout#

Jdaviz can also be displayed in a detached window, separate from your working Jupyter interface.

Note

Popups must be allowed in your browser to display properly.

The following shows jdaviz in a new popout window:

imviz.show(loc='popout')

To manually specify the anchor location, append the anchor to popout, separated by a colon:

imviz.show(loc='popout:window')

You can also popout to a new browser tab by specifying a tab anchor:

imviz.show(loc='popout:tab')
Sidecar (Jupyter Lab)#

In Jupyter Lab, sidecar provides additional methods to customize where to show the viewer in your workspace. The following shows jdaviz in the default sidecar location, to the right of the notebook:

imviz.show(loc='sidecar')

To manually specify the anchor location, append the anchor to sidecar, separated by a colon:

imviz.show(loc='sidecar:right')

Other anchors include: split-right, split-left, split-top, split-bottom, tab-before, tab-after, right. An up-to-date list can be found at jupyterlab-sidecar.

Sample Notebooks#

jdaviz is one tool that is part of STScI’s larger Data Analysis Tools Ecosystem.

These tools include three types of example Jupyter notebooks.

  1. Sample Jdaviz Notebooks that illustrate how to use Jdaviz and various API calls. These notebooks are located in the notebooks sub-directory of the git repository.

  2. Sample JDAT notebooks that illustrate likely science workflows with data obtained from the various JWST instruments. These notebook incorporate astropy and Jdaviz when possible.

  3. Sample JWST pipeline notebooks that illustrate how to run the JWST science calibration pipeline.

Creating Jdaviz-readable Products#

Spectroscopic data products (1D, 2D, and 3D) can be loaded in the different jdaviz configurations using essentially two methods, i.e., loading Spectrum1D objects or from FITS files. Here, we list a few ways in which data can be packaged to be easily loaded into a jdaviz configuration.

Data in a database#

If the data are stored in a database, we recommend storing a Spectrum1D object per entry. This would allow the user to query the data and visualize it in jdaviz with few lines of code; also see Providing scripts to load the data as Spectrum1D objects.

Data in FITS files#

If the data are stored as FITS files, we propose three options:

Using an available specutils loader#

Available loaders can be listed with the following commands:

from specutils import Spectrum1D
Spectrum1D.read.list_formats()

The majority are fairly specific to missions and instruments. Four formats are more generic and adaptable: ASCII, ECSV, tabular-fits, and wcs1d-fits. More information on how to create files that are readable by these loaders can be found on the specutils GitHub repository.

Creating a dedicated loader#

The specutils documentation on how to create a custom loader is available. We are working on the necessary documentation to prompt jdaviz to recognize a custom loader developed in specutils.

Providing scripts to load the data as Spectrum1D objects#

If none of the above is an acceptable option, the user can create the data products with their custom format and provide scripts or Jupyter Notebooks that show how to read the products and create Spectrum1D objects that can be read into jdaviz. More about how to create Spectrum1D objects for the 1D, 2D, and 3D cases can be found in the corresponding “Importing data” sections of the various configurations:

Known Issues#

You can report an issue to the Jdaviz GitHub issues.

Some currently known but unresolved common issues that users encounter are as follow in their respective categories. This list is not exhaustive, so please also consult existing Jdaviz GitHub issues as well if you are unable to find your issue here:

Installation#
On MacOS versions 10.13 and older, install fails due to scikit-image#

This can be fixed by reinstalling scikit-image:

pip uninstall scikit-image
conda install scikit-image

The reason for this issue is that prebuilt binaries for scikit-image don’t work on Mac versions of 10.13 or older and conda installs an older version of scikit-image that works with those versions. Another way to get the up-to-date scikit-image version is:

pip install -U --no-binary scikit-image scikit-image.

Although this solution takes much longer (~5 minutes) to install than the first solution.

On some platforms, install fails due to vispy#

The 0.6.4 version of vispy fails to build for some combinations of platform/OS and Python versions. vispy 0.6.5 has resolved this, but a workaround if you have an older version of vispy is to ensure you have a compatible version:

conda create -n jdaviz python=3.12
conda activate jdaviz
pip install vispy>=0.6.5
pip install jdaviz --no-cache-dir

See Issue #305 for updates on this topic.

On some platforms, install fails due to bottleneck#

In a conda environment, where numpy was installed using conda, installing jdaviz using pip will attempt to pull bottleneck from PyPI. This might result in bottleneck trying to build numpy from source and crash, stalling the installation altogether. When this happens, exit the installation, install bottleneck with conda, and try to install jdaviz again.

Application-wide#
Lab fails to start with IndexError#

In some environments, you occasionally might not able to start Jdaviz in Jupyter Lab due to this error:

IndexError: pop from an empty deque

This is an upstream issue at jupyterlab/jupyterlab#11934 that is not related to Jdaviz. The workaround is to find another environment where you do not see this error or use Jupyter Notebook instead.

Cubeviz#
Cubeviz sometimes fails to run from command line interface#

Running Cubeviz from the command line sometimes results in a failure to initialize the app in the browser due to a RuntimeError in tornado/ioloop.py. We are investigating, but in the meantime reinstalling fresh in a new conda environment may help. Alternatively, running Cubeviz in a Jupyter notebook instead of from the command line will circumvent the problem.

Spectrum does not appear when running on a Linux VM#

When running Jdaviz on a Linux virtual machine (VM), the spectrum may not appear in the spectrum viewer. This is a known bug in an underlying package. Until it is fixed, the workaround is to run the following in a Jupyter notebook cell before importing jdaviz:

from glue_jupyter.bqplot.profile import layer_artist
layer_artist.USE_GL = False
Collapse and Moment Maps: Spectral bounds do not match Region selection#

When trying to do a second collapse with the same spectral region, but with resized bounds: change to Region=None, resize the region, then reselect Region 1, the region bounds are correct. However, applying Collapse again, it errors out and the image viewer that contained the initial collapse goes blank.

Cube viewer contrast changes when collapsing Jupyter scroll window#

In order to see the full Cubeviz app in a Jupyter notebook, one can click on the side of the cell output to collapse or expand the scrollable window. This has the unintended consequence of changing the contrast of the image displayed in the Cubeviz cube viewer.

Imviz#
add_markers may not show markers#

In some OS/browser combinations, imviz.add_markers(...) might take a few tries to show the markers, or not at all. This is a known bug reported in glue-viz/glue-jupyter#243 . If you encounter this, try a different OS/browser combo.

Specviz#
Spectrum does not appear when running on a Linux VM#

See the identically named issue in Cubeviz.

Line List Plugin redshift and radial velocity do not roundtrip to full precision#

Giving a redshift value will report a converted radial velocity, which if entered manually will not convert to the exact same redshift value. Note that the redshift value is always treated as the true value and used when plotting lines, etc.

JWST Instrument Modes in Jdaviz#

JWST Modes#

This tool is designed with instrument modes from the James Webb Space Telescope (JWST) in mind, but the tool should be flexible enough to read in data from many astronomical telescopes. The table below summarizes Jdaviz file support specific to JWST instrument modes.

NIRSpec#

JWST/NIRSpec Instrument Modes in Jdaviz#

Template Mode

File Type

Pipeline Level

Primary Configuration

MOS

S2D

2b,3

Mosviz

X1D

2b,3

Specviz

IFU

S3D

2b,3

Cubeviz

X1D

2b,3

Specviz

FS

S2D

2b,3

Specviz2d

X1D

2b,3

Specviz

BOTS

X1DINTS

No Support

NIRISS#

JWST/NIRISS Instrument Modes in Jdaviz#

Template Mode

File Type

Pipeline Level

Primary Configuration

IMAGING

I2D

2b,3

Imviz

WFSS

X1D

2b

Specviz

AMI

AMINORM

No Support

SOSS

X1DINTS

No Support

NIRCam#

JWST/NIRCam Instrument Modes in Jdaviz#

Template Mode

File Type

Pipeline Level

Primary Configuration

Imaging

I2D

2b,3

Imviz

Coronagraphic Imaging

I2D

2b,3

Imviz

WFSS

X1D

2b

Specviz

Grism TSO

X1DINTS

No Support

MIRI#

JWST/MIRI Instrument Modes in Jdaviz#

Template Mode

File Type

Pipeline Level

Primary Configuration

Imaging

I2D

2b,3

Imviz

Coronagraphic Imaging

I2D

2b,3

Imviz

LRS-slit

S2D

2b,3

Specviz2d

X1D

2b,3

Specviz

LRS-slitless

X1DINTS

No Support

MRS

S3D

2b,3

Cubeviz

X1D

2b, 3

Specviz

Development Guide#

Developers#

Developer Guide#

Here is some documentation specific for developers.

Package Release Instructions#

This document outlines the steps for releasing a versioned Jdaviz package to PyPI. Currently, these do not cover submitting package updates to other distribution outlets, such as conda-forge.

This process currently requires you (the release manager) to have sufficient GitHub permissions to tag, push, and create a GitHub release on Jdaviz repository. These instructions assume that the origin remote points to your personal fork, and that upstream points to the STScI repository.

It is recommended that you lock the main branch after the “feature freeze” for the release and only unlock it when release is out on PyPI. Any urgent pull request that needs to go in after the freeze needs your blessing. A lock can be as simple as bumping the “reviews required” protection rule for the main branch to a very high number; Any rule that will prevent co-maintainers from merging pull requests without your blessing would do.

If you deem it necessary, you may choose to release a Release Candidate (RC) first before the actual release. In that case, instead of “vX.Y.Z”, it would be “vX.YrcN” (also see PEP 440).

Note

These instructions are adapted from the Astropy package template releasing instructions. Replace “vX.Y.Z” with the actual version tag of the release you are about to make.

Choose your adventure:

Releasing a minor or major version#

The automated release infrastructure has proven to be reliable for a good number of releases now, so we’ve been using this faster version as the default release procedure. The longer procedure we previously used is still available in the The old, long way section.

You can do a release from your fork directly without a clean code check-out.

  1. Ensure CI on Actions for main and RTD build for latest are passing.

  2. Lock down the main branch of the repository by setting the branch protection rule for main to some high number required to merge, so that more PRs don’t get merged while you’re releasing.

  3. Create a new local branch and make sure you have updated tags too. Note that the “x” here should actually be the letter “x”, whereas the upper case “X” and “Y” should be replace by your major and minor version numbers:

git fetch upstream main
git fetch upstream --tags
git checkout upstream/main -b vX.Y.x
  1. Update the CHANGES.rst file to make sure that all the user-facing changes are listed, and update the release date from unreleased to current date in the yyyy-mm-dd format. Remove any empty subsections.

    NOTE: You may encounter the case where there is a populated bugfix section below the current feature release section, but this bugfix release is being skipped in favor of a major release. If this happens, you will need to move those entries to the appropriate location(s) in the newest ‘released’ section, and remove that bugfix section since that release is being skipped.

  2. Update the CITATION.cff file’s date-released and version fields. If there are new contributors to the project, add them in the authors section.

  3. Do not forget to commit your changes from the last two steps:

git add CHANGES.rst
git add CITATION.cff
git commit -m "Preparing release vX.Y.0"
  1. Push the vX.Y.x branch to upstream. Make sure the CI passes. If any of the CI fails, abandon this way. Stop here; do not continue! Otherwise, go to the next step.

  2. Go to Releases on GitHub and create a new GitHub release targeting the new branch you created (not main!), and give it a new vX.Y.Z tag (do not choose any existing tags). Copy the relevant section from CHANGES.rst into the release notes section and clean up any formatting problems.

  3. The most important step: Click the Publish Release button!

  4. Check Release on Actions to make sure that the new GitHub release triggered PyPI upload successfully. Also check that files on PyPI contain both the source tarball and the wheel for that release.

  5. Check RTD builds to make sure that documentation built successfully for both latest and the new vX.Y.Z tag.

  6. Check Zenodo page for Jdaviz. It should have picked up the GitHub Release automatically.

  7. The release is basically done, but now you have to set it up for the next release cycle. In your release branch, add a new section above the current release section for the next bugfix release and push it to the new release branch:

    A.B.1 (unreleased)
    ==================
    
    Bug Fixes
    ---------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
  8. Checkout main and update CHANGES.rst and CITATIONS.cff directly in that branch using your admin power. If you do not have sufficient access to do that, you will have to update it via a pull request from your fork. Make sure the section for the version just released matches the finalized change log from the release branch you created, and add a new section to the top of CHANGES.rst as follows, replacing A.C with the next non-bugfix version, and A.B with the version you just released:

    A.C (unreleased)
    ================
    
    New Features
    ------------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    API Changes
    -----------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    Bug Fixes
    ---------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    Other Changes and Additions
    ---------------------------
    
    A.B.1 (unreleased)
    ==================
    
    Bug Fixes
    ---------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
  9. Commit your changes of the, uh, change log with a message, “Back to development: A.C.dev” and push directly to main.

  10. For this commit, if you are doing a “major” release, also do this so setuptools-scm is able to report the dev version properly. This is needed because it cannot grab the new release tag from a release branch:

git tag -a vA.C.dev -m "Back to development: A.C.dev"
git push upstream vA.C.dev
  1. Follow procedures for Milestones bookkeeping and Labels bookkeeping.

  2. For your own sanity unrelated to the release, grab the new tag for your fork:

git fetch upstream --tags

Congratulations, you have just released a new version of Jdaviz!

Releasing a bugfix version#

Note

Make sure all necessary backports to vX.Y.x are done before releasing. Most should have been automatically backported. If you need to manually backport something still, see Manual backport.

The procedure for a bugfix release is a little different from a feature release - you will be releasing from an existing release branch, and will also need to do some cleanup on the main branch. In the following, X and Y refer to the minor release for which you’re doing a bugfix release. For example, if you are releasing v3.5.2, replace all instances of vX.Y.x with v3.5.x.

  1. Lock down the vX.Y.x branch of the repository by setting the branch protection rule for v*.x to some high number required to merge, so that more PRs don’t get merged while you’re releasing.

  2. Review the appropriate Milestone to see which PRs should be released in this version, and double check that any open backport PRs intended for this release have been merged.

  3. Checkout the vX.Y.x branch corresponding to the last feature release.

  4. The CHANGES.rst file should have all of the bug fixes to be released. Delete the unreleased feature version section at the top of the changelog if it exists and update the release date of the bugfix release section from unreleased to current date in the yyyy-mm-dd format. Remove any empty subsections.

  5. Update the CITATION.cff file’s date-released and version fields. If there are new contributors to the project, add them in the authors section.

  6. Do not forget to commit your changes from the last two steps:

git add CHANGES.rst
git add CITATION.cff
git commit -m "Preparing release vX.Y.Z"
  1. Push the vX.Y.x branch to upstream. Make sure the CI passes. If any of the CI fails, abandon this way. Stop here; do not continue! Otherwise, go to the next step.

  2. Go to Releases on GitHub and create a new GitHub release targeting the release branch vX.Y.x (not main!), and give it a new vX.Y.Z tag (do not choose any existing tags). Copy the relevant section from CHANGES.rst into the release notes section and clean up any formatting problems.

  3. The most important step: Click the Publish Release button!

  4. Check Release on Actions to make sure that the new GitHub release triggered PyPI upload successfully. Also check that files on PyPI contain both the source tarball and the wheel for that release.

  5. Check RTD builds to make sure that documentation built successfully for both latest and the new vX.Y.Z tag.

  6. Check Zenodo page for Jdaviz. It should have picked up the GitHub Release automatically.

  7. The release is basically done, but now you have to set up the main branch for the next release cycle. Checkout the main branch and update CHANGES.rst using your admin power. If you do not have sufficient access to do that, you will have to update it via a pull request from your fork. Make sure the section for the version just released matches the finalized change log from the release branch (be sure to change unreleased to the appropriate date), and add a new bugfix release section below the next feature release section as follows, replacing X.Y.Z with the next minor release number. For example, if you just released 3.0.2, a section for 3.0.3 would go below the section for 3.1:

    X.Y.Z (unreleased)
    ==================
    
    Bug Fixes
    ---------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
  8. Commit your changes of the, uh, change log with a message, “Back to development: A.B.dev”

  9. Finally, you will need to set up the vX.Y.x branch for the next (potential) bugfix release. To do this (either through a direct commit using admin power, or via pull request to vX.Y.x), add a new bugfix section to the top of the change log. For example, if the bugfix release you just made was 3.6.2, add a 3.6.3 (unreleased) section (see step 7, but no need for a feature release section). Commit these changes with a message along the lines of “Back to development, vX.Y.x”.

  10. Follow procedures for Milestones bookkeeping.

  11. For your own sanity unrelated to the release, grab the new tag for your fork:

    git fetch upstream --tags
    

Congratulations, you have just released a new version of Jdaviz!

Milestones bookkeeping#
  1. Go to Milestones.

  2. Create a new milestone for the next release and the next bugfix release, if doing a feature release, or for just the next bugfix release if you just did one. You do not need to fill in the description and due date fields.

  3. For the milestone of this release, if there are any open issues or pull requests still milestoned to it, move their milestones to the next feature or bugfix milestone as appropriate.

  4. Make sure the milestone of this release ends up with “0 open” and then close it.

  5. Remind the other devs of the open pull requests with milestone moved that they will need to move their change log entries to the new release section that you have created in CHANGES.rst during the release process.

Labels bookkeeping#

This is only applicable if you are doing a new branched release. In the instructions below, A.B is the old release and A.C is the new release:

  1. Go to Labels.

  2. Find the old backport-vA.B.x label. Click its “Edit” button and add :zzz: in front of it. This would send it all the way to the end of labels listing and indicate that it has been retired from usage.

  3. Click “New label” (big green button on top right). Enter backport-vA.C.x as the label name, on-merge: backport to vA.C.x as the description, and #5319E7 as the color. Then click “Create label”.

Going forward, any PR that needs backporting to the vA.C.x branch can have this label applied before merge to trigger the auto-backport bot on merge. For more info on the bot, see https://meeseeksbox.github.io/ .

Manual backport#

Situations where a pull request might need to be manually backported after being merged into main branch:

  • Auto-backport failed.

  • Maintainer forgot to apply relevant label to trigger auto-backport (see Labels bookkeeping) before merging the pull request.

To manually backport pull request NNNN to a vX.Y.x branch; abcdef should be replaced by the actual merge commit hash of that pull request that you can copy from main branch history:

git fetch upstream vX.Y.x
git checkout upstream/vX.Y.x -b backport-of-pr-NNNN-on-vX.Y.x
git cherry-pick -x -m1 abcdef

You will likely have some merge/cherry-pick conflict here, fix them and commit. Then push the branch out to your fork:

git commit -am "Backport PR #NNNN: Original PR title"
git push origin backport-of-pr-NNNN-on-vX.Y.x

Create a backport pull request from that backport-of-pr-NNNN-on-vX.Y.x branch you just pushed against upstream/vX.Y.x (not upstream/main). Title it:

Backport PR #NNNN on branch vX.Y.x (Original PR title)

Also apply the correct label(s) and milestone. If the original pull request has a Still Needs Manual Backport label attached to it, you can also remove that label now.

The old, long way#

Note

This section is kept mainly for historical purposes, and to show how many of the things that are now automated can be done manually. Note that it is not up-to-date with the change to a branched release strategy.

This way is recommended if you are new to the process or wish to manually run some automated steps locally. It takes longer but has a smaller risk factor. It also gives you a chance to test things out on a machine that is different from the one used for deployment on GitHub Actions.

It is recommended for you to have a clean checkout of the Jdaviz repository (not the fork), especially if you also do a lot of development work. You can create a clean checkout as follows (requires SSH setup):

mkdir jdaviz_for_release
cd jdaviz_for_release
git clone git@github.com:spacetelescope/jdaviz.git .
git fetch origin --tags
  1. Ensure CI on Actions for main and RTD build for latest are passing.

  2. Update the CHANGES.rst file to make sure that all the user-facing changes are listed, and update the release date from unreleased to current date in the yyyy-mm-dd format. Remove any empty subsections.

  3. Update the CITATION.cff file’s date-released and version fields. If there are new contributors to the project, add them in the authors section. Do not forget to commit your changes from the last two steps:

git add CHANGES.rst
git add CITATION.cff
git commit -m "Preparing release vX.Y.Z"
  1. Remove any untracked files. (WARNING: This will permanently remove any files that have not been previously committed, so make sure that you don’t need to keep any of these files.) This step is not needed if you have a fresh code checkout, but does not hurt either:

git clean -xdf
  1. Tag the version you are about to release and sign it (optional but it is a good practice). Signing requires GPG setup:

git tag -s "vX.Y.Z" -m "Tagging version vX.Y.Z"
  1. Generate the package distribution files by first making sure the following packages are installed and up-to-date:

pip install build twine -U
  1. Creating the source distribution and its wheel with:

python -m build --sdist --wheel .
  1. Do a preliminary check of the generated files:

python -m twine check --strict dist/*
  1. Fix any errors or warnings reported. Skip this step if not applicable.

  2. Run unit tests using package you are about to release. It is recommended that you do this in a fresh Python environment. The following example uses conda, so if you use a non-conda Python environment manager, replace the conda commands accordingly:

conda create -n testenv python=3.12
conda activate testenv
pip install pytest pytest-astropy pytest-tornasync dist/*.whl
cd ..
python -c "import jdaviz; jdaviz.test(remote_data=True)"
cd jdaviz_for_release
  1. Fix any test failures. Skip this step if not applicable.

  2. Depending on the severity of the fixes above, you might need to submit the fixes as separate PRs and abandon the release. If that is the case, stop here, delete the vX.Y.Z tag, and start again from above when those fixes are in the main branch. If there are no fixes (yay) or if you can justify pushing the fixes as part of this release (not recommended), continue on.

  3. Remove files generated by above steps:

git clean -xdf
  1. Make sure code checkout state is clean and history is correct. If not, fix accordingly:

git status
git log
  1. The release is basically done locally, but now you have to set it up for the next release cycle. Add a new section to the top of CHANGES.rst as follows, replacing A.B with the next non-bugfix version:

    A.B (unreleased)
    ================
    
    New Features
    ------------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    API Changes
    -----------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    Bug Fixes
    ---------
    
    Cubeviz
    ^^^^^^^
    
    Imviz
    ^^^^^
    
    Mosviz
    ^^^^^^
    
    Specviz
    ^^^^^^^
    
    Specviz2d
    ^^^^^^^^^
    
    Other Changes and Additions
    ---------------------------
    
  2. Commit your changes of the, uh, change log:

git add CHANGES.rst
git commit -m "Back to development: A.B.dev"
  1. For this commit, if you are doing a “major” release, also do this so setuptools-scm is able to report the dev version properly. This is needed because it cannot grab the new release tag from a release branch:

git tag -a vA.B.dev -m "Back to development: A.B.dev"
  1. Push out the updated code and tag. If applicable, change origin to point to the remote that points to the repository being released:

git push origin main
git push origin vX.Y.Z
git push origin vA.B.dev
  1. Go to Releases on GitHub and create a new GitHub release off the new vX.Y.Z tag.

  2. Check Release on Actions to make sure that the new GitHub release triggered PyPI upload successfully. Also check that files on PyPI contain both the source tarball and the wheel for that release.

  3. Check RTD builds to make sure that documentation built successfully for both latest and the new vX.Y.Z tag.

  4. Check Zenodo page for Jdaviz. It should have picked up the GitHub Release automatically.

  5. Follow procedures for Milestones bookkeeping.

Congratulations, you have just released a new version of Jdaviz!

Jdaviz Design and Infrastructure#

Note

At the time of writing, Jdaviz was still in heavy development. If you notice that this page has fallen behind, please report an issue to the Jdaviz GitHub issues.

This section outlines the top-level structure of Jdaviz. At the highest level, Jdaviz layers different, sometimes changing technologies in the Jupyter platform to do its visualization, and therefore provides a framework for these technologies to work together. This document describes that framework, as well as the high-level sets of components needed for the Jdaviz use cases; it lists the layers of the Jdaviz framework in essentially the order in which they contact users in a typical visualization-heavy workflow. An overview of the layers is in this diagram, and each is described in more details below:

Jdaviz design and infrastructure chart.

This figure illustrates the basics of Jdaviz design and infrastructure. The top layer contains user-facing applications and supported interfaces. The middle layer encapsulates its component widgets and the visualization libraries involved. The bottom layer consists of low-level data analysis and I/O libraries.#

Jdaviz: Interfaces and Applications#
Interfaces#

“Interfaces” are the tools the user is using to access the analysis tools. The word “platform” might at first seem more applicable, but in this case all of the interfaces are using Jupyter as the platform, to ensure a consistent look-and-feel and a single platform for which to target the tools. The interfaces are then specific interfaces through which users access this platform. The target interfaces are:

  • Notebook/Lab: While the actual app the user is running may be either JupyterLab or the “classic” Jupyter Notebook, the interface idiom is similar - a relatively linear notebook-style workflow. This is the most flexible interface as it allows the user to implement their own code free-form in the notebook and run it with cells using Jdaviz tools. Hence this layer particularly emphasizes modularity and flexibility.

  • Desktop: This interface is meant to behave like a more traditional “desktop app”, i.e., a window with a fixed set of functionality and a particular layout for a specific set of scientific use cases. This interface is accessed via a Voilà wrapper that loads the same machinery as the other interfaces but presents the outputs of notebook “cells” as the only view. This trades the flexibility of the notebook interface for a consistent and reproducible layout and simpler interface without the distraction of the notebook and associated code.

  • MAST: This interface is used by the Mikulski Archive for Space Telescopes (MAST), which embeds Jdaviz applications inside existing websites. This provides the capabilities of the Jdaviz tools in other websites, while providing the sites the freedom to be designed and laid out independently from the visualization tool framework. While this even further restricts the functionality, it provides maximum flexibility in embedding.

Each of these interfaces uses a common set of applications implemented in Python and leveraging ipywidgets as the communication layer between Python and the JavaScript-level layout, rendering, and interactivity libraries. Hence the following layers are primarily implemented in Python, but utilize tools like ipyvuetify and ipygoldenlayout to allow the Python code to interact with the JavaScript implementations at the interface level.

Applications#

The next layer is the “application” layer for visualization. These applications in and of themselves do not implement significant functionality, but are particular layouts that combine the lower layers to accomplish specific visualization tasks. They have particular science goals that are then mainly reflected in the capabilities of the lower layers (widgets), but the functionality in them are connected together to solve those goals in the applications. The desktop app and embedded website interfaces will typically wrap exactly one of these applications, while the notebook/lab’s additional flexibility means it may include multiple applications, or a mix of applications and individual widgets.

Specific target applications include:

  • Specviz: A view into a single astronomical spectrum. It provides a UI to view the spectrum, as well as perform common scientific operations like marking spectral regions for further analysis (e.g., in a notebook), subtracting continua, measuring and fitting spectral lines, etc.

  • Mosviz: A view into many astronomical spectra, typically the output of a multi-object spectrograph (e.g., JWST NIRSpec). It provides capabilities for individual spectra like Specviz, but for multiple spectra at a time along with additional contextual information like on-sky views of the spectrograph slit.

  • Cubeviz: A view of spectroscopic data cubes (e.g., from JWST MIRI), along with 1D spectra extracted from the cube. In addition to common visualization capabilities like viewing slices or averages in image or wavelength space, the application will provide some standard manipulations like smoothing, moment maps, parallelized line fitting, etc.

  • Imviz: An image-viewer for 2D images leveraging the same machinery as the other applications. While this application is not intended to encapsulate a complete range of astronomical imaging-based workflows, it enables quick-look style visualization of images in a way that is compatible with the rest of the Jdaviz framework.

Application Engine#

The applications are driven by a shared layer that connects the “high-level” layers to the “low-level” layers, as discussed below. The application engine manages this shared layer. Or more concretely, the application engine is the Python-level object that can be accessed by the user in any of the interfaces to interact with a particular application. It contains several sub-pieces to achieve this goal. The most directly-used portion of this is the layout configuration management: Jdaviz applications specify the UI layout they use via this part of the application engine. The application engine then constructs the layout using glue-jupyter, ipywidgets, and other layout libraries like ipyvuetify. The application engine also is responsible for managing application-level events and data. This is done via the built-in functionality of the glue-core library, so the application engine also provides the interface for registering new functionality (both UI and data/processing) via glue-core’s registries.

Note that most of the application engine implementation belongs in glue-jupyter or glue-core, as it is not unique to Jdaviz (or even astronomy). However, Jdaviz has customized it for specific use cases, though some of the implementations might be moved upstream as Jdaviz matures, especially if they are useful beyond Jdaviz.

Visualization: Component Widgets#

The “component widgets” layer is the first of the “low-level” layers, i.e., the layers that actually implement specific visualization and analysis functionality. These widgets are self-contained and in general are meant to be composed in applications. However, for the notebook/lab interface, component widgets can and should be used directly by users for specialized scientific workflows. Component widgets in principle can be developed in any framework that can be exposed as an ipywidgets widget, although currently the plan is that most will be glue-jupyter viewers (using bqplot backend) combined with ipyvuetify layouts (that builds on Vue.js). As with the application engine, the general goal is to push any functionality necessary for these widgets upstream and not confine them to Jdaviz, but with allowances that some customization may be needed for Jdaviz-specific elements.

Note

GlueViz in the diagram above encapsulates all the libraries tied to the glue visualization ecosystem. They include but not limited to glue-core, glue-jupyter, glue-astronomy, and bqplot-image-gl. Due to the complexity of Jdaviz’s dependency tree, we will not mention all of them in this section.

Known component widgets for the target applications include:

  • Spectrum viewer: A widget that shows a 1D astronomical data set, primarily aimed at astronomical spectra. Interactivity includes panning, zooming, and region marking.

  • Image viewer: A widget that shows an astronomical image, along with its on-sky coordinates when WCS are available. Interactivity includes panning, zooming, stretch (contrast and scale), and cut values.

  • Cube slicer: A widget for displaying slices or similar aggregate operations on spectroscopic data cubes. While similar to the image viewer in appearance and interactive capabilities, the core difference is that the main data object is expected to be a data cube rather than a 2D image, and this is reflected in additional aggregation/slicing operations.

  • Table viewer: A widget to show tabular datasets like astropy.table.Table objects. Primarily meant to be combined with other viewers to examine the complete set of properties from a selection made in another viewer. Interactivity focuses on sorting and selection of specific rows (to then be highlighted in other viewers or interacted with in notebook/lab).

In addition to the component widgets above, there are also plugins that go with them to provide the necessary user interactions. Each plugin is specialized to do one thing, e.g., a “model fitting” plugin to allow users to fit astropy models to spectra.

Data Analysis and I/O Libraries#

The above layers are focused primarily on visualization. All actual operations and analysis tasks to be applied to visualized astronomical dataset are to be implemented in the respective Python libraries. It is important to note that these libraries are independent efforts from Jdaviz, and can therefore be used in whole, part, or not at all with the Jdaviz tools. This allows a full range of workflows, while also maintaining transparency to scientific users in regards to exactly how an operation in the Jdaviz tools actually works; i.e., they can at any time use the library directly instead of accessing it through Jdaviz.

Some common libraries include (this list is not exhaustive):

Note that those libraries themselves depend on the wider scientific Python ecosystem, so the list and the diagram above do not fully cover all of Jdaviz’s dependencies, but are the primary “top-level” data analysis or I/O libraries that most users are likely to focus on to complement or extend their Jdaviz workflows.

Note

In the diagram above, optional dependencies of Jdaviz have dotted lines. Optional dependencies mean they are only required for certain Jdaviz workflows and are not explicitly installed by default when you install Jdaviz.

Glupyter Framework Overview#

The glue-jupyter (“glupyter”) package supports interacting with and visualizing data within the Jupyter environment using core elements from the glue python package. It is distinct because unlike the more prominent glue package, glupyter does not leverage Qt as the front-end GUI library. Instead, glupyter maintains the separation between the data model (e.g., the core elements from glue that are not dependent on the front-end library), and the view of the data (in this case, web-based tooling provided by Jupyter).

Glupyter implements a base JupyterApplication object through which users can manage their data, create viewers, and add links between data sets. The data management and linking are controlled separate from the viewers in that changes made directly to the data state propagate to the UI – that is, the UI does not contain any state, which allows the application to be easily controlled from code. The viewers themselves are based on the IPyWidget package which allows the creation of widgets that can be used and interacted with in python, but rendered in a browser environment.

There are two distinct use cases for the glupyter environment:

  1. As a means to procedurally interact with pieces of a user’s workflow in addition to their work in e.g., a Jupyter Notebook.

  2. To provide users a web-based GUI to interact with and visualize their data while hiding the Python code, e.g., a standalone web application.

These two use cases describe a Python-first and GUI-first approach, respectively. This document will focus on detailing the design of the GUI-first approach, depicted in the following diagram.

Note

The .xml file in the img directory can be used to edit the diagram using applications like, e.g., draw.io.

_images/glue-jupyter_diagram.png
General user interface design#

The general user interface is a parallel design to the Qt desktop interface. It is meant to be the standard scaffolding supporting the display of the individual viewers, and implementation of data management functions and user plugins in much the same way that the Qt desktop version does.

The implementation leverages three primary packages:

  1. glue-jupyter: handles the data and state management, including the plugin infrastructure that provides the registry of available viewers, analysis functions, etc.

  2. ipyvuetify: provides the UI widgets for composing the web-based front-end.

  3. ipygoldenlayout: an additional widget that supports tabbing and docking the displayed viewers.

Widget design#

There are two potential approaches to designing widgets using the ipyvuetify paradigm: composing everything in the python widget subclass as a collection of python ipyvuetify components; or break the state of the widget from its view and implement the latter as template file.

The first approach, while conceptually easier to understand, has a few shortcomings. Chief of which is the fact that the view logic is jumbled up with the state of the widget. That is, we are composing the visual representation of the widget, defining the viewer logic, and defining its state all during initialization. This is both extremely verbose – as the nested nature of the Vuetify library means many of the intermediate widget classes (e.g., Layout, Container, Row, etc) need to be defined as instance attributes – and, perhaps more severe, makes it more difficult to design reactive UI behavior that responds to state changes in the widget classes automatically. This means that we must constantly interact with the UI widgets to change their state directly instead of simply having the UI respond to state changes in the custom widget class. Fundamentally, this approach means that in addition to the state of the custom widget (e.g., Toolbar), we must also be aware of the state of each individual widget that composes it. Put another way, there’s no central source of truth for the state of the custom widget as each element may contain some kind of stateful information about itself.

An alternative design, and the one used for the Jdaviz tools, is to have each widget implemented as a VuetifyTemplate object. In this way, custom widgets are defined as ipywidget-like elements whose visual representation is described by a Vuetify template. The template composes the visual representation of the custom widget using the Vue formalism, while the state is implemented as traitlets on the custom widget class. The template reads and responds to state and state changes on the custom widget, and the custom widget need not know or care about how that state is being represented (i.e. the only state is that of the custom widget).

With this approach in hand, all widgets in the glupyter GUI are composed of two files: the python file declaring the widget class (e.g., Toolbar), and the .vue file containing the template describing how the widget is to be rendered using components from the Vuetify library in the nominal Vue framework. In this way, there is a clear separation between the state of each widget (contained in the python file) and the view of that state (contained in the Vuetify file). Below is an example of what such a widget might looking like:

<template>
  <v-toolbar>
    <v-toolbar-side-icon></v-toolbar-side-icon>
    <v-toolbar-title>Title</v-toolbar-title>
    <v-spacer></v-spacer>
    <v-toolbar-items class="hidden-sm-and-down">
      <v-btn flat>Link One</v-btn>
      <v-btn flat>Link Two</v-btn>
      <v-btn flat>Link Three</v-btn>
    </v-toolbar-items>
  </v-toolbar>
</template>
with open(os.path.join(os.path.dirname(__file__), "toolbar.vue")) as f:
    TEMPLATE = f.read()


class Toolbar(VuetifyTemplate):
    template = Unicode(TEMPLATE).tag(sync=True)

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

The state of the widget is contained in attributes on the python class which allows them to be referenced in the Vuetify template. Notice in the example below that the v-btn instances simply respond to the state of the Toolbar widget’s button_names attribute, and the Toolbar class could know nothing about how that state is being represented.

<v-toolbar-items class="hidden-sm-and-down">
  <v-btn flat v-for="name in button_names">{{ name }}</v-btn>
</v-toolbar-items>
class Toolbar(VuetifyTemplate):
    template = Unicode(TEMPLATE).tag(sync=True)
    button_names = List(['One', 'Two', 'Three']).tag(sync=True)

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

The design of the interface can be broken down into three main areas: the toolbar, the navigation drawer, and the dock area. Each of these areas represents a single primary widget in the web-based application built using ipyvuetify, unified in the Application class.

Widget communication#

There are three fundamental forms of communication between widgets:

  1. direction communication using the observer pattern using Traitlets,

  2. global communication using the centralized event hub provided by glue,

  3. and callback properties on glue objects.

Direct messaging#

Because the software stack utilizes the ipywidgets package, attributes on defined widget classes (e.g., button_names on the Toolbar widget in the example above) are implemented as traitlets, which can be observed for changes. In order to register callbacks in response to changes to attributes defined on widget classes, interested parties must have a direct reference to the widget instance. Traitlets are unique in that they can be referenced in the front-end Vue code, so changing a traitlet-defined attribute of a class will propagate that change to any front-end code that references the value.

For example, if we consider that the Toolbar class above is implemented as part of a broader Application, we can respond to changes in the button_names traitlet by setting a callback function in the observe method of the Toolbar widget:

class Application(VuetifyTemplate):
    template = Unicode("""
        <template>
            <custom-toolbar></custom-toolbar>
        </template>
        """).tag(sync=True)

    def __init__(self, *args, **kwargs):
        # Associate the `custom-toolbar` element with the `Toolbar` class
        kwargs.set_default('components', {}).update({'custom-toolbar': Toolbar()})
        super().__init__(*args, **kwargs)

        self.toolbar = self.components['custom-toolbar']

        # This sets up the child-to-parent behavior
        self.toolbar.observe(self.on_button_names_changed, names='button_names')

        # Here we take advantage of the way traitlets work

    def on_button_names_changed(self, *args, **kwargs):
        print("The list of button names has been changed.")

This type of direct child-to-parent (i.e. the parent is responding to changes on the child) communication compliments the direct parent-to-child communication (i.e. the parent passing data to the child). However, this does not solve the application-level issue of multiple components, conceivably several levels deep, trying to interact with and pass data to each other. In this case, we decouple the widgets from each other and instead have them interact with a central, application-level communication hub through message objects.

Global event handing#

Communication between widgets that do not have a direct reference to each other is handled using the Hub class of the glue-core package (a dependency of glue-jupyter). The hub implements the publish/subscribe paradigm wherein widgets subscribe to particular messages on the hub and are notified whenever those messages are published by any part of the UI. This system allows us to break hard dependencies between widgets in the UI that require passing references around and to develop widgets independently.

The Jdaviz package includes a base class that can be used for adding widgets that would need to communicate through global events. This is is the TemplateMixin class and allows passing glue session objects to widgets upon their instantiation. The glue session contains the Hub object available to the application and it, along with other useful data objects, are easily accessible through the TemplateMixin.

Using the glue event framework is covered in great detail in the glue documentation. The code snippet gives an example of how an event listener may be implemented inside a widget:

from jdaviz.core.template_mixin import TemplateMixin
from glue.core.message import DataMessage

class TestWidget(TemplateMixin):
    text = Unicode("No messages...").tag(sync=True)
    template = Unicode("""
    <v-card>
        <v-card-text>
            <p>{{ text }}</p>
        </v-card-text>
    </v-card>
    """).tag(sync=True)

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

        self.hub.subscribe(self, DataMessage,
                           handler=self.on_data_message_received)

    def on_data_message_received(self, message):
        self.text = "Received data message!"
Glue callback properties#

In cases where traitlets are not appropriate (e.g., where some python object is not a strict inherited class of HasTraitlet), glue’s CallbackProperty s can be used in conjunction with a State class object. It should be noted, however, that glue callback properties do not interact with the front-end UI as in the case using traitlets; that is, changing the value of a callback property will not automatically propagate that change to the front-end. More information on using glue callback properties can be be found in Writing a custom viewer for glue.

Plugin design#

As shown in the diagram above, Jdaviz applications are ostensibly collections of widgets and viewers along with a configuration file that describes how the widgets and viewers ought to be rendered in the front-end. These widgets and viewers are defined as “Plugins”, and everything in the front-end is an example of using plugins in conjunction with the configuration file.

The UI supports four main areas currently: the tool bar area, the menu bar area, the tray bar area, and the content area. Plugins can be associated with one of these areas. Plugins themselves must by IPyWidget subclasses, below is an example of a plugin that adds a single button to the tool bar area.

@tools('test-button')
class TestButton(TemplateMixin):
    template = Unicode("""
    <v-btn>Press me!</v-btn>
    """).tag(sync=True)

On loading the application, plugins are registered to the internal plugins registry. Based on the configuration declaration file, registry items will be referenced from these registries when rendering the front-end. An example of using the above test button plugin class might be

components:
    menu_bar: false
    toolbar: true
    tray_bar: true
    content_area: true
toolbar:
    - test-button
menu_bar:
tray_bar:
content_area:

Plugin classes should not make any direct reference to the application, and should communicate via events.

UI/UX Style Guide#
Tray Plugins#

In order to be consistent with layout, styling, and spacing, UI development on plugins should try to adhere to the following principles:

  • CSS intended to be applied app-wide should live in main_styles.vue so that they are available to all popout instances via PopoutStyleWrapper (exists on anything that inherits TemplateMixin).

  • Any tray plugin should utilize <j-tray-plugin :disabled_msg='disabled_msg' :popout_button="popout_button" :scroll_to.sync="scroll_to"> as the outer-container (which provides consistent styling rules). If the plugin makes use of active status (live-preview marks or viewer callbacks), then also pass `` :uses_active_status=”uses_active_status” @plugin-ping=”plugin_ping($event)”. To enable the "Keep active" check, pass `` :uses_active_status="uses_active_status" @plugin-ping="plugin_ping($event)" :keep_active.sync="keep_active" ``. Any changes to style across all plugins should then take place in the ``j-tray-plugin stylesheet (jdaviz/components/tray_plugin.vue).

  • disabled_msg should be set to replace the UI with a message explaining why the plugin is disabled. irrelevant_msg should be set to skip the plugin in the UI entirely where the user would not need an explanation (slice plugin not relevant because cube data is not present, for example).

  • Each item should be wrapped in a v-row, but avoid any unnecessary additional wrapping-components (v-card-*, v-container, etc).

  • Only use v-col components (within a <v-row class="row-no-outside-padding">) if multiple components are necessary in a single row. Always emphasize readability at the default/minimum width of the plugin tray, rather than using columns that result in a ton of text overflow.

  • Use <v-row justify="end"> to align content to the right (such as action buttons).

  • Action buttons should use <plugin-action-button :results_isolated_to_plugin="true/false">text</plugin-action-button> to control the color depending on whether the button affects things outside the plugin itself (adding/modifying data collection or subset entries, etc) or are isolated to within the plugin (adding model components in model fitting, etc). These buttons can be wrapped in tooltip components and also have the capability of adding spinners (by passing a traitlet to :spinner) or disabling (by passing a traitlet to :disabled).

  • To remove vertical padding from rows (i.e., two successive buttons stacked vertically), use <v-row class="row-min-bottom-padding">.

  • Use new <j-plugin-section-header>Header Text</j-plugin-section-header> to separate content within a plugin (instead of nested cards, v-card-subtitle, etc).

  • Plugin settings should use <v-expansion-panels popout> immediately at the top of the plugin. Optional “sections” of a plugin or editing dynamically-created components should use <v-expansion-panels accordion> to make most use of horizontal and vertical space.

  • Number entries should use a <v-text-field type="number" v-model.number="traitlet_name"> component unless requiring support for scientific notation (in which case <v-text-field @change="python_method"> can be used with stripping invalid characters and type-casting in python). To handle emptying the input component without raising a traceback, use an IntHandleEmpty or FloatHandleEmpty traitlet instead, along with form-validation (see below) and/or checks on the python-side to handle the case of an empty string.

  • Use form validation wherever possible, and disable action buttons if the relevant validation does not pass. This is preferred to raising errors through snackbars after pressing an action button. To do this, wrap the relevant section in a <v-form v-model="form_valid_section_name">, create a form_valid_section_name = Bool(False).tag(sync=True) in the python class for the plugin, add rules to any relevant inputs, and set :disabled="!form_valid_section_name" to any action buttons.

  • When validation requires checking multiple inputs simultaneously, the validation error message can be displayed as its own element using <v-row v-if="condition"><span class="v-messages v-messages__message text--secondary"> <b style="color: red !important">WARNING:</b> warning message</span></v-row>. This should be positioned where the error makes most sense in the flow of the input elements and/or immediately above the action button to explain why it is disabled. For warnings/errors that require more attention, use a <v-alert> instead.

  • Select input elements should default whenever possible (not start as empty), and self-hide if only one valid option. Whenever possible, inputs should use form validation rules with red text explaining the error and disabling action buttons. When one selection/check makes others contextually irrelevant, those irrelevant items should be hidden entirely. When order needs to be enforced, future inputs should be hidden.

  • Re-usable components should be implemented in template_mixin.py by inheriting from BasePluginComponent along with an accompanying mixin and vue template file in jdaviz/components (which in turn are made available through ipyvue.register_component_from_file calls in app.py. These components allow the traitlets to live in the plugin-level so they can easily be observed, and separating per-component logic from the plugin logic itself.

<template>
  <j-tray-plugin
    :description="docs_description || 'Plugin description.'"
    :link="docs_link || 'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#plugin-name'"
    :irrelevant_msg="irrelevant_msg"
    :disabled_msg="disabled_msg"
    :uses_active_status="uses_active_status"
    @plugin-ping="plugin_ping($event)"
    :keep_active.sync="keep_active"
    :popout_button="popout_button"
    :scroll_to.sync="scroll_to">

    <v-row>
      ....
    </v-row>

    <v-form v-model="form_valid">
      <v-row>
        <v-text-field
          label="Label"
          type="number"
          v-model.number="int_handle_empty_traitlet"
          :rules="[() => int_handle_empty_traitlet!=='' || 'This field is required']"
          hint="Hint text."
          persistent-hint
        >
        </v-text-field>
      </v-row>

      <v-row justify="end">
        <plugin-action-button
          :results_isolated_to_plugin="false"
          :disabled="!form_valid"
          @click="(e) => {add_model(e); validate()}"
          >Action Text
        </plugin-action-button>
      </v-row>
    </v-form>
  </j-tray-plugin>
</template>
Plugin Components#

Plugin components exist to provide re-usable UI elements across multiple plugins, both for consistency in behavior between plugins and also for simplification of code.

The general concept is to move as much shared code into these components, and out of the plugins, as possible.

Design Philosophy#

Each component consists of three parts:

1. Python component class in the template_mixin module, which inherits from BasePluginComponent and passes the string names of the traitlets it needs to the constructor as keyword arguments. This class isolates the logic from the plugin itself, while still providing convenient access to the traitlets which are defined in the plugin (and in doing so, allows using those same traitlets within the plugin in the same way as any other traitlet in the plugin). Within this class, it is necessary to use add_observe() in the constructor instead of the @observe decorator on the callback method for all traitlets, so that the callback can reference the traitlet in the plugin properly. For example implementation, see SelectPluginComponent.

2. Python mixin class in the template_mixin module, which inherits from VuetifyTemplate and HubListener. This class defines default traitlets as well as the attribute for the component object itself for plugins to make use of the accompanying component. In some cases, the component class will be used manually with custom traitlets (especially if/when using multiple instances of the same component within a single plugin). For example implementation, see SpectralSubsetSelectMixin.

3. .vue template file in jdaviz/components, which are registered in app.py using ipyvue.register_component_from_file(). These templates are not linked directly to the Python class, but rather should pass all necessary traitlets and options when called from within the template file for the plugin itself. Note that this means that the instance of the component cannot be rendered individually, but also allows for components to interact with each other easily through traitlet events within the plugin. If nesting these inside each other, it might be necessary to manually re-emit events higher up the tree with something like @update:value="$emit('update_value', $event)" in the relevant .vue file.

BasePluginComponent provides the following functionality to all components:

  • app, hub, and plugin properties to access the respective instances.

  • viewer_dicts property to access a list of dictionaries, with keys: viewer, id, reference, and label (reference if available, otherwise id).

  • add_observe() method to connect a callback to the proper traitlet in the parent plugin. This can optionally take first=True to ensure the callback will be processed before any @observe watchers in the plugin.

  • overrides getattr and setattr to redirect any calls to the internal traitlet attributes to those in the plugin.

Motivations for this Design#

We converged on this framework for several reasons (compared to alternate options). If ever considering changing to a different architecture, the following should be considered there as well:

  • Each class can only subscribe to each Message object once (via self.hub.subscribe), without introducing extra wrappers. By isolating the component-logic from the plugin, the component and the plugin itself can subscribe to the same message without issues which makes writing a plugin simpler without having to worry about breaking any message subscriptions.

  • Having all the logic in a Mixin, instead of a Mixin wrapping around a separate “component” class would also prevent the ability to have multiple instances of the same component within a single plugin. This is needed in several places: subsets in line analysis and aperture photometry, for example.

  • Having each component class be standalone with its own linked template (so that it can be rendered individually) would complicate communication between components. The component would need its own traitlets which are then synced to traitlets in the plugin and/or message events would need to be used.

Considerations when Writing/Using Components#
  • Plugin components are specifically designed to be used within plugins, and should not be used elsewhere.

  • Plugin components must use add_observe instead of @observe for any traitlets referenced from the plugin itself.

  • Plugins should use the Mixin whenever appropriate for so attributes are named consistently across plugins.

Specviz Selections#

This section explains the working theory behind the selection tool and was inspired by the the introduction of two methods to the Specviz helper:

  • specviz.get_spectra()

  • specviz.get_spectral_regions()

Data loaded in are imported into Jdaviz and immediately converted into a specutils.SpectralRegion object. These are a spectral analog to the Astropy regions (which instead focuses on spatial regions and their associated WCS). These spectral regions are returned by the specviz.get_spectra() method.

The selection tool allows the user to specify a specific range on the graph. This is defined by the underlying glue library upon which Jdaviz relies on as a “glue subset.” Thus throughout the software documentation, we will refer to these user defined ranges as “subsets.” Effectively, the selection tool defines a mask that can be thought of as “definition” of which data is and is not included in the subset. Upon extraction via specviz.get_spectral_regions(), the method will return a new specutils.SpectralRegion object that applies that mask atop of the proper region (data) displayed, and realizes the subset the user defined in Jdaviz.

Linking of datasets in glue#

Note

The glue documentation includes a page about linking but the present page should be considered a more up-to-date guide with a focus on links useful to Jdaviz.

The ‘why’ of linking#

Why is linking needed in the first place? Linking in glue is a way to describe the relationship between datasets, with two main goals: to know how to overplot datasets, and to know how to apply a subset defined in one dataset (such as a spectral range) to another dataset. Having linking means being able to show, say, multiple spectra in the same plot, or multiple images that are aligned in the same image viewer, or contours on top of an image.

There are various ways of setting up links in glue, but the two main ways that have been discussed and used in Jdaviz are linking by pixel coordinates and by world coordinates (WCS).

Linking by WCS#

There are two main ways of linking by WCS, as follow.

Developing on Windows#

On some Windows OS versions, symbolic links cannot be created without using a terminal started with administrative priviledge, which is not recommended for security reasons. Therefore, setup.py instead creates a copy of the data files instead of using symbolic links. As a result, if you are changing the contents in share folder under the source checkout’s root directory, you will need to rebuild the package even in editable install mode. Otherwise, this should not affect your development experience.

WSL2 and voila#

voila is unable to display when WSL2 cannot start up the Windows-side browser executable. Unfortunately, unlike Jupyter notebook, voila does not have a --no-browser option with a tokenized URL you can copy-and-paste manually on the Windows side (see voila-dashboards/voila#773). Therefore, you might need to install Jdaviz natively on Windows to test its standalone application functionality.

Reference/API#

Configurations#
Helpers API#
jdaviz.configs.cubeviz.helper Module#
Classes#

Cubeviz(*args, **kwargs)

Cubeviz Helper class

jdaviz.configs.imviz.helper Module#
Classes#

Imviz(*args, **kwargs)

Imviz Helper class.

jdaviz.configs.mosviz.helper Module#
Classes#

Mosviz(*args, **kwargs)

Mosviz Helper class

jdaviz.configs.specviz.helper Module#
Classes#

Specviz(*args, **kwargs)

Specviz Helper class.

jdaviz.configs.specviz2d.helper Module#
Classes#

Specviz2d(*args, **kwargs)

Specviz2D Helper class

Viewers#
Viewers API#
jdaviz.configs.default.plugins.viewers Module#
Classes#

JdavizViewerMixin(*args, **kwargs)

jdaviz.configs.cubeviz.plugins.viewers Module#
Classes#

CubevizImageView(*args, **kwargs)

CubevizProfileView(*args, **kwargs)

WithSliceIndicator()

WithSliceSelection()

jdaviz.configs.imviz.plugins.viewers Module#
Classes#

ImvizImageView(*args, **kwargs)

jdaviz.configs.mosviz.plugins.viewers Module#
Classes#

MosvizImageView(*args, **kwargs)

MosvizProfile2DView(*args, **kwargs)

MosvizProfileView(*args, **kwargs)

MosvizTableViewer(session, *args, **kwargs)

jdaviz.configs.specviz.plugins.viewers Module#
Classes#

SpecvizProfileView(*args, **kwargs)

Parsers#
Parsers API#
jdaviz.configs.cubeviz.plugins.parsers Module#
Functions#

parse_data(app, file_obj[, data_type, ...])

Attempts to parse a data file and auto-populate available viewers in cubeviz.

jdaviz.configs.imviz.plugins.parsers Module#
Functions#

parse_data(app, file_obj[, ext, data_label, ...])

Parse a data file into Imviz.

jdaviz.configs.mosviz.plugins.parsers Module#
Functions#

mos_spec1d_parser(app, data_obj[, ...])

Attempts to parse a 1D spectrum object.

mos_spec2d_parser(app, data_obj[, ...])

Attempts to parse a 2D spectrum object.

mos_image_parser(app, data_obj[, ...])

Attempts to parse an image-like object or list of images.

jdaviz.configs.specviz.plugins.parsers Module#
Functions#

specviz_spectrum1d_parser(app, data[, ...])

Loads a data file or Spectrum1D object into Specviz.

jdaviz.configs.specviz2d.plugins.parsers Module#
Functions#

spec2d_1d_parser(app, data_obj[, ...])

Generate a quicklook 1D spectrum from an input 2D spectrum by summing over the cross-dispersion axis.

Plugins#
Plugins API#
jdaviz.configs.default.plugins.collapse.collapse Module#
Classes#

Collapse(*args, **kwargs)

See the Collapse Plugin Documentation for more details.

jdaviz.configs.default.plugins.data_tools.data_tools Module#
Classes#

DataTools(*args, **kwargs)

Public constructor

jdaviz.configs.default.plugins.export.export Module#
Classes#

Export(*args, **kwargs)

See the Export Plugin Documentation for more details.

jdaviz.configs.default.plugins.gaussian_smooth.gaussian_smooth Module#
Classes#

GaussianSmooth(*args, **kwargs)

See the Gaussian Smooth Plugin Documentation for more details.

jdaviz.configs.default.plugins.line_lists.line_lists Module#
Classes#

LineListTool(*args, **kwargs)

Public constructor

jdaviz.configs.default.plugins.markers.markers Module#
Classes#

Markers(*args, **kwargs)

See the Markers Plugin Documentation for more details.

jdaviz.configs.default.plugins.metadata_viewer.metadata_viewer Module#
Classes#

MetadataViewer(*args, **kwargs)

See the Metadata Viewer Plugin Documentation for more details.

jdaviz.configs.default.plugins.model_fitting.model_fitting Module#
Classes#

ModelFitting(*args, **kwargs)

See the Model Fitting Plugin Documentation for more details.

jdaviz.configs.default.plugins.plot_options.plot_options Module#
Classes#

PlotOptions(*args, **kwargs)

The Plot Options Plugin gives access to per-viewer and per-layer options and enables setting across multiple viewers/layers simultaneously.

jdaviz.configs.default.plugins.subset_plugin.subset_plugin Module#
Classes#

SubsetPlugin(*args, **kwargs)

Public constructor

jdaviz.configs.default.plugins.subset_tools.subset_tools Module#
Classes#

SubsetTools(*args, **kwargs)

Public constructor

jdaviz.configs.default.plugins.viewer_creator.viewer_creator Module#
Classes#

ViewerCreator(*args, **kwargs)

Public constructor

jdaviz.configs.cubeviz.plugins.moment_maps.moment_maps Module#
Classes#

MomentMap(*args, **kwargs)

See the Moment Maps Plugin Documentation for more details.

jdaviz.configs.cubeviz.plugins.slice.slice Module#
Classes#

Slice(*args, **kwargs)

See the Slice Plugin Documentation for more details.

jdaviz.configs.imviz.plugins.aper_phot_simple.aper_phot_simple Module#
Classes#

SimpleAperturePhotometry(*args, **kwargs)

The Aperture Photometry plugin performs aperture photometry for drawn regions.

jdaviz.configs.imviz.plugins.catalogs.catalogs Module#
Classes#

Catalogs(*args, **kwargs)

See the Catalog Search Plugin Documentation for more details.

jdaviz.configs.imviz.plugins.compass.compass Module#
Classes#

Compass(*args, **kwargs)

See the Compass Plugin Documentation for more details.

jdaviz.configs.imviz.plugins.coords_info.coords_info Module#
Classes#

CoordsInfo(*args, **kwargs)

Public constructor

jdaviz.configs.imviz.plugins.footprints.footprints Module#
Classes#

Footprints(*args, **kwargs)

See the Footprints Plugin Documentation for more details.

jdaviz.configs.imviz.plugins.image_viewer_creator.image_viewer_creator Module#
Classes#

ImageViewerCreator(*args, **kwargs)

Public constructor

jdaviz.configs.imviz.plugins.line_profile_xy.line_profile_xy Module#
Classes#

LineProfileXY(*args, **kwargs)

Public constructor

jdaviz.configs.imviz.plugins.orientation.orientation Module#
Classes#

Orientation(*args, **kwargs)

See the Orientation Plugin Documentation for more details.

jdaviz.configs.imviz.plugins.rotate_canvas.rotate_canvas Module#
Classes#

RotateCanvas(*args, **kwargs)

See the Canvas Rotation Plugin Documentation for more details.

jdaviz.configs.mosviz.plugins.row_lock.row_lock Module#
Classes#

RowLock(*args, **kwargs)

Public constructor

jdaviz.configs.mosviz.plugins.slit_overlay.slit_overlay Module#
Functions#

jwst_header_to_skyregion(header)

Convert S_REGION in given FITS header for JWST data into sky region.

Classes#

SlitOverlay(*args, **kwargs)

Public constructor

jdaviz.configs.specviz.plugins.line_analysis.line_analysis Module#
Classes#

LineAnalysis(*args, **kwargs)

The Line Analysis plugin returns specutils analysis for a single spectral line.

jdaviz.configs.specviz.plugins.unit_conversion.unit_conversion Module#
Classes#

UnitConversion(*args, **kwargs)

The Unit Conversion plugin handles global app-wide unit-conversion.

jdaviz.configs.specviz2d.plugins.spectral_extraction.spectral_extraction Module#
Classes#

SpectralExtraction(*args, **kwargs)

The Spectral Extraction plugin exposes specreduce methods for tracing, background subtraction, and spectral extraction from 2D spectra.

Nuts and Bolts#
Utilities API#
jdaviz.app Module#
Classes#

Application(**kwargs)

The main application object containing implementing the ipyvue/vuetify template instructions for composing the interface.

jdaviz.configs.default.plugins.data_tools.file_chooser Module#
Classes#

FileChooser(**kwargs)

FileChooser class.

jdaviz.configs.default.plugins.line_lists.line_list_mixin Module#
Classes#

LineListMixin()

Line list-related methods and properties for use in the configuration helper classes.

jdaviz.configs.default.plugins.model_fitting.fitting_backend Module#
Functions#

fit_model_to_spectrum(spectrum, ...[, ...])

Fits a CompoundModel to a Spectrum1D instance.

jdaviz.configs.default.plugins.model_fitting.initializers Module#

This module is used to initialize spectral models to the data at hand.

This is used by model-fitting code that has to create spectral model instances with sensible parameter values such that they can be used as first guesses by the fitting algorithms.

Functions#

initialize(instance, x, y)

Initialize given model.

get_model_parameters(model_cls[, model_kwargs])

jdaviz.configs.imviz.wcs_utils Module#

This module handles calculations based on world coordinate system (WCS).

Functions#

get_compass_info(image_wcs, image_shape[, r_fac])

Calculate WCS compass parameters.

draw_compass_mpl(image[, orig_shape, wcs, ...])

Visualize the compass using Matplotlib.

jdaviz.core.astrowidgets_api Module#
Classes#

AstrowidgetsImageViewerMixin()

This class implements astrowidgets API for Jdaviz image viewer.

jdaviz.core.config Module#

This file contains helper function related to configuration handling.

Functions#

read_configuration([path])

Loads a configuration from a YAML file.

get_configuration([path, section, config])

Retrieve a copy of a specified configuration.

list_configurations()

Get a list of pre-built configurations.

jdaviz.core.custom_traitlets Module#
Classes#

HandleEmptyMixin(*args, **kwargs)

Mixin to handle empty field.

IntHandleEmpty(*args, **kwargs)

Mixin to handle empty integer field.

FloatHandleEmpty(*args, **kwargs)

Mixin to handle empty floating point field.

jdaviz.core.data_formats Module#
Functions#

guess_dimensionality(filename)

Guess the dimensionality of a file.

get_valid_format(filename)

Identify a best match Jdaviz configuration from a filename.

identify_data(filename[, current])

Identify the data format and application configuration from a filename.

identify_helper(filename[, ext])

Guess the appropriate viz helper for a data file.

jdaviz.core.events Module#
Classes#

NewViewerMessage(cls, data[, x_attr])

Message to trigger viewer creation in the application.

ViewerAddedMessage(viewer_id, *args, **kwargs)

Unlike NewViewerMessage, this should be emitted after a viewer is created.

ViewerRemovedMessage(viewer_id, *args, **kwargs)

Message emitted after a viewer is destroyed by the application.

LoadDataMessage(path, *args, **kwargs)

Create a new message

AddDataMessage(data, viewer[, viewer_id])

Create a new message

SnackbarMessage(text[, color, timeout, loading])

Create a new message

RemoveDataMessage(data, viewer[, viewer_id])

Create a new message

AddLineListMessage(table, *args, **kwargs)

Create a new message

RowLockMessage(is_locked, *args, **kwargs)

Create a new message

SliceSelectSliceMessage(value, *args, **kwargs)

Message generated by the cubeviz helper and processed by the slice plugin to sync slice selection across all viewers

SliceValueUpdatedMessage(value, value_unit, ...)

Message generated by the slice plugin when the selected slice is updated

SliceToolStateMessage(change, viewer, *args, ...)

Message generated by the select slice plot plugin when activated/deactivated

TableClickMessage(selected_index[, shared_image])

Message generated by Mosviz table to zoom to object on image

LinkUpdatedMessage(link_type, ...)

Message generated when the WCS/pixel linking is changed

ExitBatchLoadMessage(*args, **kwargs)

Message generated when exiting the outermost batch_load context manager

AstrowidgetMarkersChangedMessage(...)

Message generated when markers are added/removed from an image viewer via astrowidgets API

MarkersPluginUpdate(table_length, *args, ...)

Message when the length of the markers plugin table changes

CanvasRotationChangedMessage(viewer_id, ...)

Message generated by canvas rotation plugin

GlobalDisplayUnitChanged(axis, unit, *args, ...)

Message generated when the global app-wide display unit is changed

ChangeRefDataMessage(data, viewer[, ...])

Create a new message

PluginTableAddedMessage(sender)

Message generated when a plugin table is initialized

PluginTableModifiedMessage(sender)

Message generated when the items in a plugin table are changed

PluginPlotAddedMessage(sender)

Message generated when a plugin plot is initialized

PluginPlotModifiedMessage(sender)

Message generated when the items in a plugin plot are changed

jdaviz.core.freezable_state Module#
Classes#

FreezableState()

FreezableProfileViewerState(**kwargs)

FreezableBqplotImageViewerState(*args, **kwargs)

jdaviz.core.helpers Module#

Helper classes are meant to provide a convenient user API for specific configurations. They allow a separation of “viztool-specific” API and the glue application objects.

See also spacetelescope/jdaviz#104 for more details on the motivation behind this concept.

Classes#

ConfigHelper([app, verbosity, history_verbosity])

The Base Helper Class.

ImageConfigHelper(*args, **kwargs)

ConfigHelper that uses an image viewer as its primary viewer.

jdaviz.core.linelists Module#
Functions#

get_linelist_metadata()

Return metadata for line lists.

get_available_linelists()

Return all available line lists.

load_preset_linelist(name)

Return one of the preset line lists, loaded into QTable.

jdaviz.core.marks Module#
Classes#

OffscreenLinesMarks(viewer)

BaseSpectrumVerticalLine(**kwargs)

Public constructor

SpectralLine(**kwargs)

Subclass on bqplot Lines, mostly so that we can erase spectral lines by eliminating any SpectralLines objects from a figures marks list.

SliceIndicatorMarks(**kwargs)

Subclass on bqplot Lines to handle slice/wavelength indicator.

ShadowMixin()

Mixin class to propagate traits from one mark object to another.

ShadowLine(**kwargs)

Create a white shadow line around another line to help make it standout on top of other lines.

ShadowLabelFixedY(**kwargs)

Label whose position shadows that of a parent shadowing line and will flip alignment based on whether it is left or right of the center of the viewer.

PluginMark(*args, **kwargs)

LinesAutoUnit(**kwargs)

Public constructor

PluginLine(**kwargs)

Public constructor

PluginScatter(**kwargs)

Public constructor

LineAnalysisContinuum(**kwargs)

Public constructor

LineAnalysisContinuumCenter(**kwargs)

Public constructor

LineAnalysisContinuumLeft(**kwargs)

Public constructor

LineAnalysisContinuumRight(**kwargs)

Public constructor

LineUncertainties(**kwargs)

Public constructor

ScatterMask(**kwargs)

Public constructor

SelectedSpaxel(**kwargs)

Public constructor

MarkersMark(**kwargs)

Public constructor

FootprintOverlay(**kwargs)

Public constructor

ApertureMark(**kwargs)

Public constructor

SpectralExtractionPreview(**kwargs)

Public constructor

jdaviz.core.region_translators Module#

The region_translators module houses translations of Region Shapes to Aperture Photometry (photutils.aperture) apertures.

Functions#

regions2roi(region_shape[, wcs])

Convert a given regions shape to glue ROI.

regions2aperture(region_shape)

Convert a given regions shape to photutils aperture.

aperture2regions(aperture)

Convert a given photutils aperture to regions shape.

jdaviz.core.registries Module#
Functions#

convert(name)

Converts camel-case strings to snake-case.

Classes#

UniqueDictRegistry()

Base registry class that handles hashmap-like associations between a string representation of a plugin and the class to be instantiated.

ViewerRegistry()

Registry containing references to custom viewers.

TrayRegistry()

Registry containing references to plugins that will be added to the sidebar tray tabs.

ToolRegistry()

Registry containing references to plugins which will populate the application-level toolbar.

MenuRegistry()

Registry containing references to plugins that will populate the application-level menu bar.

DataParserRegistry()

Registry containing parsing functions for attempting to auto-populate the application-defined initial viewers.

jdaviz.core.template_mixin Module#
Functions#

show_widget(widget, loc, title)

skip_if_no_updates_since_last_active([...])

with_spinner([spinner_traitlet])

decorator on a plugin method to set a traitlet to True at the beginning and False either on failure or successful completion.

with_temp_disable([timeout, ...])

decorator on a plugin method to track the amount of time the wrapped method takes, and disable live plugin-previews if it takes longer than timeout seconds.

Classes#

TemplateMixin(*args, **kwargs)

Public constructor

PluginTemplateMixin(*args, **kwargs)

This base class can be inherited by all sidebar/tray plugins to expose common functionality.

ViewerPropertiesMixin()

BasePluginComponent(plugin, **kwargs)

This base class handles attaching traitlets from the plugin itself to logic handled within the component, support for caching and clearing caches on properties, and common properties for accessing the app, etc.

MultiselectMixin(**kwargs)

Public constructor

SelectPluginComponent(**kwargs)

Plugin select, with support for single or multi-selection.

UnitSelectPluginComponent(**kwargs)

This extends BasePluginComponent for common functionality for a select/dropdown component.

EditableSelectPluginComponent(**kwargs)

Plugin select with support for renaming, adding, and deleting items (by the user).

PluginSubcomponent(**kwargs)

Public constructor

SubsetSelect(**kwargs)

Plugin select for subsets, with support for single or multi-selection.

SubsetSelectMixin(**kwargs)

Applies the SubsetSelect component as a mixin in the base plugin.

SpatialSubsetSelectMixin(**kwargs)

Applies the SubsetSelect component as a mixin in the base plugin.

SpectralSubsetSelectMixin(**kwargs)

Applies the SubsetSelect component as a mixin in the base plugin.

ApertureSubsetSelect(**kwargs)

Plugin select for aperture subsets, with support for single or multi-selection, as well as live-preview rendered in the viewers.

ApertureSubsetSelectMixin(**kwargs)

Applies the ApertureSubsetSelect component as a mixin in the base plugin.

DatasetSpectralSubsetValidMixin(**kwargs)

Adds a traitlet tracking whether self.dataset and self.spectral_subset overlap in the spectral axis.

SpectralContinuumMixin(**kwargs)

Plugin select to choose options for a linear spectral continuum.

ViewerSelect(**kwargs)

Plugin select for viewers, with support for single or multi-selection.

ViewerSelectMixin(**kwargs)

Applies the ViewerSelect component as a mixin in the base plugin.

LayerSelect(**kwargs)

Plugin select for layers, with support for single or multi-selection.

LayerSelectMixin(**kwargs)

Applies the LayerSelect component as a mixin in the base plugin.

PluginTableSelect(**kwargs)

Plugin select for plugin table entries, with support for single or multi-selection.

PluginTableSelectMixin(**kwargs)

Public constructor

PluginPlotSelect(**kwargs)

Plugin select for plugin plot entries, with support for single or multi-selection.

PluginPlotSelectMixin(**kwargs)

Public constructor

NonFiniteUncertaintyMismatchMixin(**kwargs)

Adds a traitlet that identifies if there are any finite data values that correspond to a non-finite uncertainty at that index.

DatasetSelect(**kwargs)

Plugin select for data entries, with support for single or multi-selection.

DatasetSelectMixin(**kwargs)

Applies the DatasetSelect component as a mixin in the base plugin.

DatasetMultiSelectMixin(**kwargs)

Applies the DatasetSelect component as a mixin in the base plugin with togglable multiselect.

FileImportSelectPluginComponent(**kwargs)

IMPORTANT: Always accompany with HasFileImportSelect IMPORTANT: currently assumed only one instance per-plugin

HasFileImportSelect(**kwargs)

Public constructor

Table(**kwargs)

Table subcomponent.

TableMixin(**kwargs)

Table subcomponent mixin.

Plot(**kwargs)

Plot subcomponent.

PlotMixin(**kwargs)

Plot subcomponent mixin.

AutoTextField(plugin, value, default, auto, ...)

Label component with the ability to synchronize to a plugin-provided default value or override with a custom value.

AutoTextFieldMixin(**kwargs)

Applies the AutoTextField component as a mixin in the base plugin.

AddResults(plugin, label, label_default, ...)

Plugin component for providing a data-label and selecting a viewer to add the results from the plugin.

AddResultsMixin(**kwargs)

Applies the AddResults component as a mixin in the base plugin.

PlotOptionsSyncState(plugin, viewer_select, ...)

Plugin component for syncing with glue state objects.

jdaviz.core.validunits Module#
Functions#

units_to_strings(unit_list)

Convert equivalencies into readable versions of the units.

create_spectral_equivalencies_list(...[, ...])

Get all possible conversions from current spectral_axis_unit.

create_flux_equivalencies_list(flux_unit, ...)

Get all possible conversions for flux from current flux units.

jdaviz.models.physical_models Module#

Models that have physical origins.

Classes#

BlackBody(*args, **kwargs)

Blackbody model using the Planck function.

Class Inheritance Diagram#

Inheritance diagram of jdaviz.models.physical_models.BlackBody

jdaviz.utils Module#
Functions#

enable_hot_reloading()

Use watchdog to perform hot reloading.

bqplot_clear_figure(fig)

Clears a given bqplot.Figure to mimic matplotlib clf().

standardize_metadata(metadata)

Standardize given metadata so it can be viewed in Metadata Viewer plugin.

alpha_index(index)

Converts an index to label (A-Z, AA-ZZ).

get_subset_type(subset)

Determine the subset type of a subset or layer

Classes#

SnackbarQueue()

Class that performs the role of VSnackbarQueue, which is not implemented in ipyvuetify.

ColorCycler([counter])

Cycles through matplotlib's default color palette after first using the Glue default data color.

License & Attribution#

Citation#

Cite Us#

If you use jdaviz, please cite us via our Zenodo record: Zenodo

License#

This project is Copyright (c) JDADF Developers and licensed under the terms of the BSD 3-Clause license.

This package is based upon the Astropy package template which is licensed under the BSD 3-clause licence. See the licenses folder for more information.