Reading JWST ASDF-in-FITS with astrowidgets

This is a proof-of-concept using astrowidgets to read in JWST ASDF-in-FITS data. As it is using the dev versions of several different packages, this notebook is not guaranteed to work as-is in the future. As Ginga is primarily an image viewer, we will not concern ourselves with spectrocopic data models in this notebook.

Relevant specs used in testing (more or less):


In [ ]:
import warnings

from astropy.io import fits

from astrowidgets import ImageWidget

from ginga.misc.log import get_logger
from ginga.util import wcsmod

We need to ask Ginga to explicitly use its astropy_ape14 WCS interface. This is unnecessary if every user sets it in their ~/.ginga/general.cfg but that is not always guaranteed.


In [ ]:
wcsmod.use('astropy_ape14')

This notebook assumes that you have downloaded a JWST data file of interest into the working directory. Example file can be found at https://stsci.box.com/s/hwrc5reqygmmv2rl3yvvz90l7ryjac6h (requires permission for access).


In [ ]:
filename = 'jw1069001001_01203_00002_nrca1_level2_cal.fits'

The following cell should show a multi-extension FITS with an ASDF-in-FITS extension. For example:

Filename: jw1069001001_01203_00002_nrca1_level2_cal.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU     232   ()      
  1  SCI           1 ImageHDU        53   (2048, 2048)   float32   
  2  ERR           1 ImageHDU        10   (2048, 2048)   float32   
  3  DQ            1 ImageHDU        11   (2048, 2048)   int32 (rescales to uint32)   
  4  AREA          1 ImageHDU         9   (2048, 2048)   float32   
  5  VAR_POISSON    1 ImageHDU         9   (2048, 2048)   float32   
  6  VAR_RNOISE    1 ImageHDU         9   (2048, 2048)   float32   
  7  ASDF          1 BinTableHDU     11   1R x 1C   [14057B]   

In [ ]:
with fits.open(filename) as pf:
    pf.info()

Then, we customize our image widget by subclassing ImageWidget and adding a method to load the file. In the future, after https://github.com/astropy/astrowidgets/pull/78 is merged, this subclassing will be unnecessary and we will be able to use ImageWidget directly.


In [ ]:
class JWSTImageWidget(ImageWidget):  
    def load_file(self, filename):
        from ginga.util.io import io_asdf
        
        # Even if jwst package is not called directly, it is used
        # to load the correct GWCS data models behind the scenes.
        image = io_asdf.load_file(filename)
        self._viewer.set_image(image)

We define a Ginga logger to go with our image widget. This logger prints out error messages to screen directly.


In [ ]:
logger = get_logger('my viewer', log_stderr=True, log_file=None, level=40)

We create the widget instance. This would be the thing that you interface with for widget magic.


In [ ]:
w = JWSTImageWidget(logger=logger)

We load our JWST data file into our widget instance.


In [ ]:
with warnings.catch_warnings():
    warnings.simplefilter('ignore')  # Ignore validation warning
    w.load_file(filename)

This would display the widget. When you mouse over the pixels, you would see coordinates information (both pixels and sky) change. See https://astrowidgets.readthedocs.io/en/latest/ for documentation on astrowidgets.


In [ ]:
w

Let's change the colormap, the stretch, and the cuts.


In [ ]:
w.set_colormap('viridis_r')
w.stretch = 'log'
w.cuts = 'histogram'

Now, we mark some stars of interest by running the following cell and then click on the widget above. You will see a marker appear where you click each time. We will also customize how the marker would show in the viewer.


In [ ]:
marker_params = {'type': 'circle', 'color': 'red', 'radius': 10,
                 'linewidth': 2}
w.start_marking(marker_name='demo', marker=marker_params)
print(w.is_marking)

When we are done, we run the following cell to stop marking.


In [ ]:
w.stop_marking()
print(w.is_marking)

We can see the points we manually selected above.


In [ ]:
tab = w.get_markers(marker_name='all')
tab.pprint_all()

Optional: Delete all the markers to start over marking objects again above.


In [ ]:
w.reset_markers()