{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Adding Annotations to the WWT View" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook we'll demonstrate the different tools that pywwt offers for adding “annotations” — overlays — to the WWT view." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Step 1: Setting up WWT\n", "\n", "First, we need to open up WWT. First we import the `WWTJupyterWidget` class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pywwt.jupyter import WWTJupyterWidget" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we use this class to create the pywwt \"widget\". Crucially, the second line (containing just `wwt`) is needed to insert the widget into the notebook, and not just assign it to a variable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "wwt = WWTJupyterWidget()\n", "wwt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*If you're using JupyterLab* and not just a plain Jupyter notebook, you can move the WWT view to a separate window pane. This is **extremely** useful since it lets you keep on typing code without scrolling WWT out of view. Here's how you do that:\n", "\n", "![Right click and select \"Create New View for Output\"](data/separate-pane-instructions.jpg)\n", "\n", "If you don't get a menu when you right-click, or the menu doesn't look like the one pictured, you are using a plain Jupyter notebook and will have to scroll back and forth. See the [First Steps](./First%20Steps.ipynb) notebook for more information and troubleshooting tips if you don’t get a viewer at all." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Step 2: A basic circle annotation\n", "\n", "Let's start about as basic as you can get: a circle. pywwt uses Astropy's “units” support for measuring things like circle radii, so let’s import that module, along with another one that will be helpful:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astropy import units as u\n", "from astropy.coordinates import SkyCoord, concatenate " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "OK, that’s all we need! By default, new circles will be placed at the center of the current WWT view:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "circ = wwt.add_circle(\n", " radius = 2 * u.degree,\n", " line_color = '#008ca8', # HTML hexadecimal color specification\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can change the circle's position later, though, using Astropy's standard sky-coordinate class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = SkyCoord.from_name('Megrez')\n", "wwt.center_on_coordinates(c, instant=False)\n", "circ.set_center(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or we can just create a circle in a specified position right off the bat:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "other_circ = wwt.add_circle(center = c, radius = 3 * u.degree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With pywwt in general, nearly any setting that you can modify after-the-fact, you can also set directly during the creation of your object.\n", "\n", "You can also create filled circles, if that’s your jam:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "circ.fill = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's about it for circles! Let's get rid of them:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "wwt.clear_annotations()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Step 3: Line Annotations\n", "\n", "You can also overlay lines. Here we draw out the Big Dipper — note that the `concatenate` function being used here was imported from the Astropy `coordinates` module above." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bd = concatenate((\n", " SkyCoord.from_name('Alkaid'), \n", " SkyCoord.from_name('Mizar'),\n", " SkyCoord.from_name('Alioth'), \n", " SkyCoord.from_name('Megrez'),\n", " SkyCoord.from_name('Phecda'), \n", " SkyCoord.from_name('Merak'),\n", " SkyCoord.from_name('Dubhe'),\n", "))\n", "\n", "wwt.center_on_coordinates(SkyCoord.from_name('Megrez'))\n", "\n", "line = wwt.add_line(bd)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's make the line a little bit easier on the eyes, and complete the circle of the dipper:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "line.add_point(SkyCoord.from_name('Megrez'))\n", "line.color = 'salmon' # HTML \"named\" colors are also allowed\n", "line.opacity = 0.3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Step 4: Polygons\n", "\n", "You can create filled polygons too! Below we have a complex set of commands that will fill in a few parts of the Orion constellation.\n", "\n", "One thing you should know: WWT's polygon fills use an [even-odd rule] that mean that you must specify your polygon points such that they are **counterclockwise** on the sky (East-from-North position angle increasing). If you create a small polygon with clockwise points, nothing will fill in!\n", "\n", "[even-odd rule]: https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "wwt.center_on_coordinates(SkyCoord.from_name('eta orion'), instant=False)\n", "\n", "body_coords = concatenate((\n", " SkyCoord.from_name('delta orion'),\n", " SkyCoord.from_name('bellatrix'),\n", " SkyCoord.from_name('betelgeuse'),\n", " SkyCoord.from_name('zeta orion'),\n", "))\n", "\n", "body_poly = wwt.add_polygon(\n", " body_coords,\n", " fill = True, \n", " fill_color = 'lightslategray', \n", " opacity = 0.4,\n", " line_color = 'lightslategray',\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "club_coords = concatenate((\n", " SkyCoord.from_name('67 orionis'),\n", " SkyCoord.from_name('chi1 orionis'),\n", " SkyCoord.from_name('chi2 orionis'),\n", " SkyCoord.from_name('xi orionis'),\n", "))\n", "\n", "club_poly = wwt.add_polygon(\n", " club_coords,\n", " fill = True,\n", " fill_color = 'saddlebrown',\n", " opacity = 0.4,\n", " line_color = 'saddlebrown',\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bow_coords = concatenate((\n", " SkyCoord.from_name('pi5 orionis'),\n", " SkyCoord.from_name('pi4 orionis'),\n", " SkyCoord.from_name('pi3 orionis'),\n", " SkyCoord.from_name('pi2 orionis'),\n", " SkyCoord.from_name('omicron2 orionis'),\n", "))\n", "\n", "bow_poly = wwt.add_polygon(\n", " bow_coords,\n", " opacity = 0.4, \n", " line_color = 'saddlebrown',\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bow_poly.fill = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## What's Next\n", "\n", "WWT’s annotations are handy, but they aren’t meant for heavy-duty data analysis. If you want to plot a lot of points, the [NASA Exoplanet Archive](./NASA%20Exoplanet%20Archive.ipynb) tutorial will show you how to load large data tables into WWT with lots of fancy display controls." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## Credits\n", "\n", "This notebook was prepared by O. Justin Otor and Peter K. G. Williams." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.6" } }, "nbformat": 4, "nbformat_minor": 4 }