311.1. Single interactive plots#
311.1. Single interactive plots¶
For the Rubin Science Platform at data.lsst.cloud.
Data Release: Data Preview 1
Container Size: large
LSST Science Pipelines version: r29.2.0
Last verified to run: 2026-03-23
Repository: github.com/lsst/tutorial-notebooks
DOI: 10.11578/rubin/dc.20250909.20
Learning objective: Interactive catalog data visualizations for single plots.
LSST data products: Object table
Packages: lsst.rsp.get_tap_service, holoviews, bokeh
Credit: Originally developed by the Rubin Community Science team, inspired by the tutorials of Leanne Guy and Keith Bechtol. Please consider acknowledging them if this notebook is used for the preparation of journal articles, software releases, or other notebooks.
Get Support: Everyone is encouraged to ask questions or raise issues in the Support Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there.
1. Introduction¶
The Rubin Science Platform was designed to enable scientific analysis of the LSST data sets, which will be unprecedentedly large and complex. The software and techniques that are best suited for visualizing large data sets might be new to many astronomers. This series of notebooks introduce learners with some knowledge of python to three open-source Python libraries that enable powerful interactive visualization of catalogs.
- HoloViews: Produce high-quality interactive visualizations easily by annotating plots and images rather than using direct calls to a plotting library.
- Bokeh: A powerful data visualization library that provides interactive tools including brushing and linking between multiple plots.
- Datashader: Accurately render very large datasets quickly and flexibly.
This notebook focuses on HoloViews and Bokeh for single interactive plots.
These packages are part of the Holoviz ecosystem of tools intended for visualization in a web browser and can be used to create quite sophisticated dashboard-like interactive displays and widgets. The goal of this tutorial is to provide an introduction and starting point from which to create more advanced, custom interactive visualizations. Holoviz has a vibrant and active community where you can ask questions and discuss visualizations with a global community.
Notice: If the notebook or any interactive features seem to stall, first try going a few cells back and rerunning them in order (the order in which cells are run is important for this notebook's functionality). If that does not work, try restarting the kernel. If issues persist, try logging out and restarting the Notebook aspect using a "large" instance of the JupyterLab environment.
Warning: It is not recommended to "Restart Kernel and Run All Cells" in this notebook, or to execute multiple cells very quickly. Some of the examples require interaction (e.g., for the user to select points on a graph) in order to run correctly, and going too fast can cause some plots to not display properly.
Related tutorials: This notebook is part one in a series of three tutorials on interactive catalog data visualizations.
1.1. Import packages¶
Import general scientific python packages (numpy, pandas),
functions from the astronomy python package astropy,
the Rubin function for accessing the TAP service (lsst.rsp.get_tap_service),
and various functions from the holoviews and bokeh packages
that are used in this tutorial.
import numpy as np
import pandas as pd
from astropy import units as u
from astropy.coordinates import SkyCoord
from lsst.rsp import get_tap_service
import bokeh
from bokeh.io import output_notebook
from bokeh.models import HoverTool
import holoviews as hv
Show which version of Bokeh, HoloViews we are working with. This is important when referring to online documentation as APIs can change between versions.
print("Bokeh version: " + bokeh.__version__)
print("HoloViews version: " + hv.__version__)
Bokeh version: 3.8.2 HoloViews version: 1.22.1
1.2. Define functions and parameters¶
Update the maximum number of display rows for Pandas tables.
pd.set_option('display.max_rows', 5)
Set the display of the output Bokeh plots to be inline, in the notebook.
Set the HoloViews plotting library to be bokeh.
The HoloViews and Bokeh icons are displayed when the library is loaded successfully.
Always set the extension after executing output_notebook() to avoid issues with plot display.
2. Use the TAP service to obtain table data¶
The basis for any data visualization is the underlying data. This tutorial works with tabular data that is retrieved from a cone search around a defined coordinate with a specified radius using the Rubin TAP service.
Get a Rubin TAP service instance.
service = get_tap_service("tap")
assert service is not None
Define a reference position on the sky (in the Extended Chandra Deep Field South or ECDFS field, as an example) and a radius in degrees for a cone search.
coord = SkyCoord(ra=53.2*u.degree, dec=-28.1*u.degree, frame='icrs')
radius = 1 * u.deg
Define the query pass to the TAP service.
query = """SELECT coord_ra, coord_dec, objectId, r_extendedness,
g_cModelMag, r_cModelMag, i_cModelMag
FROM dp1.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', {}, {}, {})) = 1
AND r_cModelMag < 27
AND r_extendedness IS NOT NULL
""".format(coord.ra.value, coord.dec.value, radius.to(u.deg).value)
print(query)
SELECT coord_ra, coord_dec, objectId, r_extendedness,
g_cModelMag, r_cModelMag, i_cModelMag
FROM dp1.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', 53.2, -28.1, 1.0)) = 1
AND r_cModelMag < 27
AND r_extendedness IS NOT NULL
As this query will return a very large dataset, use an asynchronous query. This will take a few minutes.
job = service.submit_job(query)
job.run()
<pyvo.dal.tap.AsyncTAPJob at 0x7886831958e0>
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
assert job.phase == 'COMPLETED'
Job phase is COMPLETED
After the job phase has completed, fetch the results into a Pandas table.
data = job.fetch_result().to_table().to_pandas()
Confirm that the expected number of rows has been returned (258807). If true, the following cell will not return an assertion error.
assert len(data) == 258807
Compute three colors from the apparent magnitudes.
data['gmi'] = data['g_cModelMag'] - data['i_cModelMag']
data['rmi'] = data['r_cModelMag'] - data['i_cModelMag']
data['gmr'] = data['g_cModelMag'] - data['r_cModelMag']
Use the r-band extendedness parameter to classify objects as having a "shape_type" of "point" or "extended".
data['shape_type'] = data['r_extendedness'].map({0: 'point', 1: 'extended'})
Convert the objectId to a string because as an integer, it's too large for bokeh to handle.
data['objectId'] = np.array(data['objectId']).astype('str')
Option to print the number of objects with shape_type as "point" or "extended".
# tx1 = np.where(data['shape_type'] == 'point')[0]
# tx2 = np.where(data['shape_type'] == 'extended')[0]
# print(len(tx1), len(tx2))
# del tx1, tx2
Confirm that the expected number of each shape_type have been returned.
assert data[data["shape_type"] == "point"].shape[0] == 48454
assert data[data["shape_type"] == "extended"].shape[0] == 210353
3. HoloViews¶
HoloViews supports easy analysis and visualization by
annotating data rather than utilizing direct calls to plotting packages.
This tutorial uses Bokeh as the plotting
library backend for HoloViews.
HoloViews supports several plotting libraries, such as matplotlib, which can be set in hv.extension() at the beginning.
Create a 8% random subsample of this dataset with which to demonstrate some basic HoloViews functionality. Print the length of this subset and confirm that it is 8% of the original size.
frac = 0.08
data20K = data.sample(frac=frac, axis='index')
print(len(data20K))
assert len(data20K) == round(frac * len(data))
20705
3.1. Scatter plot¶
The basic core primitives of HoloViews are Elements (hv.Element).
Elements are simple wrappers for data which provide a semantically
meaningful visual representation.
An Element may be a set of Points, an Image, a Curve, a Histogram, etc.
See the HoloViews Reference Gallery
for all the various types of Elements that can be created with HoloViews.
The example in this section uses the HoloViews Scatter Element
to quickly visualize the catalog data as a scatter plot.
HoloViews maintains a strict separation between content and presentation.
This separation is achieved by maintaining sets of keyword values as
options that specify how Elements are to appear.
This example applies the default options and removes the toolbar.
Make a simple scatter plot of the data using the Scatter element.
hv.Scatter(data20K).options(toolbar=None)
Figure 1: A non-interactive plot of
coord_ravs.coord_decappears as a blue circle composed of individual, but mostly blended, blue dots.
The data20K set contains many columns. If no columns are specified explicitly, the first 2 columns are taken for x and y respectively by the Scatter Element.
3.2. Hover tool¶
The hover tool can display columns of data points in the scatter plot when hovering the mouse over the plot. It is more user-friendly to be selective about which information is shown with the hover tool.
Create a custom hover tool with select columns: the RA and Dec, the r-band
magnitude, and the shape_type.
raDecHover = HoverTool(
tooltips=[
('ra,dec', '@coord_ra / @coord_dec'),
('rmag', '@r_cModelMag'),
('type', '@shape_type'),
],
formatters={
'ra/dec': 'printf',
'rmag': 'numeral',
'type': 'printf',
},
point_policy="follow_mouse"
)
Set Bokeh customizations as a python dictionary.
plot_style_bkh = dict(alpha=0.5, color='darkmagenta',
marker='triangle', size=3,
xticks=5, yticks=5,
height=400, width=400,
toolbar='above')
Display the plot.
hv.Scatter(data20K).opts(tools=[raDecHover], **plot_style_bkh)
Figure 2: Same as Fig 1, but plotted with purple points, and a hover tool showing the selected columns.
Hover the mouse over the plot above and see only the selected columns' data are displayed.
It might be necessary to zoom in until points are distinguishable in order to notice how the hover tool box contents list only three properties per point.
3.3. Histogram¶
Now bin the data in RA using the robust
Freedman Diaconis Estimator in numpy.histogram,
plot the resulting distribution using the HoloViews
Histogram Element,
and add in some basic plot options.
Read more about about customizing plots via options. Note that options can be shortened to opts.
(ra_bin, count) = np.histogram(data20K['coord_ra'], bins='fd')
ra_distribution = hv.Histogram((ra_bin, count)).opts(
title="RA distribution", color='darkmagenta',
xlabel='RA', fontscale=1.2,
height=400, width=400)
ra_distribution
Figure 3: A histogram (bar chart in purple) of the number of objects in a given RA bin in the subset of twenty thousand objects. This plot is interactive and displays a tool bar at right for the user to, e.g., zoom in on the plot.
4. Conclusion¶
This notebook demonstrates single interactive plots for visualizing catalog data. Additional notebooks in this series will present paired plots and working with larger datasets.