This exercise is intended to take about 15 minutes. As usual, please ask in the Whova chat if you run into any problems or need any clarifications. For “big-picture” questions, there will time for a debrief/Q&A after the exercise.
If you haven’t yet done so, download the files rh04475_00_01ww_tnx.fit (729 MiB) and HFI_SkyMap_857_2048_R2.02_full.fits (576 MiB) into your notebooks folder.
Open up the WWT app if needed. If the JupyterLab launcher isn’t handy, you can use the “View ⇒ Activate command palette” menu option and then select “AAS WorldWide Telescope”.
Connect this notebook to the app with:
from pywwt.jupyter import connect_to_app
wwt = await connect_to_app().becomes_ready()
The following command will make the environment a bit more uniform:
wwt.foreground_opacity = 0
Small FITS images can actually be visualized in WWT without any tiling. For instance, this WISE 12µm image towards the Westerhout 5 star forming region can be loaded in as-is:
from os.path import join as pjoin
layer_w5 = wwt.layers.add_image_layer(pjoin('data', 'w5.fits'))
Such images do, however, need to be provided to WWT in a TAN projection. pywwt will reproject small inputs if needed.
You can control FITS display settings from Python as well as using the app's interactive interface. For instance:
layer_w5.cmap = 'plasma'
layer_w5.vmin = 400
layer_w5.vmax = 1000
layer_w5.stretch = 'sqrt'
layer_w5.opacity = 0.9
There are currently some limitations in pywwt that limit the synchronization between the Python code and the WWT app, so mixing and matching the two interfaces can sometimes lead to unexpected results.
If your input image is large, pywwt will use Toasty to tile it on-the-fly. The following command will load a photographic plate scanned by the DASCH project. It may take several minutes to run for this particular input image, even using all of your CPUs.
layer_dash = wwt.layers.add_image_layer('rh04475_00_01ww_tnx.fit')
While you're waiting:
htop
to verify that Toasty is using all of your CPUs.Once the image loads, change the WWT background to PanSTARRS1 3pi
and verify that this image lines up with the night sky. This image is nearly centered on the celestial north pole, so you might encounter some “gimbal lock” while panning the WWT UI around.
Fortunately, the tiled data are cached. If you remove the image layer and rerun the cell above, it should finish instantly.
While pywwt's built-in logic aims to handle all sorts of input images, there will always be corner cases where you need to give more explicit instructions.
To demonstrate those steps, and help show all of the pieces that need to come together to display images, we'll work through an example HEALPix image that needs special handling. First we import the lower-level modules:
from toasty.builder import Builder
from toasty.merge import averaging_merger, cascade_images
from toasty.pyramid import PyramidIO
from toasty.samplers import healpix_fits_file_sampler
And set up the inputs:
hpxpath = "HFI_SkyMap_857_2048_R2.02_full.fits"
depth = 6
outdir = "hfi"
Set up the variables that will help resample the HEALPix pixelization onto the TOAST pixelization:
pio = PyramidIO(outdir, default_format="fits")
builder = Builder(pio)
sampler = healpix_fits_file_sampler(hpxpath, force_galactic=True)
Sample the bottom layer. This will probably take around a minute to run.
builder.toast_base(sampler, depth, cli_progress=True)
Emit the metadata that the WWT engine needs to know how to run this file:
builder.write_index_rel_wtml()
Now run the downsampling cascade. This should be pretty quick because after the base layer resampling, this step is computationally inexpensive:
cascade_images(pio, depth, averaging_merger, cli_progress=True)
That was everything we needed to generate the data. To display them in this JupyterLab session, we first use the WWT Kernel Data Relay to start serving the generated files through the Jupyter server:
url = wwt._serve_tree(path=outdir)
print(url)
Then make the WWT engine aware of the data:
wwt.load_image_collection(url=url + "index.wtml", remote_only=True)
Finally, tell the engine to add the imagery as a layer in the current view:
layer_hfi = wwt.layers.add_preloaded_image_layer(url=url + builder.imgset.url, name="HFI")
As loaded, the image pixel cuts are way off. Change the stretch to Logarithmic and reduce the High cutoff until you can see structure.
Try changing the background image to something like GLIMPSE 360, then blinking the HFI image on and off, to see if structures in the galactic plane align. (GLIMPSE 360 only covers a narrow range of latitude above and below the galactic midplane.)
Open the top-level tiled FITS file, hfi/0/0/0_0.fits
, in your favorite desktop FITS viewer to get a sense for the way that the galactic plane maps onto the TOAST projection.
If you have extra time, you can investigate why the DASCH image had to be tiled with the TOAST format even though it is not an all-sky image.
We can force Toasty to tile it using WWT's TAN format as follows. This tiling process will once again take several minutes. Due to the way that the tiling process is implemented in this mode, the progress bar will not show any movement. But processing is still going if the cell label looks like [*]
, with an asterisk:
from toasty import TilingMethod
wwt.layers.add_image_layer(
'rh04475_00_01ww_tnx.fit',
tiling_method=TilingMethod.TAN
)
Overlay this image with the one generated using the TOAST method. Set the TAN image to be partially opaque. If you pan the view around at the right zoom level, you should be able to see the corners of the TAN image moving relative to the corners of the TOAST image. This happens due to the approximates used in the TAN rendering code, which break down at large angular scales.