diff --git a/notebooks/acs_cte_forward_model_example.ipynb b/notebooks/acs_cte_forward_model_example.ipynb new file mode 100644 index 0000000..03fd6ec --- /dev/null +++ b/notebooks/acs_cte_forward_model_example.ipynb @@ -0,0 +1,1244 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Pixel-based ACS/WFC CTE Forward Model\n", + "\n", + "This notebook demonstrates preparing data for input into the ACS/WFC pixel-based CTE forward model and running the model.\n", + "\n", + "### Table of Contents\n", + "\n", + "[Introduction](#intro_ID)
\n", + "[0. Update Astroconda](#update)
\n", + "[1. Imports](#imports)
\n", + "[2. Download data and reference files](#download)
\n", + "[3. Create an image of artificial stars](#stars)
\n", + "\n", + "[Option A: Start with an observed FLC image](#option-a)\n", + " - [4. Add artificial stars](#A4)\n", + " - [5. Reverse the flat and dark correction](#A5)\n", + " - [6. Run CTE forward model](#A6)\n", + " - [7. (Optional) Run CTE correction](#A7)\n", + " - [8. Apply flat and dark correction](#A8)
\n", + " \n", + "[Option B: Start with a synthetic image](#option-b)\n", + " - [4. Create your image](#B4)\n", + " - [5. Run CTE forward model](#B5)\n", + " - [6. (Optional) Run CTE correction](#B6)\n", + " - [7. Apply flat and dark correction](#B7)
\n", + "\n", + "[About this Notebook](#about_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## Introduction\n", + "\n", + "The charge transfer efficiency (CTE) of the Advanced Camera for Surveys (ACS) Wide Field Channel (WFC) has been decreasing over the lifetime of the instrument. Radiation damage from cosmic rays and other sources leads to charge traps within the detector. These traps remove electrons from charge packets as they are transferred between rows of the detector, and release the electrons in subsequent pixels. This causes flux to be removed from bright features and released into pixels behind the features (relative to the row closest to the amplifier), creating bright trails.\n", + "\n", + "A pixel-based CTE correction model for the ACS/WFC detector is fully described in [Anderson & Bedin (2010)](http://adsabs.harvard.edu/abs/2010PASP..122.1035A), and a recent update to the model is presented in ACS ISR 2018-04 (link to be added soon). The model is based on an empirical determination of the number and depth of charge traps distributed across the detector. It simulates detector readout of an input image, removes the result from the input, and iterates five times. In this way, a reverse model is successively approximated by the forward model. Electrons released in trails are removed and added back to the bright feature in which they originated.\n", + "\n", + "The pixel-based correction was implemented in the calibration pipeline code for ACS (`CALACS`) in 2012 and the algorithm was updated and improved in 2018. The CTE correction step within `CALACS` runs on bias-corrected images, `blv_tmp` files, producing `blc_tmp` files, which lack the bright trails due to poor CTE. Further calibration, including dark correction and flat-fielding, produces `flt` and `flc` files from the `blv_tmp` and `blc_tmps` files, respectively. For more information on calibration of ACS/WFC data, see the [ACS Data Handbook](http://www.stsci.edu/hst/acs/documents/handbooks/currentDHB/toc.html).\n", + "\n", + "Users desiring to more fully understand the effects of pixel-based CTE correction on their science may wish to run the forward model (i.e., the detector readout simulation) on data containing artificial stars. Here we demonstrate two methods for running the CTE forward model. In [Option A](#option-a), we begin with an observed `flc` image, whereas in [Option B](#option_b), we begin with a raw image and generate synthetic data on which to run the forward model.\n", + "\n", + "**Note: The forward model, like the CTE correction step in `CALACS`, adds 10% of the difference between the input and output SCI extensions to the ERR extensions to account for uncertainty in the CTE model. Below, we provide guidance for properly repopulating the ERR extensions of forward-modeled data.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 0. Update Astroconda\n", + "\n", + "It is highly recommended to use [AstroConda](https://astroconda.readthedocs.io/en/latest/) to manage analysis packages for HST data. If you already use Astroconda, make sure the versions of `hstcal` and [`acstools`](https://acstools.readthedocs.io/en/latest/) are both 2.1.0. This version of `hstcal` should contain `CALACS` version 10.1.0. Check the versions of all three on the command line:\n", + "\n", + "`$ conda list hstcal`\n", + "\n", + "`$ conda list acstools`\n", + "\n", + "`$ calacs.e --version`\n", + "\n", + "If `hstcal` and `acstools` are not up-to-date, you can update them on the command line:\n", + "\n", + "`$ conda update hstcal`\n", + "\n", + "`$ conda update acstools`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 1. Imports\n", + "\n", + "Start by importing several packages:\n", + "\n", + "- *matplotlib notebook* for creating interactive plots\n", + "- *os* for setting environment variables\n", + "- *shutil* for managing directories\n", + "- *glob* for finding lists of files\n", + "- *numpy* for math and array calculations\n", + "- *collections OrderedDict* for making dictionaries easily\n", + "- *matplotlib pyplot* for plotting\n", + "- *matplotlib.colors LogNorm* for scaling images\n", + "- *astropy.io fits* for working with FITS files\n", + "- *photutils datasets* for creating synthetic stars and images\n", + "- *astroquery.mast Observations* for downloading data from MAST\n", + "- *acstools acsccd* for performing bias correction\n", + "- *acstools acscte* for performing CTE correction (reversing CTE trailing)\n", + "- *acstools acs2d* for performing dark correction and flat-fielding\n", + "- *acstools acscteforwardmodel* for running CTE forward model (generating CTE trailing)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib notebook\n", + "import os\n", + "import shutil\n", + "import glob\n", + "import numpy as np\n", + "from collections import OrderedDict\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.colors import LogNorm\n", + "from astropy.io import fits\n", + "from photutils import datasets\n", + "from astroquery.mast import Observations\n", + "from acstools import acsccd\n", + "from acstools import acscte\n", + "from acstools import acs2d\n", + "from acstools import acscteforwardmodel" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 2. Download data and reference files\n", + "\n", + "Full-frame, new-mode subarray, and 2K old-mode subarray ACS/WFC images can be run through the CTE forward model. New-mode subarrays were added to the HST flight software at the beginning of Cycle 24. These subarrays have `APERTURE` keywords of the type `WFC1A-512, WFC1A-1K, WFC1A-2K`, etc. Old-mode subarrays have `APERTURE` keywords of the type `WFC1-512, WFC1-1K, WFC1-2K`, etc. WFC apertures are also listed in [Table 7.7 of the ACS IHB](http://www.stsci.edu/hst/acs/documents/handbooks/current/c07_obstechniques08.html#368839).\n", + "\n", + "We recommend that the CTE forward model be run on data that has been bias-corrected, but not dark-corrected or flat-fielded. The flat and dark should be present in the image input into the CTE forward model because these features are present in the image when it is read out, and are therefore affected by CTE losses. The forward model can be run on `flc` files, but the results will technically be incorrect. Photometric tests of forward modeled data of both types show minor differences. Post-SM4 subarray data must be destriped with [`acs_destripe_plus`](https://acstools.readthedocs.io/en/latest/acs_destripe_plus.html), which will also perform the other calibration steps. **Note: At this time, `acs_destripe_plus` only produces `flt`/`flc` images.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We download a full-frame 47 Tuc image, `jd0q14ctq`, from the ACS CCD Stability Monitor program (PI: Coe, 14402) from the Mikulski Archive for Space Telescopes ([MAST](https://mast.stsci.edu/portal/Mashup/Clients/Mast/Portal.html)) using [astroquery](https://astroquery.readthedocs.io/en/latest/). This image was taken in March 2016, and so it is strongly affected by CTE losses. We download the `flc` image for [Option A](#option-a) and the `raw` image for [Option B](#option-b) into the current directory." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "obs_table = Observations.query_criteria(obs_id='jd0q14ctq')\n", + "\n", + "Observations.download_products(obs_table['obsid'], mrp_only=False, productSubGroupDescription=['FLC','RAW'])\n", + "\n", + "# Move file to working directory and remove mast-created directory tree\n", + "files = glob.glob('mastDownload/HST/jd0q14ctq/jd0q14ctq*.fits')\n", + "\n", + "for file in files:\n", + " shutil.move(file, '.')\n", + "\n", + "shutil.rmtree('mastDownload')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, update and download the correct flat and dark reference files for the `jd0q14ctq` dataset from the [Calibration Reference Data System](https://hst-crds.stsci.edu/) (CRDS). We use the [CRDS command line tools](https://hst-crds.stsci.edu/static/users_guide/command_line_tools.html#crds-bestrefs) to do this." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.environ['CRDS_SERVER'] = 'https://hst-crds.stsci.edu'\n", + "os.environ['CRDS_PATH'] = './crds_cache'\n", + "os.environ['JREF'] = './crds_cache/references/hst/acs/'\n", + "\n", + "!crds bestrefs --update-bestrefs --sync-references=1 --files jd0q14ctq_flc.fits" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we obtain the filenames of the flat (`PFLTFILE`), CTE-corrected dark (`DRKCFILE`), and superbias (`BIASFILE`) reference files from the image header. The flat will be used to add the effects of the flat field back into the image. If the data were post-flashed, then the flash file (`FLSHFILE`) is needed as well. This is shown in the commented line below. The CTE-corrected dark will be used to add dark current to the `flc` file and the synthetic data. The superbias will be used to repopulate the ERR extensions of the forward-modeled image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdr = fits.getheader('jd0q14ctq_flc.fits')\n", + "\n", + "flat = hdr['PFLTFILE'].split('$')[-1]\n", + "dkc = hdr['DRKCFILE'].split('$')[-1]\n", + "bias = hdr['BIASFILE'].split('$')[-1]\n", + "# flash = hdr['FLSHFILE'].split('$')[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We open the flat and dark images and obtain the `SCI` extensions of both CCDs, which are extension 1 for WFC2 and extension 4 for WFC1. We open the superbias image and obtain the `ERR` extensions of both CCDs, which are extension 2 for WFC2 and extension 5 for WFC2. If the flash file is needed, obtain the `SCI` extensions for both CCDs. This is shown in the commented out lines below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The JREF environment variable gives the directory containing the reference files\n", + "flat_hdu = fits.open('{}/{}'.format(os.environ['JREF'],flat))\n", + "\n", + "flat_wfc1 = flat_hdu[4].data\n", + "flat_wfc2 = flat_hdu[1].data\n", + "\n", + "dkc_hdu = fits.open('{}/{}'.format(os.environ['JREF'],dkc))\n", + "\n", + "dkc_wfc1 = dkc_hdu[4].data\n", + "dkc_wfc2 = dkc_hdu[1].data\n", + "\n", + "# Darks can sometimes have negative pixels because they have been flash-corrected and CTE-corrected\n", + "# Set all negative pixels to zero\n", + "dkc_wfc1[dkc_wfc1 < 0.] = 0.\n", + "dkc_wfc2[dkc_wfc2 < 0.] = 0.\n", + "\n", + "bias_hdu = fits.open('{}/{}'.format(os.environ['JREF'],bias))\n", + "\n", + "err_bias_wfc1 = bias_hdu[5].data\n", + "err_bias_wfc2 = bias_hdu[2].data\n", + "\n", + "dq_bias_wfc1 = bias_hdu[6].data\n", + "dq_bias_wfc2 = bias_hdu[3].data\n", + "\n", + "# flash_dhu = fits.open('{}/{}'.format(os.environ['JREF'],flash))\n", + "\n", + "# flash_wfc1 = flash_hdu[4].data\n", + "# flash_wfc2 = flash_hdu[1].data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 3. Create image of artificial stars\n", + "\n", + "We will need an image containing artificial stars on zero background for both methods presented below. Artificial stars are typically generated using models that do not include the flat field, or are produced from data that have been flat-fielded. If this is the case, artificial stars should be added to the image at the `flc` stage.\n", + "\n", + "Users of this notebook may have a preferred method for generating artificial stars and adding them to data, so here we simply add several Gaussians to the image using utilities within `photutils.datasets` in `astropy`. These Gaussians are not representative of the true ACS/WFC PSF, and are added here for illustrative purposes only. Please note that artificial sources with peak values approaching or exceeding the WFC CCD full well value of about 80,000 electrons are not recommended for simulated data. Blooming of charge from saturated pixels is not implemented in this example.\n", + "\n", + "There are many tools for generating artificial stars, including [Tiny Tim](http://www.stsci.edu/hst/observatory/focus/TinyTim) (source code may be downloaded [here](http://tinytim.stsci.edu/sourcecode.php)), [effective PSFs](http://www.stsci.edu/hst/acs/documents/isrs/isr0601.pdf), or [`EPSFBuilder`](https://photutils.readthedocs.io/en/stable/epsf.html) in `photutils`. A recent study of PSF models for ACS/WFC can be found [here](http://www.stsci.edu/hst/acs/documents/isrs/isr1708.pdf)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, we generate a table of random Gaussian sources of typical brightness for our 47 Tuc field with $\\mathrm{FWHM}\\sim2.5$ pixels. Because $\\mathrm{FWHM} = 2.355\\sigma$, we will generate Gaussian sources with $\\sigma \\sim 1.06$ pixels in both $x$ and $y$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "n_sources = 300\n", + "param_ranges = [('amplitude', [500, 30000]),\n", + " ('x_mean', [0, 4095]),\n", + " ('y_mean', [0, 2047]),\n", + " ('x_stddev', [1.05, 1.07]),\n", + " ('y_stddev', [1.05, 1.07]),\n", + " ('theta', [0, np.pi])]\n", + "\n", + "param_ranges = OrderedDict(param_ranges)\n", + "\n", + "sources = datasets.make_random_gaussians_table(n_sources, param_ranges, random_state=12345)\n", + "\n", + "print(sources)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we get the shape of one of the `FLC` image SCI extensions and make an image from the table of Gaussian sources. Finally, we run the synthetic image through a Poisson sampler in order to simulate the Poisson noise of the scene." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "wfc2 = fits.getdata('jd0q14ctq_flc.fits', ext=1)\n", + "\n", + "shape = wfc2.shape\n", + "\n", + "synth_stars_image = datasets.make_gaussian_sources_image(shape, sources)\n", + "\n", + "synth_stars_image = np.random.poisson(synth_stars_image)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(synth_stars_image, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=10, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Option A: Start with an observed FLC image\n", + "\n", + "We begin with the `flc` image because it is the closest approximation to a pristine image of the sky. Below we plot a portion of the downloaded 47 Tuc image. Stars of various magnitudes are visible, as well as cosmic rays." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "flc = fits.getdata('jd0q14ctq_flc.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(flc, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 4. Add artificial stars\n", + "\n", + "Add the image of artificial stars generated above to both CCDs of the `flc` image, and save it as a new file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('jd0q14ctq_flc.fits')\n", + "\n", + "wfc1 = hdu[4].data\n", + "wfc2 = hdu[1].data\n", + "\n", + "wfc1 += synth_stars_image\n", + "wfc2 += synth_stars_image\n", + "\n", + "hdu.writeto('jd0q14ctq_stars_flc.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below we plot a section of the `flc` image with a few artificial stars circled in red." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "flc_stars = fits.getdata('jd0q14ctq_stars_flc.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(flc_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 5. Reverse the flat and dark correction\n", + "\n", + "First, calculate the total exposure time of the 47 Tuc image by combining the exposure time, flash time (if any), and 3 seconds of extra dark time to approximate instrument commanding overheads." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('jd0q14ctq_stars_flc.fits')\n", + "\n", + "hdr = hdu[0].header\n", + "\n", + "exptime = hdr['EXPTIME']\n", + "flashtime = hdr['FLASHDUR']\n", + "darktime = exptime + flashtime + 3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we open the 47 Tuc image and obtain the `SCI` extensions of both CCDs. We then multiply by the flat and scale the CTE-corrected dark by the total exposure time. We also run the scaled dark image through a Poisson sampler to include Poisson noise in the dark scene. We then add the dark current to the image. We save the result, which is now effectively a `blc_tmp` file. If the data are post-flashed, we also need to reverse the flash correction. We do this by multiplying the flash file by the flash duration, running it through a Poisson sampler, and adding it to the 47 Tuc image. The lines for this are commented out below. **Note: It is not recommended to use a simulated exposure time that scales pixels in the dark or flash image to or above the full well depth of ~80,000 electrons.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "wfc1 = hdu[4].data\n", + "wfc2 = hdu[1].data\n", + "\n", + "wfc1 *= flat_wfc1\n", + "wfc2 *= flat_wfc2\n", + "\n", + "wfc1 += np.random.poisson(dkc_wfc1*darktime)\n", + "wfc2 += np.random.poisson(dkc_wfc2*darktime)\n", + "\n", + "# wfc1 += np.random.poisson(flash_wfc1*flashtime)\n", + "# wfc2 += np.random.poisson(flash_wfc2*flashtime)\n", + "\n", + "hdu.writeto('jd0q14ctq_stars_pfl_dkc.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Finally, we update the header keyword `PCTECORR` to `PERFORM`, which is necessary for running the forward model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('jd0q14ctq_stars_pfl_dkc.fits', 'PCTECORR', value='PERFORM')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 6. Run CTE forward model\n", + "\n", + "We are now ready to run the CTE forward model, which simulates the effects of CTE losses while reading out the detector. In this example, we will use the `acstools` module `acscteforwardmodel`. Note that this step may take a few minutes. The resulting filename will be `*_ctefmod.fits`. We rename the file to have the suffix `*_blv_tmp.fits` so that it can be processed by `CALACS` in a later step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "acscteforwardmodel.acscteforwardmodel('jd0q14ctq_stars_pfl_dkc.fits')\n", + "\n", + "os.rename('jd0q14ctq_stars_pfl_dkc_ctefmod.fits', 'jd0q14ctq_stars_ctefmod_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After the forward model is run, the SCI extensions of the image are equivalent to a `blv_tmp` file, in principle. However, the ERR extensions are the original `flc` ERR extensions plus 10% of the forward model correction. To ensure the ERR extensions are accurate to a `blv_tmp` file, we will set every pixel to zero and calculate new values for each pixel according to\n", + "\n", + "$\\mathrm{ERR} = \\sqrt{\\mathrm{SCI} + \\mathrm{RN}^2 + (\\mathrm{ERR}_{\\mathrm{superbias}}g)^2}$,\n", + "\n", + "where $\\mathrm{SCI}$ is the pixel value in the SCI extension (all negative pixels are set to zero), $\\mathrm{RN}$ is the readnoise, $\\mathrm{ERR}_{\\mathrm{superbias}}$ is the pixel value in the ERR extension of the superbias, and $g$ is the gain.\n", + "\n", + "First, we access the header and SCI and ERR extensions of the forward-modeled data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('jd0q14ctq_stars_ctefmod_blv_tmp.fits')\n", + "\n", + "sci_wfc1 = hdu[4].data\n", + "sci_wfc2 = hdu[1].data\n", + "\n", + "err_wfc1 = hdu[5].data\n", + "err_wfc2 = hdu[2].data\n", + "\n", + "hdr = hdu[0].header" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we take the readnoise and gain values for each quadrant from the header." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rn_A = hdr['READNSEA']\n", + "rn_B = hdr['READNSEB']\n", + "rn_C = hdr['READNSEC']\n", + "rn_D = hdr['READNSED']\n", + "\n", + "gain_A = hdr['ATODGNA']\n", + "gain_B = hdr['ATODGNB']\n", + "gain_C = hdr['ATODGNC']\n", + "gain_D = hdr['ATODGND']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we make copies of the SCI extensions in which to set all negative values to zero. We calculate the appropriate error for each quadrant and save them to the ERR extensions of the forward-modeled image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sci_wfc1_pos = np.copy(sci_wfc1)\n", + "sci_wfc2_pos = np.copy(sci_wfc2)\n", + "\n", + "sci_wfc1_pos[sci_wfc1_pos < 0] = 0\n", + "sci_wfc2_pos[sci_wfc2_pos < 0] = 0\n", + "\n", + "err_A = np.sqrt(sci_wfc1_pos[:,:2048] + rn_A**2 + (err_bias_wfc1[20:,24:2072]*gain_A)**2)\n", + "err_B = np.sqrt(sci_wfc1_pos[:,2048:] + rn_B**2 + (err_bias_wfc1[20:,2072:-24]*gain_B)**2)\n", + "err_C = np.sqrt(sci_wfc2_pos[:,:2048] + rn_C**2 + (err_bias_wfc2[:-20,24:2072]*gain_C)**2)\n", + "err_D = np.sqrt(sci_wfc2_pos[:,2048:] + rn_D**2 + (err_bias_wfc2[:-20,2072:-24]*gain_D)**2)\n", + "\n", + "err_wfc1[:] = np.hstack((err_A, err_B))\n", + "err_wfc2[:] = np.hstack((err_C, err_D))\n", + "\n", + "hdu.writeto('jd0q14ctq_stars_ctefmod_blv_tmp.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### (Optional) 7. Run CTE correction\n", + "\n", + "If desired, we now CTE correct the forward-modeled image. To do this, we need to update the `PCTECORR` keyword to `PERFORM` again and update the `NEXTEND` keyword to 6, the number of extensions left after running the forward model. (This is because the forward model strips the distortion-related extensions from the input file, but does not update `NEXTEND`.) Finally, run `acscte` on the image. The resulting filename will be `*_blc_tmp.fits`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'PCTECORR', value='PERFORM')\n", + "fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'NEXTEND', value=6)\n", + "\n", + "acscte.acscte('jd0q14ctq_stars_ctefmod_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 8. Apply flat and dark correction\n", + "\n", + "Finally, we flat-field and dark-correct the forward-modeled image using `acs2d` to produce an `flt`-like image. First, we update the keywords `DARKCORR` and `FLATCORR` to `PERFORM`. All other relevant `CALACS` header keyword switches are set to `COMPLETE` because the original data was an `flc` image. The resulting filename will be `*_flt.fits`. **Note:** If the data were post-flashed, and the flash background was added back in during an earlier step, we must also set `FLSHCORR` equal to `PERFORM`. This option is shown below in a commented out line." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'DARKCORR', value='PERFORM')\n", + "fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLATCORR', value='PERFORM')\n", + "# fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLSHCORR', value='PERFORM')\n", + "\n", + "acs2d.acs2d('jd0q14ctq_stars_ctefmod_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the forward-modeled image was CTE-corrected in [Step 7](#A7), we run `acs2d` on the CTE-corrected image. The resulting filename will be `*_flc.fits`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('jd0q14ctq_stars_ctefmod_blc_tmp.fits', 'DARKCORR', value='PERFORM')\n", + "fits.setval('jd0q14ctq_stars_ctefmod_blc_tmp.fits', 'FLATCORR', value='PERFORM')\n", + "# fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLSHCORR', value='PERFORM')\n", + "\n", + "acs2d.acs2d('jd0q14ctq_stars_ctefmod_blc_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The 47 Tuc image(s) are now prepared for further analysis appropriate for the user's science. The cells below plot a portion of the final images." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "flt_stars = fits.getdata('jd0q14ctq_stars_ctefmod_flt.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(flt_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "flc_stars = fits.getdata('jd0q14ctq_stars_ctefmod_flc.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(flc_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Option B: Start with a synthetic image\n", + "\n", + "We start with the `raw` file from the `jd0q14ctq` dataset, and process the `SCI` extensions to make a completely synthetic dataset.\n", + "\n", + "\n", + "### 4. Create a synthetic image\n", + "\n", + "We will create an image that is equivalent to a `blc_tmp` file. This means that the image is not flat-fielded and includes sky background, Poisson noise from the sky, artificial stars or other sources, Poisson noise from the sources, dark current, and dark noise.\n", + "\n", + "We first process the data with `acsccd` within `acstools` to create a `blv_tmp`. This ensures that the error (`ERR`) and data quality (`DQ`) extensions are created and the header keywords for every extension are initially populated, which is necessary for the CTE forward model to run." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "acsccd.acsccd('jd0q14ctq_raw.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we obtain the `SCI` extensions from the `blv_tmp` file, and set the pixels to zero." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('jd0q14ctq_blv_tmp.fits')\n", + " \n", + "wfc1 = hdu[4].data\n", + "wfc2 = hdu[1].data\n", + "\n", + "wfc1[:] = np.zeros(shape)\n", + "wfc2[:] = np.zeros(shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We then generate an image containing a user-selected sky background level (here we choose 40 electrons arbitrarily) and Poisson noise. Finally, we sum the noise image and the artificial star image, and save the result as a new file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "noise_image = datasets.make_noise_image(shape, type='poisson', mean=40, random_state=12345)\n", + "\n", + "wfc1 += noise_image + synth_stars_image\n", + "wfc2 += noise_image + synth_stars_image\n", + "\n", + "hdu.writeto('synth.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below we plot a portion of the synthetic image, with sources circled in red." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "synth = fits.getdata('synth.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(synth, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to properly remove the dark current after the forward model is run, we update the exposure time and flash duration header keywords, `EXPTIME` and `FLASHDUR`, with the desired simulated exposure time. The total exposure time used for the dark correction is the combination of exposure time, flash duration, and 3 seconds of extra overhead. Here we set `EXPTIME` to 300 seconds and `FLASHDUR` to 0 seconds. The total darktime will therefore be 303 seconds." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "exptime = 300.\n", + "flashdur = 0.\n", + "\n", + "hdu = fits.open('synth.fits')\n", + "\n", + "hdr = hdu[0].header\n", + "\n", + "hdr['EXPTIME'] = exptime\n", + "hdr['FLASHDUR'] = flashdur\n", + "\n", + "darktime = exptime + flashdur + 3." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, obtain the `SCI` extensions of both CCDs. We then multiply by the flat and scale the CTE-corrected dark by a chosen exposure time to simulate. We also run the scaled dark image through a Poisson sampler to include Poisson noise in the dark scene. We then add the dark current to the image. If post-flash is desired, multiply the flash reference file by the flash duration, run it through a Poisson sampler, and add to the synthetic data. This is shown in the commented out lines below. We save the result, which is now effectively a `blc_tmp` file. **Note: It is not recommended to use a simulated exposure time that scales pixels in the dark or flash image to or above the full well depth of ~80,000 electrons.**\n", + "\n", + "Note that these reference files are specific to the [anneal cycle](http://www.stsci.edu/hst/acs/documents/handbooks/current/c04_detector4.html#415503) in which these data were taken. If an observation date other than that listed in the `DATE-OBS` header keyword is desired for the synthetic data, different reference files will be needed. These can be found by updating the `DATE-OBS` header keyword in the synthetic image to the desired observation date, and rerunning the cell in [Section 2]() which uses `CRDS bestrefs` to download the correct reference files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "wfc1 = hdu[4].data\n", + "wfc2 = hdu[1].data\n", + "\n", + "wfc1 *= flat_wfc1\n", + "wfc2 *= flat_wfc2\n", + "\n", + "wfc1 += np.random.poisson(dkc_wfc1*darktime)\n", + "wfc2 += np.random.poisson(dkc_wfc2*darktime)\n", + "\n", + "# wfc1 += np.random.poisson(flash_wfc1*flashdur)\n", + "# wfc2 += np.random.poisson(flash_wfc2*flashdur)\n", + "\n", + "hdu.writeto('synth_blc_tmp.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 5. Run CTE forward model\n", + "\n", + "We are now ready to run the CTE forward model, which simulates the effects of CTE losses while reading out the detector. In this example, we will use the `acstools` module `acscteforwardmodel`. Note that this step may take a few minutes. The resulting filename will be `*_ctefmod.fits`. We rename this to `*_blv_tmp.fits` in order to ensure the correct behavior from `acs2d` in a later step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "acscteforwardmodel.acscteforwardmodel('synth_blc_tmp.fits')\n", + "\n", + "os.rename('synth_blc_tmp_ctefmod.fits', 'synth_ctefmod_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, we also add readnoise to the forward-modeled SCI extensions to complete the readout simulation. We find the readnoise values for each quadrant of the image from the header keywords `READNSEA`, `READNSEB`, etc. We make a noise image for each quadrant, concatenate quadrants A and B and quadrants C and D, and add them to the synthetic image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rn_A = hdr['READNSEA']\n", + "rn_B = hdr['READNSEB']\n", + "rn_C = hdr['READNSEC']\n", + "rn_D = hdr['READNSED']\n", + "\n", + "img_rn_A = datasets.make_noise_image((shape[0], int(shape[1]/2)), type='gaussian', mean=0., stddev=rn_A)\n", + "img_rn_B = datasets.make_noise_image((shape[0], int(shape[1]/2)), type='gaussian', mean=0., stddev=rn_B)\n", + "img_rn_C = datasets.make_noise_image((shape[0], int(shape[1]/2)), type='gaussian', mean=0., stddev=rn_C)\n", + "img_rn_D = datasets.make_noise_image((shape[0], int(shape[1]/2)), type='gaussian', mean=0., stddev=rn_D)\n", + "\n", + "wfc1_rn = np.hstack((img_rn_A, img_rn_B))\n", + "wfc2_rn = np.hstack((img_rn_C, img_rn_D))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('synth_ctefmod_blv_tmp.fits')\n", + "\n", + "wfc1 = hdu[4].data\n", + "wfc2 = hdu[1].data\n", + "\n", + "wfc1 += wfc1_rn\n", + "wfc2 += wfc2_rn\n", + "\n", + "hdu.writeto('synth_ctefmod_rn_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The SCI extensions of this image are now equivalent to a `blv_tmp` file, in principle. However, the ERR extensions are the original `blv_tmp` ERR extensions plus 10% of the forward model correction. To ensure the ERR extensions are accurate, we will calculate new values for each pixel according to\n", + "\n", + "$\\mathrm{ERR} = \\sqrt{\\mathrm{SCI} + \\mathrm{RN}^2 + (\\mathrm{ERR}_{\\mathrm{superbias}}g)^2}$,\n", + "\n", + "where $\\mathrm{SCI}$ is the pixel value in the SCI extension (all negative pixels are set to zero), $\\mathrm{RN}$ is the readnoise, $\\mathrm{ERR}_{\\mathrm{superbias}}$ is the pixel value in the ERR extension of the superbias, and $g$ is the gain.\n", + "\n", + "First, we access the header and SCI and ERR extensions of the forward-modeled data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('synth_ctefmod_rn_blv_tmp.fits')\n", + "\n", + "sci_wfc1 = hdu[4].data\n", + "sci_wfc2 = hdu[1].data\n", + "\n", + "err_wfc1 = hdu[5].data\n", + "err_wfc2 = hdu[2].data\n", + "\n", + "hdr = hdu[0].header" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we take the readnoise and gain values for each quadrant from the header." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "rn_A = hdr['READNSEA']\n", + "rn_B = hdr['READNSEB']\n", + "rn_C = hdr['READNSEC']\n", + "rn_D = hdr['READNSED']\n", + "\n", + "gain_A = hdr['ATODGNA']\n", + "gain_B = hdr['ATODGNB']\n", + "gain_C = hdr['ATODGNC']\n", + "gain_D = hdr['ATODGND']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we make copies of the SCI extensions in which to set all negative values to zero. We calculate the appropriate error for each quadrant and save them to the ERR extensions of the forward-modeled image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sci_wfc1_pos = np.copy(sci_wfc1)\n", + "sci_wfc2_pos = np.copy(sci_wfc2)\n", + "\n", + "sci_wfc1_pos[sci_wfc1_pos < 0] = 0\n", + "sci_wfc2_pos[sci_wfc2_pos < 0] = 0\n", + "\n", + "# The superbias ERR arrays contain 20 rows of virtual overscan at the edge of each CCD furthest from the amplifier\n", + "# and 24 columns of physical prescan on the left and right edges.\n", + "err_A = np.sqrt(sci_wfc1_pos[:,:2048] + rn_A**2 + (err_bias_wfc1[20:,24:2072]*gain_A)**2)\n", + "err_B = np.sqrt(sci_wfc1_pos[:,2048:] + rn_B**2 + (err_bias_wfc1[20:,2072:-24]*gain_B)**2)\n", + "err_C = np.sqrt(sci_wfc2_pos[:,:2048] + rn_C**2 + (err_bias_wfc2[:-20,24:2072]*gain_C)**2)\n", + "err_D = np.sqrt(sci_wfc2_pos[:,2048:] + rn_D**2 + (err_bias_wfc2[:-20,2072:-24]*gain_D)**2)\n", + "\n", + "err_wfc1[:] = np.hstack((err_A, err_B))\n", + "err_wfc2[:] = np.hstack((err_C, err_D))\n", + "\n", + "hdu.writeto('synth_ctefmod_rn_blv_tmp.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We also repopulate the DQ extensions because they reflect the processing of the original `blv_tmp` SCI extensions. To do this, we reprocess the data with `DQICORR` and `SINKCORR`, both within `acsccd`, and add in the DQ extensions of the appropriate superbias file. First, we rename the synthetic image to have a filename `*_raw.fits`, or `acsccd` will fail. Then, we update the `DQICORR` and `SINKCORR` header keywords to `PERFORM` and run `acsccd`. The output will be `*_blv_tmp.fits` again." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.rename('synth_ctefmod_rn_blv_tmp.fits', 'synth_ctefmod_rn_raw.fits')\n", + "\n", + "fits.setval('synth_ctefmod_rn_raw.fits', 'DQICORR', value='PERFORM')\n", + "fits.setval('synth_ctefmod_rn_raw.fits', 'SINKCORR', value='PERFORM')\n", + "\n", + "acsccd.acsccd('synth_ctefmod_rn_raw.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, obtain the DQ extensions of the superbias file, and add them to the new DQ extensions of the synthetic data with a bitwise OR operator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hdu = fits.open('synth_ctefmod_rn_blv_tmp.fits')\n", + "\n", + "dq_wfc1 = hdu[6].data\n", + "dq_wfc2 = hdu[3].data\n", + "\n", + "dq_wfc1[:] = np.bitwise_or(dq_wfc1, dq_bias_wfc1[20:,24:-24])\n", + "dq_wfc2[:] = np.bitwise_or(dq_wfc2, dq_bias_wfc2[:-20,24:-24])\n", + "\n", + "hdu.writeto('synth_ctefmod_rn_blv_tmp.fits', overwrite=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 6. (Optional) Run CTE correction\n", + "\n", + "If desired, we now CTE correct the forward-modeled image. To do this, we need to update the `PCTECORR` keyword to `PERFORM` again, and run `acscte` on the image. The resulting filename will be `*_blc_tmp.fits`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'PCTECORR', value='PERFORM')\n", + "\n", + "acscte.acscte('synth_ctefmod_rn_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 7. Apply flat and dark correction\n", + "\n", + "Finally, we flat-field and dark-correct the forward-modeled image using `acs2d` to produce an `flt`-like image. We first ensure that the `DARKCORR`, `FLATCORR`, and if necessary, `FLSHCORR` header keywords are set to `PERFORM`. The resulting filename will be `*_flt.fits`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'DARKCORR', value='PERFORM')\n", + "fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'FLATCORR', value='PERFORM')\n", + "# fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'FLSHCORR', value='PERFORM')\n", + "\n", + "acs2d.acs2d('synth_ctefmod_rn_blv_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the forward-modeled image was CTE-corrected in [Step 6](#B6), we run `acs2d` on the CTE-corrected image. The resulting filename will be `*_flc.fits`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'DARKCORR', value='PERFORM')\n", + "fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'FLATCORR', value='PERFORM')\n", + "# fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'FLSHCORR', value='PERFORM')\n", + "\n", + "acs2d.acs2d('synth_ctefmod_rn_blc_tmp.fits')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The 47 Tuc image(s) are now prepared for further analysis appropriate for the user's science. The cells below plot a portion of the final images." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "synth_ctefmod = fits.getdata('synth_ctefmod_rn_flt.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(synth_ctefmod, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "synth_ctefmod_flc = fits.getdata('synth_ctefmod_rn_flc.fits', ext=1)\n", + "\n", + "fig, ax = plt.subplots(1,1, figsize=(9,4))\n", + "\n", + "ax.imshow(synth_ctefmod_flc, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')\n", + "ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20, markerfacecolor='none', markeredgecolor='red',\n", + " linestyle='none')\n", + "\n", + "ax.set_xlim(2000, 2800)\n", + "ax.set_ylim(1200, 1700)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### About this Notebook\n", + "**Author:** Jenna Ryon, ACS Instrument Team
\n", + "**Updated On:** 08/28/2018" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Top of Page](#title_ID)\n", + "\"stsci_pri_combo_mark_horizonal_white_bkgd\" " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:astroconda]", + "language": "python", + "name": "conda-env-astroconda-py" + }, + "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.5.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}