From abaa0be1e6033e54e3c315d94b666f81e64619ba Mon Sep 17 00:00:00 2001
From: Mitchell Revalski <56605543+mrevalski@users.noreply.github.com>
Date: Mon, 9 Dec 2024 16:51:38 -0500
Subject: [PATCH] corrected file opening error
---
notebooks/DrizzlePac/drizzle_wfpc2.ipynb | 1129 ++++++++++++++++++++++
1 file changed, 1129 insertions(+)
create mode 100644 notebooks/DrizzlePac/drizzle_wfpc2.ipynb
diff --git a/notebooks/DrizzlePac/drizzle_wfpc2.ipynb b/notebooks/DrizzlePac/drizzle_wfpc2.ipynb
new file mode 100644
index 000000000..c66e5d922
--- /dev/null
+++ b/notebooks/DrizzlePac/drizzle_wfpc2.ipynb
@@ -0,0 +1,1129 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "# Drizzling new WFPC2 FLT data products with chip-normalization \n",
+ "***\n",
+ "\n",
+ "
This notebook requires creating and activating a virtual environment using the requirements file in this notebook's repository. Please also review the README file before using the notebook.
\n",
+ "\n",
+ "\n",
+ "## Table of Contents\n",
+ " **[1. Introduction](#intro)
**\n",
+ " **[2. Download the Data](#Data)**
\n",
+ " **[3. Update the WCS](#WCS)**
\n",
+ " **[4. Align the Images](#align)**
\n",
+ " **[5. Drizzle-combine the images](#drizzle)**
\n",
+ " **[Conclusions](#conclusions)**
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 1. Introduction \n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "This notebook shows how to work with a new type of WFPC2 calibrated data product in MAST. The new data products combine the previously separate files containing the science array `c0m.fits`and data quality array `c1m.fits` into a new file with suffix `flt.fits`, similar to calibrated images for ACS and WFC3. \n",
+ "\n",
+ "These `flt` files have now been corrected for differences in the inverse sensitivity the science arrays of each chip using the software '[photeq](https://drizzlepac.readthedocs.io/en/deployment/photeq.html)' so that a single PHOTFLAM (or PHOTFNU) value may be used for photometry. \n",
+ "\n",
+ "The new `flt` files include four key differences from the older style `c0m`, `c1m` WFPC2 files:\n",
+ " \n",
+ " 1.) The SCI & DQ arrays are merged into a single file with multiple extensions.\n",
+ " 2.) The SCI arrays are corrected for different 'inverse sensitivities' across chips.\n",
+ " 3.) The SCI arrays from different chips may now be drizzled together in a mosaic.\n",
+ " 4.) The SCI header WCS includes improved absolute astromentry (i.e. WCSNAME='*GAIA*').\n",
+ "\n",
+ " This example uses WFPC2 observations of Omega Centauri (NGC 5139) in the F555W filter taken from CAL proposal [8447](http://www.stsci.edu/cgi-bin/get-proposal-info?id=8447&observatory=HST). The two exposures have been dithered to place the same stars on the WF2 and WF4 chips to measure relative photometry across the two chips. After using `TweakReg` to realign the images, we show how to combine the images with `AstroDrizzle`. We inspect the resulting science and weight images and compare the results with those derived from the older MAST data products.\n",
+ "\n",
+ "**Acronyms:**\n",
+ "- Hubble Space Telescope (HST)\n",
+ "- Wide Field Camera 3 (WFC3)\n",
+ "- Advanced Camera for Surveys (ACS)\n",
+ "- Wide Field and Planetary Camera 2 (WFPC2)\n",
+ "- Mikulski Archive for Space Telescopes (MAST)\n",
+ "- Flexible Image Transport System (FITS)\n",
+ "- World Coordinate System (WCS)\n",
+ "- Hubble Advanced Products (HAP)\n",
+ "- Single Visit Mosaic (SVM)\n",
+ "- Planetary Chip (PC)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "### Import Packages\n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "***\n",
+ "\n",
+ "The following Python packages are required to run the Jupyter Notebook:\n",
+ " - [**os**](https://docs.python.org/3/library/os.html) - change and make directories\n",
+ " - [**glob**](https://docs.python.org/3/library/glob.html) - gather lists of filenames\n",
+ " - [**shutil**](https://docs.python.org/3/library/shutil.html) - copy files between folders\n",
+ " - [**numpy**](https://numpy.org) - math and array functions\n",
+ " - [**matplotlib**](https://matplotlib.org) - create graphics\n",
+ " - [pyplot](https://matplotlib.org/stable/tutorials/pyplot.html) - make figures and graphics\n",
+ " - [**astroquery**](https://astroquery.readthedocs.io/en/latest/) - download astronomical data\n",
+ " - [mast.Observations](https://astroquery.readthedocs.io/en/latest/mast/mast_obsquery.html) - query MAST database\n",
+ " - [**astropy**](https://www.astropy.org) - model fitting and file handling\n",
+ " - [io.fits](https://docs.astropy.org/en/stable/io/fits/) - import FITS files\n",
+ " - [table.Table](https://docs.astropy.org/en/stable/api/astropy.table.QTable.html) - tables without physical units\n",
+ " - [visualization.LogStretch](https://docs.astropy.org/en/stable/api/astropy.visualization.LogStretch.html#astropy.visualization.LogStretch) - display image normalization\n",
+ " - [visualization.ImageNormalize](https://docs.astropy.org/en/stable/api/astropy.visualization.ImageNormalize.html#astropy.visualization.ImageNormalize) - display image normalization\n",
+ " - [**ipython**](https://ipython.org) - cell formatting and interactives\n",
+ " - [display.Image](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.Image) - display image files\n",
+ " - [display.clear_output](http://ipython.org/ipython-doc/dev/api/generated/IPython.display.html#IPython.display.clear_output) - clear text from cells\n",
+ " - [**photutils**](https://photutils.readthedocs.io/en/stable/index.html) - aperture photometry tools\n",
+ " - [photutils.aperture](https://photutils.readthedocs.io/en/stable/aperture.html) - aperture photometry tools\n",
+ " - [aperture_photometry](https://photutils.readthedocs.io/en/stable/api/photutils.aperture.aperture_photometry.html#photutils.aperture.aperture_photometry) - measure aperture photometry\n",
+ " - [CircularAperture](https://photutils.readthedocs.io/en/stable/api/photutils.aperture.CircularAperture.html) - measure photometry in circle\n",
+ " - [CircularAnnulus](https://photutils.readthedocs.io/en/stable/api/photutils.aperture.CircularAnnulus.html) - measure photometry in annulus\n",
+ " - [ApertureStats](https://photutils.readthedocs.io/en/stable/api/photutils.aperture.ApertureStats.html) - calculate aperture statistics\n",
+ " - [**drizzlepac**](https://www.stsci.edu/scientific-community/software/drizzlepac) - combine HST images into mosaics\n",
+ " - [astrodrizzle](https://drizzlepac.readthedocs.io/en/deployment/astrodrizzle.html) - combine exposures by drizzling\n",
+ " - [tweakreg](https://drizzlepac.readthedocs.io/en/deployment/tweakreg.html) - align exposures to a common WCS\n",
+ " - [**stwcs**](https://stwcs.readthedocs.io/en/latest/) - WCS based distortion models and transformations\n",
+ " - [updatewcs](https://stwcs.readthedocs.io/en/stable/updatewcs.html) - modify WCS in HST file headers"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os\n",
+ "import glob\n",
+ "import shutil\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from astroquery.mast import Observations\n",
+ "from astropy.io import fits\n",
+ "from astropy.table import Table\n",
+ "from astropy.visualization import LogStretch, ImageNormalize\n",
+ "from IPython.display import Image, clear_output\n",
+ "from photutils.aperture import CircularAnnulus, CircularAperture, ApertureStats, aperture_photometry\n",
+ "from drizzlepac import tweakreg, astrodrizzle\n",
+ "from stwcs.updatewcs import updatewcs\n",
+ "\n",
+ "%matplotlib inline\n",
+ "%config InlineBackend.figure_format = 'retina'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 2. Download the Data \n",
+ "[Table of Contents](#toc)\n",
+ " \n",
+ "The WFPC2 data are downloaded using the `astroquery` API to access the [MAST](http://archive.stsci.edu) archive. The `astroquery.mast` [documentation](http://astroquery.readthedocs.io/en/latest/mast/mast.html) has more examples for how to find and download data from MAST.\n",
+ "\n",
+ "MAST queries may be done using `query_criteria`, where we specify:
\n",
+ "\n",
+ " $\\rightarrow$ obs_id, proposal_id, and filters \n",
+ "\n",
+ "MAST data products may be downloaded by using `download_products`, where we specify:
\n",
+ "\n",
+ " $\\rightarrow$ data_prod = original `c0m`, `c1m` files and new `flt` calibrated images and their corresponding `drw` drizzled files \n",
+ "\n",
+ " $\\rightarrow$ data_type = standard products `CALWFPC2` or Hubble Advanced Products: 'Single Visit Mosaics' `HAP-SVM`\n",
+ "\n",
+ " Depending on your connection speed this cell may take a few minutes to execute.
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "obs_ids = ['U5JX0108R', 'U5JX010HR']\n",
+ "filts = ['F555W']\n",
+ "\n",
+ "obsTable = Observations.query_criteria(obs_id=obs_ids, filters=filts)\n",
+ "products = Observations.get_product_list(obsTable)\n",
+ "\n",
+ "data_prod = ['C0M', 'C1M', 'FLT', 'DRW'] \n",
+ "data_type = ['CALWFPC2'] # Options: ['CALWFPC2', 'HAP-SVM']\n",
+ " \n",
+ "Observations.download_products(products, productSubGroupDescription=data_prod, project=data_type)\n",
+ "\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The MAST pipeline uses the new `flt` files to create two new types of WFPC2 drizzled products. Unlike the original `u*_drz.fits` files, which were drizzled to an output scale of the WF chips (0.0996\"/pix), the new drizzled files `u*_drw.fits` are drizzled to an output scale of the PC chip (0.0455\"/pix), where the new `drw` suffix reflects the improved WCS. \n",
+ "\n",
+ "A second drizzled product `hst_*drz.fits` combines all images in the same filter and may include improved relative alignment across filters in the same visit. These are referred to as Hubble Advanced Products and are listed below, but are beyond the scope of this notebook. For more details, see the [HAP Webpage](https://outerspace.stsci.edu/pages/viewpage.action?spaceKey=HAdP&title=Improvements+in+HST+Astrometry) and the [Drizzlepac Handbook](https://hst-docs.stsci.edu/drizzpac).\n",
+ " \n",
+ "\n",
+ " Drizzled Image Dimensions Scale Input Updated\n",
+ " (\"/pix) File WCS?\n",
+ " ______________________________________________________________________________________\n",
+ " u5jx010hr_drz.fits [1515, 1495] 0.0996 c?m.fits N\n",
+ " u5jx010hr_drw.fits [4171, 4143] 0.0455 flt.fits Y\n",
+ " hst_8447_01_wfpc2_pc_f555w_u5jx01_drz.fits [6258, 6215] 0.0455 flt.fits Y "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Move files to the current working directory"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fits_files = glob.glob('mastDownload/HST/*/*.fits')\n",
+ "for f in fits_files:\n",
+ " base_name = os.path.basename(f)\n",
+ " if os.path.isfile(base_name):\n",
+ " os.remove(base_name)\n",
+ " shutil.move(f, '.') \n",
+ "shutil.rmtree('mastDownload')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the File Structure\n",
+ "\n",
+ "While the `flt.fits` files use the same notation for different chips, `EXT=('SCI',1)` the order of the FITS extensions (`'SCI', 'ERR', 'DQ'`) is different for WFC3/UVIS and WFPC2. For example:\n",
+ "\n",
+ " uvis_flt.fits[1] = uvis_flt.fits['SCI',1] --> UVIS2, SCI\n",
+ " uvis_flt.fits[2] = uvis_flt.fits['ERR',1] --> UVIS2, ERR\n",
+ " uvis_flt.fits[3] = uvis_flt.fits['DQ',1] --> UVIS2, DQ\n",
+ " uvis_flt.fits[4] = uvis_flt.fits['SCI',2] --> UVIS1, SCI\n",
+ " uvis_flt.fits[5] = uvis_flt.fits['ERR',2] --> UVIS1, ERR\n",
+ " uvis_flt.fits[6] = uvis_flt.fits['DQ',2] --> UVIS1, DQ\n",
+ "\n",
+ " wfpc2_flt.fits[1] = wfpc2_flt.fits['SCI',1) --> PC1, SCI\n",
+ " wfpc2_flt.fits[2] = wfpc2_flt.fits['SCI',2] --> WF2, SCI\n",
+ " wfpc2_flt.fits[3] = wfpc2_flt.fits['SCI',3] --> WF3, SCI\n",
+ " wfpc2_flt.fits[4] = wfpc2_flt.fits['SCI',4] --> WF4, SCI\n",
+ " wfpc2_flt.fits[5] = wfpc2_flt.fits['DQ',1] --> PC1, DQ\n",
+ " wfpc2_flt.fits[6] = wfpc2_flt.fits['ERR',1] --> PC1, ERR \n",
+ " wfpc2_flt.fits[7] = wfpc2_flt.fits['DQ',2] --> WF2, DQ\n",
+ " wfpc2_flt.fits[8] = wfpc2_flt.fits['ERR',2] --> WF2, ERR\n",
+ " wfpc2_flt.fits[9] = wfpc2_flt.fits['DQ',3] --> WF3, DQ\n",
+ " wfpc2_flt.fits[10] = wfpc2_flt.fits['ERR',3] --> WF3, ERR\n",
+ " wfpc2_flt.fits[11] = wfpc2_flt.fits['DQ',4] --> WF4, DQ\n",
+ " wfpc2_flt.fits[12] = wfpc2_flt.fits['ERR',4] --> WF4, ERR"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fits.info('u5jx010hr_c0m.fits')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fits.info('u5jx010hr_flt.fits')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The drizzled products, on the other hand, contain 3 data extensions: `SCI`, `WHT`, and `CTX`. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fits.info('u5jx010hr_drw.fits')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Compare photometric keywords from the handbook with the image headers\n",
+ " \n",
+ "`PHOTFLAM` 'inverse sensitivity' values are listed in Table 5.1 of the WFPC2 DATA HANDBOOK Section 5.1 [Photometric Zeropoint](http://www.stsci.edu/instruments/wfpc2/Wfpc2_dhb/wfpc2_ch53.html) for the gain 7 setting (which is the default setting for most science programs). The `PHOTFLAM` values for gain 14 can be obtained by multiplying by the gain ratios: 1.987 (PC1), 2.003 (WF2), 2.006 (WF3), and 1.955 (WF4), where the values are from [Holtzman et al. (1995)](https://ui.adsabs.harvard.edu/abs/1995PASP..107.1065H/abstract). \n",
+ "\n",
+ " Filter PC1 WF2 WF3 WF4\n",
+ " ----- --------- --------- --------- ---------\n",
+ " f555w \t 3.483e-18 3.396e-18 3.439e-18 3.507e-18 \n",
+ "\n",
+ "The `PHOTFLAM` values include differences in the gain (e- DN-1) between chips, i.e. Table 4.2 in Section 4.4: \"Read Noise and Gain Settings\" in the [2008 WFPC2 Instrument Handbook](https://www.stsci.edu/files/live/sites/www/files/home/hst/instrumentation/legacy/wfpc2/_documents/wfpc2_ihb.pdf), reproduced below:\n",
+ "\n",
+ " Gain PC1 WF2 WF3 WF4\n",
+ " ----- --------- --------- --------- ---------\n",
+ " \"7\" 7.12 ± 0.41 7.12 ± 0.41 6.90 ± 0.32 7.10 ± 0.39\n",
+ " \"15\" 13.99 ± 0.63 14.50 ± 0.77 13.95 ± 0.63 13.95 ± 0.70\n",
+ " \n",
+ "\n",
+ "While WFC3 and ACS flt.fits data products are in units of electrons (WFC3/UVIS, ACS/WFC) or electrons/sec (WFC3/IR), WFPC2 images are in units of 'Data Number' (DN) or 'COUNTS' as reflected in the BUNIT keyword.
\n",
+ " \n",
+ "Here we inspect a subset of photometry keywords in the `c0m` and `flt` files:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with fits.open('u5jx0108r_c0m.fits') as h:\n",
+ " phot1 = h[1].header['PHOTFLAM']\n",
+ " phot2 = h[2].header['PHOTFLAM']\n",
+ " phot3 = h[3].header['PHOTFLAM']\n",
+ " phot4 = h[4].header['PHOTFLAM']\n",
+ " gain = h[0].header['ATODGAIN']\n",
+ " bunit = h[1].header['BUNIT']\n",
+ "\n",
+ "print('PHOTFLAM for PC1: ', phot1, ' Factor Relative to WF3: ', round(phot1/phot3, 4))\n",
+ "print('PHOTFLAM for WF2: ', phot2, ' Factor Relative to WF3: ', round(phot2/phot3, 4))\n",
+ "print('PHOTFLAM for WF3: ', phot3, ' Factor Relative to WF3: ', round(phot3/phot3, 4))\n",
+ "print('PHOTFLAM for WF4: ', phot4, ' Factor Relative to WF3: ', round(phot4/phot3, 4))\n",
+ "print('Gain Value is: ', gain) \n",
+ "print('Units are: ', bunit) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Note the unique PHOTFLAM values for each chip in the original `c0m` data products (above). \n",
+ "\n",
+ "In the new `flt` data products, the PHOTFLAM values are all set to the value for WF3 (below)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with fits.open('u5jx0108r_flt.fits') as h:\n",
+ " phot1 = h[1].header['PHOTFLAM']\n",
+ " phot2 = h[2].header['PHOTFLAM']\n",
+ " phot3 = h[3].header['PHOTFLAM']\n",
+ " phot4 = h[4].header['PHOTFLAM']\n",
+ " gain = h[0].header['ATODGAIN']\n",
+ " bunit = h[1].header['BUNIT']\n",
+ "\n",
+ "print('PHOTFLAM for PC1: ', phot1, ' Factor Relative to WF3: ', round(phot1/phot3, 4))\n",
+ "print('PHOTFLAM for WF2: ', phot2, ' Factor Relative to WF3: ', round(phot2/phot3, 4))\n",
+ "print('PHOTFLAM for WF3: ', phot3, ' Factor Relative to WF3: ', round(phot3/phot3, 4))\n",
+ "print('PHOTFLAM for WF4: ', phot4, ' Factor Relative to WF3: ', round(phot4/phot3, 4))\n",
+ "print('Gain Value is: ', gain) \n",
+ "print('Units are: ', bunit) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The new `drw` data products carry the WF3 PHOTFLAM values. While the BUNIT keyword says 'counts', it should say 'counts/sec'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with fits.open('u5jx010hr_drw.fits') as h:\n",
+ " phot1 = h[1].header['PHOTFLAM']\n",
+ " gain = h[0].header['ATODGAIN']\n",
+ " bunit = h[1].header['BUNIT']\n",
+ "\n",
+ "print('PHOTFLAM for Combined image', phot1, ' Factor Relative to WF3: ', round(phot1/phot3, 4))\n",
+ "print('Gain Value is: ', gain) \n",
+ "print('Units are: ', bunit) "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Because WF3 is the chip with the most accurate flux calibration, this was selected as the 'reference' chip and the inverse sensitivities in the new `flt` files have been equalized to that value. For example:\n",
+ "\n",
+ " photeq.photeq(files='*_flt.fits', ref_phot_ext=3) # or ('sci',3)\n",
+ " \n",
+ "\n",
+ "Note that `photeq` adjusts the pixels values in the SCI array so that photometry can be obtained using a single `PHOTFLAM`. The ratio of the count rates in the chips will therefore be equal to the ratio of the PHOTFLAM values. \n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Compare the equation for computing STMAG using the new and the old workflow: \n",
+ "\n",
+ "NEW: Use `flt` files \n",
+ " \n",
+ "Drizzle the 'flt.fits' files and do photometry for all chips at once; \n",
+ "\n",
+ " STMAG = -21.1 -2.5*log (countrate * PHOTFLAM) \n",
+ "\n",
+ "OLD: Use `c0m` files \n",
+ " \n",
+ " option A.) Drizzle the 'c0m.fits' files and do photometry for each chip separately; \n",
+ " \n",
+ " STMAG = -21.1 -2.5*log (countrate * PHOTFLAM_1,2,3,4) \n",
+ " \n",
+ " option B.) Run [phot_eq](https://drizzlepac.readthedocs.io/en/deployment/photeq.html) on the 'c0m.fits' files prior to drizzling, normalizing to the WF3 chip. Use the first equation with a single PHOTFLAM value which equal to PHOTFLAM for WF3 in the second equation.\n",
+ " \n",
+ "With the older `c0m` data products, caution must be taken when using `AstroDrizzle` to combine chips of different sensitivity. `AstroDrizzle` works with calibrated images in units of counts (electrons or Data Numbers) or count rates and not in units of flux. It assumes that all input frames can be converted to physical flux units using a single inverse-sensitivity value, and the output drizzled product simply copies the `PHOTFLAM` keyword value from the first input image. When this occurs, the inverse-sensitivity will vary across the final drizzled product, and users will need to keep track of which sources fell on which chip when doing photometry. Moreover, varying detector sensitivities can affect the cosmic-ray rejection algorithm used by `AstroDrizzle`, and this may result in the misidentification of some good pixels as cosmic rays. Using the new FLT style files solves these issues by normalizing the chips to a single `PHOTFLAM` value."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Check image header data \n",
+ "\n",
+ "In this section, we inspect keywords in the image headers which are useful for understanding the data. Note the `PHOTMODE` keyword in column 6 below, which lists the CCD gain. Additionally, we inspect the keywords `WCSNAME` and `NMATCHES` to determine whether the images have improved astrometry."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "paths = sorted(glob.glob('*flt.fits'))\n",
+ "data = []\n",
+ "keywords_ext0 = [\"ROOTNAME\", \"TARGNAME\", \"FILTNAM1\", \"EXPTIME\"]\n",
+ "keywords_ext1 = [\"ORIENTAT\", \"PHOTMODE\", \"PHOTFLAM\", \"WCSNAME\", \"NMATCHES\"]\n",
+ "\n",
+ "for path in paths:\n",
+ " path_data = []\n",
+ " for keyword in keywords_ext0:\n",
+ " path_data.append(fits.getval(path, keyword, ext=0))\n",
+ " for keyword in keywords_ext1:\n",
+ " path_data.append(fits.getval(path, keyword, ext=1))\n",
+ " data.append(path_data)\n",
+ " \n",
+ "keywords = keywords_ext0 + keywords_ext1\n",
+ "table = Table(np.array(data), names=keywords, dtype=['str', 'str', 'str', 'f8', 'f8', 'str', 'f8', 'str', 'i8'])\n",
+ "table['EXPTIME'].format = '7.1f' \n",
+ "table['ORIENTAT'].format = '7.2f'\n",
+ "table['PHOTFLAM'].format = '7.6g' \n",
+ "table"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here we see that the images have been aligned to Gaia eDR3 with ~ 100 matched objects in the HST data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 3. Update the WCS \n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "Unlike the new `flt` products, the older WFPC2 `c0m` files contain World Coordinate System (WCS) information based on an older-style description of image distortions. Before these images can be processed with `drizzlepac`, their WCS must be converted to a new format. This can be achieved using `updatewcs()` function from the `stwcs` package. \n",
+ "\n",
+ "More details may be found in the DrizzlePac Handbook, chapter 4.4.5 under section: ['Making WFPC2 Images Compatible with AstroDrizzle'](https://www.stsci.edu/files/live/sites/www/files/home/scientific-community/software/drizzlepac/_documents/drizzlepac-handbook-v1.pdf). NOTE: Running `updatewcs` is not necessary when working with `flt` files. \n",
+ "\n",
+ "First we download the necessary reference files from the CRDS website."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "os.environ['CRDS_SERVER_URL'] = 'https://hst-crds.stsci.edu'\n",
+ "os.environ['CRDS_PATH'] = os.path.abspath(os.path.join('.', 'reference_files'))\n",
+ "os.system('crds bestrefs --files u5jx01*_c0m.fits --sync-references=1 --update-bestrefs')\n",
+ "os.environ['uref'] = os.path.abspath(os.path.join('.', 'reference_files', 'references', 'hst', 'wfpc2')) + os.path.sep\n",
+ "\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**NOTE:** This next step may raise warnings which may be ignored. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "updatewcs('u*c0m.fits', use_db=False)\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "While the new `flt` images have already been aligned to Gaia, we want to directly compare (ratio) the two sets of drizzled products. Thus we reset the WCS in the `flt` files to use the 'distortion-only' solution. When there are a large number of GAIA matches ($\\geq$ 20), users will want to use the GAIA-based WCS solutions for optimal alignment, especially when there is a large dither across chips, which can introduce a significant rotational offset between exposures (as seen in the `TweakReg` shift files below). In this notebook we focus on photometric differences between the WF2 and WF4 chips, so simply align the exposures using bright stars in common between the two `flt` images."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "updatewcs('u*flt.fits', use_db=False)\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4. Align the Images \n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "After resetting the WCS, we check for any residual pointing errors between the two dithered exposures. Precise aligment is needed to achieve the best drizzle-combined products. The expected pointing accuracy for various observing scenerios is summarized in the DrizzlePac Handbook [Chapter 4.4](https://hst-docs.stsci.edu/drizzpac/chapter-4-astrometric-information-in-the-header/4-4-hst-pointing-accuracy-and-stability). Input images must first be aligned so that when the coordinates of a given object (in detector space) are converted to sky coordinates (using the WCS), that object's sky coordinates must be approximately equal in each frame. \n",
+ "\n",
+ "The `DrizzlePac` task `TweakReg` may be used to correct for any errors in the image header WCS. First, `TweakReg` finds sources in each image, matches sources in common across images, and finds a separate linear transformation to align each image. `TweakReg` then computes a new WCS for each image based on this linear transformation.\n",
+ "\n",
+ "Here we show a basic image alignment procedure. For a more detailed illustration of image alignment, please refer to other example notebooks in this repository. Note we use a farily large `searchrad` of 1 arcsec, because we have removed the Gaia WCS and are using the original 'distortion only' solution which can have large errors in the case of large dithers. \n",
+ "\n",
+ "First we align the `flt` files and inspect the results before aligning the `c0m` files and verifying that output `shiftfile` values are identical. While testing the alignment, we recommend setting `updatehdr` = `False` to confirm that the alignment results look accurate and then rerunning with the keyword set to `True`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "input_images = sorted(glob.glob('u*flt.fits'))\n",
+ "\n",
+ "tweakreg.TweakReg(input_images, \n",
+ " updatehdr=True, \n",
+ " clean=True,\n",
+ " reusename=True, \n",
+ " interactive=False,\n",
+ " conv_width=3.0, \n",
+ " threshold=200.0,\n",
+ " ylimit=1,\n",
+ " shiftfile=True, \n",
+ " outshifts='shift_flt.txt',\n",
+ " searchrad=1,\n",
+ " tolerance=3,\n",
+ " minobj=7)\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### If the alignment is unsuccessful, stop the notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open('shift_flt.txt', 'r') as shift:\n",
+ " for line_number, line in enumerate(shift, start=1):\n",
+ " if \"nan\" in line:\n",
+ " raise ValueError('nan found in line {} in shift file'.format(line_number))\n",
+ " else:\n",
+ " continue"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the shift file and fit residuals\n",
+ "\n",
+ "We can look at the shift file to see how well the fit did (or we could open the output png images for more information). The columns are:\n",
+ "- Filename, X Shift [pixels], Y Shift [pixels], Rotation [degrees], Scale, X RMS [pixels], Y RMS [pixels]\n",
+ "\n",
+ "**Note that there is a small shift in x=1.8 pix and y=-0.4 pix and large rotation of 0.014 degrees between the two images, likely due to the large chip-sized dither.** These residuals are larger than the RMS scatter of 0.15 pixels and are therefore likely to be real. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "shift_flt_table = Table.read('shift_flt.txt', format='ascii.no_header', \n",
+ " names=['file', 'dx', 'dy', 'rot', 'scale', 'xrms', 'yrms'])\n",
+ "\n",
+ "formats = ['.2f', '.2f', '.3f', '.5f', '.2f', '.2f']\n",
+ "for i, col in enumerate(shift_flt_table.colnames[1:]):\n",
+ " shift_flt_table[col].format = formats[i]\n",
+ "shift_flt_table"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the Astrometric residual scatter plots\n",
+ "\n",
+ "Good practice includes inspecting not only the shift file residuals, but also the accompanying diagnostic plots. The residuals in the plot below are clustered around 0.0 with no obvious systematics."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Image(filename='residuals_u5jx010hr_flt.png', width=500, height=300)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here we align the `c0m` files with the same parameter settings:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "input_images = sorted(glob.glob('u*c0m.fits'))\n",
+ "\n",
+ "tweakreg.TweakReg(input_images, \n",
+ " updatehdr=True, \n",
+ " clean=True,\n",
+ " reusename=True, \n",
+ " interactive=False,\n",
+ " conv_width=3.0, \n",
+ " threshold=200.0,\n",
+ " ylimit=1,\n",
+ " shiftfile=True, \n",
+ " outshifts='shift_c0m.txt',\n",
+ " searchrad=1,\n",
+ " tolerance=3,\n",
+ " minobj=7)\n",
+ "\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Finally, we compare the shift file computed from the `flt` and `c0m` files to confirm that the results are identical."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "shift_c0m_table = Table.read('shift_c0m.txt', format='ascii.no_header', \n",
+ " names=['file', 'dx', 'dy', 'rot', 'scale', 'xrms', 'yrms'])\n",
+ "\n",
+ "formats = ['.2f', '.2f', '.3f', '.5f', '.2f', '.2f']\n",
+ "for i, col in enumerate(shift_c0m_table.colnames[1:]):\n",
+ " shift_c0m_table[col].format = formats[i]\n",
+ " \n",
+ "shift_c0m_table"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "shift_flt_table"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 5. Drizzle-combine the images \n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "All four chips are now drizzled together. For speed in the notebook, we set the output pixel scale to that of the WF chips, but this can be reset to the PC scale if desired, to match the scale of the new `drw` drizzled products. \n",
+ "\n",
+ "While we have turned sky subtraction off in the notebook, recommend using `skymethod` = 'localmin' and not 'match' for WFPC2 to avoid issues with overlapping vignetted regions along chip boundaries. See Figure 3.1.2 in the [WFPC2 Instrument Handbook](https://www.stsci.edu/files/live/sites/www/files/home/hst/instrumentation/legacy/wfpc2/_documents/wfpc2_ihb.pdf). For more information drizzling HST data, see the [Drizzlepac Handbook](https://hst-docs.stsci.edu/drizzpac) and the list of commands in the [readthedocs](https://drizzlepac.readthedocs.io/en/latest/drizzlepac_api/astrodrizzle.html).\n",
+ "\n",
+ "Users may wish turn on the sky subtraction and cosmic-ray rejection steps by setting `skysub`, `median`, `blot`, and `driz_cr` parameters to `True`. In that case, the recommended parameter settings for WFPC2 are `driz_cr_snr='5.5 3.5'`, and `driz_cr_scale='2.0 1.5'`. For more discussion on drizzling parameters for WFPC2 when using the output scale of the WF chips, see the [Prior Drizzling Example](https://www.stsci.edu/files/live/sites/www/files/home/scientific-community/software/drizzlepac/examples/_documents/DrizzlePac_EX7.pdf)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "astrodrizzle.AstroDrizzle('u*flt.fits', \n",
+ " output='wfpc2_flt', \n",
+ " preserve=False, \n",
+ " build=False, \n",
+ " context=False, \n",
+ " skysub=False, \n",
+ " driz_sep_wcs=True, \n",
+ " driz_sep_scale=0.0996, \n",
+ " driz_sep_bits='8,1024', \n",
+ " driz_sep_fillval=-1, \n",
+ " median=False, \n",
+ " blot=False,\n",
+ " driz_cr=False, \n",
+ " final_fillval=None, \n",
+ " final_bits='8,1024', \n",
+ " final_wcs=True, \n",
+ " final_scale=0.0996)\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "astrodrizzle.AstroDrizzle('u*c0m.fits', \n",
+ " output='wfpc2_c0m', \n",
+ " preserve=False, \n",
+ " build=False, \n",
+ " context=False, \n",
+ " static=True, \n",
+ " skysub=False, \n",
+ " driz_sep_wcs=True, \n",
+ " driz_sep_refimage='u5jx010hr_single_sci.fits', \n",
+ " driz_sep_bits='8,1024', \n",
+ " driz_sep_fillval=-1, \n",
+ " median=False, \n",
+ " blot=False, \n",
+ " driz_cr=False, \n",
+ " final_fillval=None, \n",
+ " final_bits='8,1024', \n",
+ " final_wcs=True, \n",
+ " final_scale=0.0996, \n",
+ " final_refimage='wfpc2_flt_drw_sci.fits')\n",
+ "clear_output()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Clean up unnecessary mask files."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fits_files = glob.glob('*ask.fits')\n",
+ "for f in fits_files:\n",
+ " base_name = os.path.basename(f)\n",
+ " if os.path.isfile(base_name):\n",
+ " os.remove(base_name)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the single drizzled output frames derived from the dithered `flt` inputs\n",
+ "\n",
+ "Here we compare the single drizzled frames. Note that WF4 and WF2 overlap in the footprint on the sky."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "drz1_single = fits.getdata('u5jx010hr_single_sci.fits')\n",
+ "drz2_single = fits.getdata('u5jx0108r_single_sci.fits')\n",
+ "\n",
+ "fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(20, 10))\n",
+ "im1 = ax1.imshow(drz1_single, cmap='gray', vmin=0, vmax=4, origin='lower')\n",
+ "ax1.set_title('Target on WF4')\n",
+ "im2 = ax2.imshow(drz2_single, cmap='gray', vmin=0, vmax=4, origin='lower')\n",
+ "ax2.set_title('Target on WF2')\n",
+ "\n",
+ "x1 = ax1.get_position().get_points().flatten()[0]\n",
+ "x2 = ax2.get_position().get_points().flatten()[2] - x1\n",
+ "ax_cbar = fig.add_axes([x1, 0, x2, 0.03])\n",
+ "plt.colorbar(im1, cax=ax_cbar, orientation='horizontal')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the single drizzled output frames derived from the dithered `c0m` inputs\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "drz1_c0m_single = fits.getdata('u5jx010hr_c0m_single_sci.fits')\n",
+ "drz2_c0m_single = fits.getdata('u5jx0108r_c0m_single_sci.fits')\n",
+ "\n",
+ "fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(20, 10))\n",
+ "im1 = ax1.imshow(drz1_single, cmap='gray', vmin=0, vmax=4, origin='lower')\n",
+ "ax1.set_title('Target on WF4')\n",
+ "im2 = ax2.imshow(drz2_single, cmap='gray', vmin=0, vmax=4, origin='lower')\n",
+ "ax2.set_title('Target on WF2')\n",
+ "\n",
+ "x1 = ax1.get_position().get_points().flatten()[0]\n",
+ "x2 = ax2.get_position().get_points().flatten()[2] - x1\n",
+ "ax_cbar = fig.add_axes([x1, 0, x2, 0.03])\n",
+ "plt.colorbar(im1, cax=ax_cbar, orientation='horizontal')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Inspect the ratio of the two drizzled images to see changes due to photometric normalization"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ratio_flt_c0m = drz1_single/drz1_c0m_single\n",
+ "fig = plt.figure(figsize=(7, 7))\n",
+ "img_ratio = plt.imshow(ratio_flt_c0m, vmin=0.97, vmax=1.03, cmap='Greys_r', origin='lower')\n",
+ "plt.colorbar(img_ratio, orientation='vertical')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Compare the combined drizzled image and the weight image. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "flt_drw_sci = fits.getdata('wfpc2_flt_drw_sci.fits')\n",
+ "flt_drw_wht = fits.getdata('wfpc2_flt_drw_wht.fits')\n",
+ "fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(20, 10))\n",
+ "im1 = ax1.imshow(flt_drw_sci, cmap='gray', vmin=0, vmax=0.5, origin='lower')\n",
+ "ax1.set_title('SCI')\n",
+ "im2 = ax2.imshow(flt_drw_wht, cmap='gray', vmin=0, vmax=50, origin='lower')\n",
+ "ax2.set_title('WHT')\n",
+ "x1 = ax1.get_position().get_points().flatten()[0]\n",
+ "x2 = ax2.get_position().get_points().flatten()[2] - x1\n",
+ "ax_cbar = fig.add_axes([x1, 0, x2, 0.03])\n",
+ "plt.colorbar(im1, cax=ax_cbar, orientation='horizontal')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Note the Planetary Chip (PC) has ~4x WHT because the native pixel scale is ~2x smaller."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "scale_ratio = 0.0996/0.0455\n",
+ "area_ratio = scale_ratio**2 \n",
+ "print('')\n",
+ "print('PIXEL SCALE RATIO: WF/PC = (0.0996/0.0455) = ', scale_ratio)\n",
+ "print('PIXEL AREA RATIO: WF/PC = (0.0996/0.0455)**2 = ', area_ratio)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next, we compare the two drizzled images, zooming in to highlight where the two chips overlap. Note that the one on the right has a slightly more uniform background across the field of view. Finally, we then identify three isolated stars for photometry. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c0m_drw_sci = fits.getdata('wfpc2_c0m_drw_sci.fits')\n",
+ "flt_drw_sci = fits.getdata('wfpc2_flt_drw_sci.fits')\n",
+ "\n",
+ "im1 = c0m_drw_sci[700:1600, 700:1600]\n",
+ "im2 = flt_drw_sci[700:1600, 700:1600]\n",
+ "\n",
+ "fig, ax = plt.subplots(1, 2, figsize=(15, 10))\n",
+ "norm1 = ImageNormalize(im1, vmin=0.1, vmax=8, stretch=LogStretch())\n",
+ "ax[0].imshow(im1, norm=norm1, cmap='gray', origin='lower')\n",
+ "ax[1].imshow(im2, norm=norm1, cmap='gray', origin='lower')\n",
+ "ax[0].set_title('C0M drz_sci (zoom)', fontsize=20)\n",
+ "ax[1].set_title('FLT drz_sci (zoom)', fontsize=20)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the ratio of the combined drizzled images from FLT and C0M"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ratio_drw = flt_drw_sci/c0m_drw_sci\n",
+ "fig = plt.figure(figsize=(7, 7))\n",
+ "img_ratio = plt.imshow(ratio_drw, vmin=0.97, vmax=1.03, cmap='Greys_r', origin='lower')\n",
+ "plt.colorbar(img_ratio, orientation='vertical')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Perform aperture photometry on three stars in the WF2, WF4 overlap region\n",
+ "\n",
+ "Here we perform aperture photometry in a radius of 5 pixels to show the change in count rates in each drizzle-combined image."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "positions = [(1180, 1381), (1388, 1190), (1232, 1210)] # Coords are (Y+1, X+1)\n",
+ "aperture = CircularAperture(positions, r=5)\n",
+ "annulus_aperture = CircularAnnulus(positions, r_in=10, r_out=15)\n",
+ "\n",
+ "print('Aperture radius:', aperture)\n",
+ "print('Annulus:', annulus_aperture)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = fits.getdata('wfpc2_flt_drw_sci.fits')\n",
+ "aperstats = ApertureStats(data, annulus_aperture)\n",
+ "bkg_mean = aperstats.mean\n",
+ "\n",
+ "phot_table = aperture_photometry(data, aperture)\n",
+ "\n",
+ "for col in phot_table.colnames:\n",
+ " phot_table[col].info.format = '%.8g' # for consistent table output\n",
+ "\n",
+ "print('drz_flt_combined: \"wfpc2_flt_drw_sci.fits\"')\n",
+ "print(' SKY values :', bkg_mean)\n",
+ "print('---------------------------------')\n",
+ "print(phot_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = fits.getdata('wfpc2_c0m_drw_sci.fits')\n",
+ "aperstats = ApertureStats(data, annulus_aperture)\n",
+ "bkg_mean = aperstats.mean\n",
+ "\n",
+ "phot_table = aperture_photometry(data, aperture)\n",
+ "\n",
+ "for col in phot_table.colnames:\n",
+ " phot_table[col].info.format = '%.8g' # for consistent table output\n",
+ "\n",
+ "print('drz_c0m_combined: \"wfpc2_c0m_drw_sci.fits\"')\n",
+ "print(' SKY values :', bkg_mean)\n",
+ "print('---------------------------------')\n",
+ "print(phot_table)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "While the total change in photometry is only a few DN/sec, properly accounting for the relative gain across chips is necessary to achieve the best possible photometric precision. As we've demonstrated in this notebook, this is accomplished by using the new `flt` style files, or running photeq on the older `c0m` style files."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Conclusions \n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "MAST now include new WFPC2 `flt.fits` data products to replace the old `c0m.fits`, `c1m.fits` files. The new products include a new flux normalization between chips so that only a single zeropoint (inverse sensitivity, PHOTFLAM value) is needed for all chips. This allows for different chips to be drizzled together, for example, when combining images at multiple orientations. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " \n",
+ "## About this Notebook\n",
+ "[Table of Contents](#toc)\n",
+ "\n",
+ "***\n",
+ "\n",
+ " Created: 14 Dec 2018; M. Cara\n",
+ " Updated: 16 Nov 2023; K. Huynh & J. Mack\n",
+ " Updated: 10 Dec 2024; J. Mack & M. Revalski\n",
+ " \n",
+ " **Source:** [https://github.com/spacetelescope/hst_notebooks](https://github.com/spacetelescope/hst_notebooks)\n",
+ "\n",
+ "\n",
+ "### Additional Resources\n",
+ "\n",
+ "Below are some additional resources that may be helpful. Please send any questions to the [HST Help Desk](https://stsci.service-now.com/hst).\n",
+ "\n",
+ "- [WFPC2 Website](https://www.stsci.edu/hst/instrumentation/legacy/wfpc2)\n",
+ "- [WFPC2 2002 Data Handbook](https://www.stsci.edu/instruments/wfpc2/Wfpc2_dhb/WFPC2_longdhbcover.html) \n",
+ "- [WFPC2 2008 Instrument Handbook](https://www.stsci.edu/files/live/sites/www/files/home/hst/instrumentation/legacy/wfpc2/_documents/wfpc2_ihb.pdf)\n",
+ "- [Drizzlepac Handbook](https://hst-docs.stsci.edu/drizzpac)\n",
+ "- [WFPC2 Prior Drizzling Example](https://www.stsci.edu/files/live/sites/www/files/home/scientific-community/software/drizzlepac/examples/_documents/DrizzlePac_EX7.pdf)\n",
+ "\n",
+ "\n",
+ "\n",
+ "### Software Citations\n",
+ "If you use Python packages such as `astropy`, `astroquery`, `drizzlepac`, `matplotlib`, or `numpy` for published research, please cite the authors. Follow the links below for more information about citing various packages:\n",
+ "\n",
+ "* [Citing `astropy`](https://www.astropy.org/acknowledging.html)\n",
+ "* [Citing `astroquery`](https://github.com/astropy/astroquery/blob/main/astroquery/CITATION)\n",
+ "* [Citing `drizzlepac`](https://drizzlepac.readthedocs.io/en/latest/getting_started/citing_drizzlepac.html)\n",
+ "* [Citing `matplotlib`](https://matplotlib.org/stable/users/project/citing.html)\n",
+ "* [Citing `numpy`](https://numpy.org/citing-numpy/)\n",
+ "* [Citing `photutils`](https://photutils.readthedocs.io/en/stable/getting_started/citation.html)\n",
+ "***\n",
+ "\n",
+ "[Top of Page](#top)\n",
+ ""
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.11.7"
+ },
+ "varInspector": {
+ "cols": {
+ "lenName": 16,
+ "lenType": 16,
+ "lenVar": 40
+ },
+ "kernels_config": {
+ "python": {
+ "delete_cmd_postfix": "",
+ "delete_cmd_prefix": "del ",
+ "library": "var_list.py",
+ "varRefreshCmd": "print(var_dic_list())"
+ },
+ "r": {
+ "delete_cmd_postfix": ") ",
+ "delete_cmd_prefix": "rm(",
+ "library": "var_list.r",
+ "varRefreshCmd": "cat(var_dic_list()) "
+ }
+ },
+ "types_to_exclude": [
+ "module",
+ "function",
+ "builtin_function_or_method",
+ "instance",
+ "_Feature"
+ ],
+ "window_display": false
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}