
Pixel-based ACS/WFC CTE Forward Model#
This notebook demonstrates preparing data for input into the ACS/WFC pixel-based CTE forward model and running the model.
Table of Contents#
Introduction
Imports
Download the Data
1. Create an image of artificial stars
Option A: Start with an observed FLC image
Option B: Start with a synthetic image
Introduction#
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.
A pixel-based CTE correction model for the ACS/WFC detector is fully described in Anderson & Bedin (2010), and a recent update to the model is presented in ACS ISR 2018-04. 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.
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.
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, we begin with an observed flc image, whereas in Option B, we begin with a raw image and generate synthetic data on which to run the forward model.
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.
Imports#
It is recommended that you use a base virtual environment. If you are already using a virtual environment, please ensure that you use the most up-to-date versions of the packages listed in the requirements.txt file in this notebook folder.
Start by importing several packages:
matplotlib notebook for creating interactive plots
os for setting environment variables
shutil for managing directories
numpy for math and array calculations
matplotlib pyplot for plotting
matplotlib.colors LogNorm for scaling images
astropy.io fits for working with FITS files
photutils datasets for creating synthetic stars and images
astroquery.mast Observations for downloading data from MAST
acstools acsccd for performing bias correction
acstools acscte for performing CTE correction (reversing CTE trailing)
acstools acs2d for performing dark correction and flat-fielding
acstools acscteforwardmodel for running CTE forward model (generating CTE trailing)
import os
import shutil
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits
from astropy.modeling.models import Gaussian2D
from photutils.datasets import make_noise_image, make_model_params, make_model_image
from astroquery.mast import Observations
from acstools import acsccd
from acstools import acscte
from acstools import acs2d
from acstools import acscteforwardmodel
/home/runner/micromamba/envs/ci-env/lib/python3.11/site-packages/acstools/utils_findsat_mrt.py:24: UserWarning: skimage not installed. MRT calculation will not work: ModuleNotFoundError("No module named 'skimage'")
warnings.warn(f'skimage not installed. MRT calculation will not work: {repr(e)}') # noqa
Download the Data#
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.
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, which will also perform the other calibration steps. Note: At this time, acs_destripe_plus only produces flt/flc images.
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) using astroquery. This image was taken in March 2016, and so it is strongly affected by CTE losses. We download the flc image for Option A and the raw image for Option B into the current directory.
obs_table = Observations.query_criteria(obs_id='jd0q14ctq')
dl_table = Observations.download_products(obs_table['obsid'], mrp_only=False,
productSubGroupDescription=['FLC', 'RAW'])
for row in dl_table:
oldfname = row['Local Path']
unique_fname = np.unique(oldfname)
newfname = os.path.basename(oldfname)
print(row)
os.rename(oldfname, newfname)
shutil.rmtree('mastDownload')
Downloading URL https://mast.stsci.edu/api/v0.1/Download/file?uri=mast:HST/product/jd0q14ctq_raw.fits to ./mastDownload/HST/jd0q14ctq/jd0q14ctq_raw.fits ...
[Done]
Downloading URL https://mast.stsci.edu/api/v0.1/Download/file?uri=mast:HST/product/jd0q14ctq_flc.fits to ./mastDownload/HST/jd0q14ctq/jd0q14ctq_flc.fits ...
[Done]
Downloading URL https://mast.stsci.edu/api/v0.1/Download/file?uri=mast:HST/product/hst_14402_14_acs_wfc_f775w_jd0q14ct_flc.fits to ./mastDownload/HST/hst_14402_14_acs_wfc_f775w_jd0q14ct/hst_14402_14_acs_wfc_f775w_jd0q14ct_flc.fits ...
[Done]
Local Path Status Message URL
----------------------------------------------- -------- ------- ----
./mastDownload/HST/jd0q14ctq/jd0q14ctq_raw.fits COMPLETE None None
Local Path Status Message URL
----------------------------------------------- -------- ------- ----
./mastDownload/HST/jd0q14ctq/jd0q14ctq_flc.fits COMPLETE None None
Local Path Status Message URL
--------------------------------------------------------------------------------------------------- -------- ------- ----
./mastDownload/HST/hst_14402_14_acs_wfc_f775w_jd0q14ct/hst_14402_14_acs_wfc_f775w_jd0q14ct_flc.fits COMPLETE None None
Next, update and download the correct flat and dark reference files for the jd0q14ctq dataset from the Calibration Reference Data System (CRDS). We use the CRDS command line tools to do this.
os.environ['CRDS_SERVER'] = 'https://hst-crds.stsci.edu'
os.environ['CRDS_PATH'] = './crds_cache'
os.environ['jref'] = './crds_cache/references/hst/acs/'
!crds bestrefs --update-bestrefs --sync-references=1 --files jd0q14ctq_flc.fits
CRDS - INFO - No comparison context or source comparison requested.
CRDS - INFO - ===> Processing jd0q14ctq_flc.fits
CRDS - INFO - 0 errors
CRDS - INFO - 0 warnings
CRDS - INFO - 2 infos
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.
hdr = fits.getheader('jd0q14ctq_flc.fits')
flat = hdr['PFLTFILE'].split('$')[-1]
dkc = hdr['DRKCFILE'].split('$')[-1]
bias = hdr['BIASFILE'].split('$')[-1]
# flash = hdr['FLSHFILE'].split('$')[-1]
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.
# The jref environment variable gives the directory containing the reference files
flat_hdu = fits.open('{}/{}'.format(os.environ['jref'], flat))
flat_wfc1 = flat_hdu[4].data
flat_wfc2 = flat_hdu[1].data
dkc_hdu = fits.open('{}/{}'.format(os.environ['jref'], dkc))
dkc_wfc1 = dkc_hdu[4].data
dkc_wfc2 = dkc_hdu[1].data
# Darks can sometimes have negative pixels because they have been flash-corrected
# and CTE-corrected. Set all negative pixels to zero
dkc_wfc1[dkc_wfc1 < 0.] = 0.
dkc_wfc2[dkc_wfc2 < 0.] = 0.
bias_hdu = fits.open('{}/{}'.format(os.environ['jref'], bias))
err_bias_wfc1 = bias_hdu[5].data
err_bias_wfc2 = bias_hdu[2].data
dq_bias_wfc1 = bias_hdu[6].data
dq_bias_wfc2 = bias_hdu[3].data
# flash_dhu = fits.open('{}/{}'.format(os.environ['jref'], flash))
# flash_wfc1 = flash_hdu[4].data
# flash_wfc2 = flash_hdu[1].data
1. Create image of artificial stars#
We will need an image containing artificial stars on zero background for both options 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.
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.
There are many tools for generating artificial stars, including Tiny Tim, effective PSFs, or EPSFBuilder in photutils. A recent study of PSF models for ACS/WFC can be found here.
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\). We get use the shape of one of the flc image SCI extensions for creating the (x, y) coordinates of the sources.
wfc2 = fits.getdata('jd0q14ctq_flc.fits', ext=1)
shape = wfc2.shape
n_sources = 300
sources = make_model_params(shape, n_sources, x_name='x_mean', y_name='y_mean',
amplitude=(500, 30000), x_stddev=(1.05, 1.07),
y_stddev=(1.05, 1.07), theta=(0, np.pi), seed=12345)
sources
| id | x_mean | y_mean | amplitude | x_stddev | y_stddev | theta |
|---|---|---|---|---|---|---|
| int64 | float64 | float64 | float64 | float64 | float64 | float64 |
| 1 | 931.1683480255269 | 2034.731927781212 | 24273.448018412746 | 1.052614567617044 | 1.0578600277164938 | 2.8992449842520105 |
| 2 | 1297.4421594511477 | 2020.2558629061712 | 11822.754625107013 | 1.0618173409771416 | 1.0602199712414007 | 2.1780695595200688 |
| 3 | 3266.008913234879 | 1314.8224557352416 | 20899.070304107507 | 1.0507665561773338 | 1.0571366668824644 | 2.383984415966027 |
| 4 | 2769.939131395992 | 1030.403833222326 | 15048.61324113437 | 1.0517693372066452 | 1.0593415182072188 | 1.395289071630695 |
| 5 | 1601.9847192654192 | 975.5712053609202 | 13782.020382350489 | 1.0621928600284587 | 1.0641908208884874 | 0.5996291996338178 |
| 6 | 1363.205848540711 | 1243.9420055214678 | 4826.070921792934 | 1.0636999296992307 | 1.0581745784783634 | 2.5910405690665805 |
| 7 | 2450.6726546931295 | 922.0358345842421 | 9115.754462480229 | 1.0540239851398874 | 1.0546547351550888 | 0.9051036409307787 |
| 8 | 764.8632242328099 | 519.3794285853596 | 29956.815759113422 | 1.066687828209262 | 1.060442453559736 | 0.46925904081503583 |
| 9 | 2755.608756283889 | 873.1830758388562 | 12099.561207905457 | 1.0525415974521963 | 1.0510926327002308 | 1.458293270125343 |
| ... | ... | ... | ... | ... | ... | ... |
| 291 | 3049.199296016571 | 974.3854129537558 | 10182.939255592759 | 1.0582276669645014 | 1.060568620486222 | 0.8800304042809031 |
| 292 | 1068.9294421398708 | 185.2889387754592 | 29699.704174650862 | 1.067041046045279 | 1.0592933029553009 | 0.6668416749113799 |
| 293 | 459.72808011782627 | 479.4770609052098 | 9450.767076933364 | 1.0549456781778814 | 1.056729610877866 | 0.8851592290836784 |
| 294 | 3864.1154244755094 | 492.79078623907435 | 28586.58598534217 | 1.058411636622201 | 1.0555466310084305 | 0.4200575104110322 |
| 295 | 2799.982150530955 | 769.4783583080148 | 26401.06084867246 | 1.0654222515797471 | 1.059642783502198 | 0.48148852760241173 |
| 296 | 3924.704169661908 | 1586.5420950195162 | 18944.135655263068 | 1.066979179761192 | 1.0648042376434979 | 2.448456948684402 |
| 297 | 1349.672037398428 | 1889.2709182654376 | 23719.284446053513 | 1.0675980704498134 | 1.0681062036226 | 0.23461983014438023 |
| 298 | 787.4899431859599 | 834.4354849267897 | 6521.774161315369 | 1.0666277383620673 | 1.0691378501204618 | 2.776254516985 |
| 299 | 560.2867956283426 | 675.4838643564142 | 3249.2235656380913 | 1.0696288260546474 | 1.0601718945578338 | 0.08120462986196368 |
| 300 | 3864.0750442510675 | 485.298054308759 | 710.7189661087606 | 1.055301294889783 | 1.0694088760643832 | 2.214824097280904 |
Next, we 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.
model = Gaussian2D()
synth_stars_image = make_model_image(shape, model, sources,
x_name='x_mean', y_name='y_mean', progress_bar=True)
synth_stars_image = np.random.poisson(synth_stars_image)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(synth_stars_image, vmin=0, vmax=200, interpolation='nearest',
cmap='Greys_r', origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=10,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
[<matplotlib.lines.Line2D at 0x7f312972a690>]
Option A: Start with an observed FLC image#
In this Option, we add synthetic stars to the scene in an flc image and process it appropriately for use with the forward model. We use 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.
flc = fits.getdata('jd0q14ctq_flc.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(flc, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r', origin='lower')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
2A. Add artificial stars#
Add the image of artificial stars generated above to both CCDs of the flc image, and save it as a new file.
hdu = fits.open('jd0q14ctq_flc.fits')
wfc1 = hdu[4].data
wfc2 = hdu[1].data
wfc1 += synth_stars_image
wfc2 += synth_stars_image
hdu.writeto('jd0q14ctq_stars_flc.fits', overwrite=True)
Below we plot a section of the flc image with a few artificial stars circled in red.
flc_stars = fits.getdata('jd0q14ctq_stars_flc.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(flc_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
3A. Reverse the flat and dark correction#
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.
hdu = fits.open('jd0q14ctq_stars_flc.fits')
hdr = hdu[0].header
exptime = hdr['EXPTIME']
flashtime = hdr['FLASHDUR']
darktime = exptime + flashtime + 3
Next, we open the 47 Tuc image and obtain the SCI extensions of both CCDs. We 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.
wfc1 = hdu[4].data
wfc2 = hdu[1].data
wfc1 *= flat_wfc1
wfc2 *= flat_wfc2
wfc1 += np.random.poisson(dkc_wfc1*darktime)
wfc2 += np.random.poisson(dkc_wfc2*darktime)
# wfc1 += np.random.poisson(flash_wfc1*flashtime)
# wfc2 += np.random.poisson(flash_wfc2*flashtime)
hdu.writeto('jd0q14ctq_stars_pfl_dkc.fits', overwrite=True)
Finally, we update the header keyword PCTECORR to PERFORM, which is necessary for running the forward model.
fits.setval('jd0q14ctq_stars_pfl_dkc.fits', 'PCTECORR', value='PERFORM')
4A. Run CTE forward model#
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.
acscteforwardmodel.acscteforwardmodel('jd0q14ctq_stars_pfl_dkc.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Setting max threads to 4 out of 4 available
Trying to open jd0q14ctq_stars_pfl_dkc.fits...
Read in Primary header from jd0q14ctq_stars_pfl_dkc.fits...
CALBEG*** ACSCTE -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:49:21 UTC
Input jd0q14ctq_stars_pfl_dkc.fits
Output jd0q14ctq_stars_pfl_dkc_ctefmod.fits
Trying to open jd0q14ctq_stars_pfl_dkc.fits...
Read in Primary header from jd0q14ctq_stars_pfl_dkc.fits...
APERTURE WFCENTER
FILTER1 F775W
FILTER2 CLEAR2L
DETECTOR WFC
CCDTAB jref$72m1821dj_ccd.fits
CCDTAB PEDIGREE=inflight
CCDTAB DESCRIP =CCD table with updated readnoise values for CCDGAIN=2.-------------
CCDTAB DESCRIP =July 2009
PCTECORR PERFORM
PCTEFILE jref$8ch1518tj_cte.fits
PCTEFILE PEDIGREE=INFLIGHT 01/03/2002 22/07/2010
PCTEFILE DESCRIP =Parameters needed for gen3 pixel-based CTE correction -----------
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
(pctecorr) Parallel and Serial PCTETAB file auto-detected.
(pctecorr) Reading CTE parameters from PCTETAB file: 'jref$8ch1518tj_cte.fits'...
(pctecorr) Collecting data for Correction Type: parallel.
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
CTE_NAME: Par/Serial PixelCTE 2023
CTE_VER: 3.0
PCTERNOI: 4.300000
PCTENSMD: 0
PCTETRSH: -10
FIXROCR: 1
Opening jref$8ch1518tj_cte.fits[1] to read QPROF table.
CTEDATE0: 52334.9
CTEDATE1: 57710.4
PCTETLEN: 60
PCTENFOR: 5
PCTENPAR: 7
Opening jref$8ch1518tj_cte.fits[2] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 1.
Reading in image from CPROF EXTVER 1.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
(pctecorr) The parallel CTE processing parameters have been read.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.300000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 5
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 7
(pctecorr) CTE_FRAC: 0.951805
(pctecorr) NOTE: No serial CTE correction is done for any subarray data.
(pctecorr) Collecting data for Correction Type: serial
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
CTE_NAME: Par/Serial PixelCTE 2023
CTE_VER: 3.0
PCTERNOI: 4.300000
PCTENSMD: 0
PCTETRSH: -10
FIXROCR: 1
Opening jref$8ch1518tj_cte.fits[13] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[14] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 4.
Reading in image from CPROF EXTVER 4.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.300000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp C.
(pctecorr) Read noise level from CCDTAB: 4.050000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: C
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -23159.580078 (-0.003276%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: C
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp C.
(pctecorr) Read noise level from CCDTAB: 4.050000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -361068.468750 (-0.051091%)
(pctecorr) CTE run time for current chip: 46.98(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[17] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[18] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 5.
Reading in image from CPROF EXTVER 5.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.050000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp D.
(pctecorr) Read noise level from CCDTAB: 5.050000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: D
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -17034.068359 (-0.002019%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: D
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp D.
(pctecorr) Read noise level from CCDTAB: 5.050000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -414984.781250 (-0.049179%)
(pctecorr) CTE run time for current chip: 54.35(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[5] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[6] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 2.
Reading in image from CPROF EXTVER 2.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 5.050000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp A.
(pctecorr) Read noise level from CCDTAB: 4.350000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: A
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -21612.359375 (-0.003730%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: A
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp A.
(pctecorr) Read noise level from CCDTAB: 4.350000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -291053.562500 (-0.050237%)
(pctecorr) CTE run time for current chip: 49.46(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[9] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[10] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 3.
Reading in image from CPROF EXTVER 3.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.350000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp B.
(pctecorr) Read noise level from CCDTAB: 3.750000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: B
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -29917.306641 (-0.002641%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: B
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp B.
(pctecorr) Read noise level from CCDTAB: 3.750000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -474393.062500 (-0.041882%)
(pctecorr) CTE run time for current chip: 63.94(s) with 4 procs/threads
PCTECORR COMPLETE
End 02-Dec-2025 20:52:58 UTC
*** ACSCTE complete ***
os.rename('jd0q14ctq_stars_pfl_dkc_ctefmod.fits', 'jd0q14ctq_stars_ctefmod_blv_tmp.fits')
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 for a blv_tmp file, we will set every pixel to zero and calculate new values for each pixel according to
\(\mathrm{ERR} = \sqrt{\mathrm{SCI} + \mathrm{RN}^2 + (\mathrm{ERR}_{\mathrm{superbias}}g)^2}\),
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.
First, we access the header and SCI and ERR extensions of the forward-modeled data.
hdu = fits.open('jd0q14ctq_stars_ctefmod_blv_tmp.fits')
sci_wfc1 = hdu[4].data
sci_wfc2 = hdu[1].data
err_wfc1 = hdu[5].data
err_wfc2 = hdu[2].data
hdr = hdu[0].header
Next, we take the readnoise and gain values for each quadrant from the header.
rn_A = hdr['READNSEA']
rn_B = hdr['READNSEB']
rn_C = hdr['READNSEC']
rn_D = hdr['READNSED']
gain_A = hdr['ATODGNA']
gain_B = hdr['ATODGNB']
gain_C = hdr['ATODGNC']
gain_D = hdr['ATODGND']
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.
sci_wfc1_pos = np.copy(sci_wfc1)
sci_wfc2_pos = np.copy(sci_wfc2)
sci_wfc1_pos[sci_wfc1_pos < 0] = 0
sci_wfc2_pos[sci_wfc2_pos < 0] = 0
err_A = np.sqrt(sci_wfc1_pos[:, :2048] + rn_A**2 + (err_bias_wfc1[20:, 24:2072]*gain_A)**2)
err_B = np.sqrt(sci_wfc1_pos[:, 2048:] + rn_B**2 + (err_bias_wfc1[20:, 2072:-24]*gain_B)**2)
err_C = np.sqrt(sci_wfc2_pos[:, :2048] + rn_C**2 + (err_bias_wfc2[:-20, 24:2072]*gain_C)**2)
err_D = np.sqrt(sci_wfc2_pos[:, 2048:] + rn_D**2 + (err_bias_wfc2[:-20, 2072:-24]*gain_D)**2)
err_wfc1[:] = np.hstack((err_A, err_B))
err_wfc2[:] = np.hstack((err_C, err_D))
hdu.writeto('jd0q14ctq_stars_ctefmod_blv_tmp.fits', overwrite=True)
(Optional) 5A. Run CTE correction#
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.
fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'PCTECORR', value='PERFORM')
fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'NEXTEND', value=6)
acscte.acscte('jd0q14ctq_stars_ctefmod_blv_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Setting max threads to 4 out of 4 available
Trying to open jd0q14ctq_stars_ctefmod_blv_tmp.fits...
Read in Primary header from jd0q14ctq_stars_ctefmod_blv_tmp.fits...
CALBEG*** ACSCTE -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:52:58 UTC
Input jd0q14ctq_stars_ctefmod_blv_tmp.fits
Output jd0q14ctq_stars_ctefmod_blc_tmp.fits
Warning Output file `jd0q14ctq_stars_ctefmod_blc_tmp.fits' already exists.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blv_tmp.fits.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blv_tmp.fits.
ERROR: status = 1021
6A. Apply flat and dark correction#
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.
fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'DARKCORR', value='PERFORM')
fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLATCORR', value='PERFORM')
# fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLSHCORR', value='PERFORM')
acs2d.acs2d('jd0q14ctq_stars_ctefmod_blv_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open jd0q14ctq_stars_ctefmod_blv_tmp.fits...
Read in Primary header from jd0q14ctq_stars_ctefmod_blv_tmp.fits...
CALBEG*** ACS2D -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:52:58 UTC
Input jd0q14ctq_stars_ctefmod_blv_tmp.fits
Output jd0q14ctq_stars_ctefmod_flt.fits
Warning Output file `jd0q14ctq_stars_ctefmod_flt.fits' already exists.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blv_tmp.fits.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blv_tmp.fits.
ERROR: status = 1021
If the forward-modeled image was CTE-corrected in Step 7A, we run acs2d on the CTE-corrected image. The resulting filename will be *_flc.fits.
fits.setval('jd0q14ctq_stars_ctefmod_blc_tmp.fits', 'DARKCORR', value='PERFORM')
fits.setval('jd0q14ctq_stars_ctefmod_blc_tmp.fits', 'FLATCORR', value='PERFORM')
# fits.setval('jd0q14ctq_stars_ctefmod_blv_tmp.fits', 'FLSHCORR', value='PERFORM')
acs2d.acs2d('jd0q14ctq_stars_ctefmod_blc_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open jd0q14ctq_stars_ctefmod_blc_tmp.fits...
Read in Primary header from jd0q14ctq_stars_ctefmod_blc_tmp.fits...
CALBEG*** ACS2D -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:52:58 UTC
Input jd0q14ctq_stars_ctefmod_blc_tmp.fits
Output jd0q14ctq_stars_ctefmod_flc.fits
Warning Output file `jd0q14ctq_stars_ctefmod_flc.fits' already exists.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blc_tmp.fits.
ERROR: Error processing jd0q14ctq_stars_ctefmod_blc_tmp.fits.
ERROR: status = 1021
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, the flt and, if produced, the flc.
flt_stars = fits.getdata('jd0q14ctq_stars_ctefmod_flt.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(flt_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
flc_stars = fits.getdata('jd0q14ctq_stars_ctefmod_flc.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(flc_stars, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
Option B: Start with a synthetic image#
In this Option, we start with the raw file from the jd0q14ctq dataset and process the SCI extensions to make a completely synthetic dataset. We then process it appropriately for use in the forward model.
2B. Create a synthetic image#
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.
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.
acsccd.acsccd('jd0q14ctq_raw.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open jd0q14ctq_raw.fits...
Read in Primary header from jd0q14ctq_raw.fits...
CALBEG*** ACSCCD -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:53:00 UTC
Input jd0q14ctq_raw.fits
Output jd0q14ctq_blv_tmp.fits
Warning Output file `jd0q14ctq_blv_tmp.fits' already exists.
ERROR: Error processing jd0q14ctq_raw.fits.
ERROR: Error processing jd0q14ctq_raw.fits.
ERROR: status = 1021
Next, we obtain the SCI extensions from the blv_tmp file, and set the pixels to zero.
hdu = fits.open('jd0q14ctq_blv_tmp.fits')
wfc1 = hdu[4].data
wfc2 = hdu[1].data
wfc1[:] = np.zeros(shape)
wfc2[:] = np.zeros(shape)
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.
noise_image = make_noise_image(shape, distribution='poisson', mean=40, seed=12345)
wfc1 += noise_image + synth_stars_image
wfc2 += noise_image + synth_stars_image
hdu.writeto('synth.fits', overwrite=True)
Below we plot a portion of the synthetic image, with sources circled in red.
synth = fits.getdata('synth.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(synth, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
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 overhead (which depends on whether the data are post-flashed or not). Here we set EXPTIME to 300 seconds and FLASHDUR to 0 seconds. In principle one should retrieve the overheads from CCDTAB, but we provide a simpler approach here. Please note that the overhead times may change.
exptime = 300.
flashdur = 0.
hdu = fits.open('synth.fits')
hdr = hdu[0].header
hdr['EXPTIME'] = exptime
hdr['FLASHDUR'] = flashdur
if flashdur > 0:
overhead = 2.43
else:
overhead = 0.21
darktime = exptime + flashdur + overhead
We need to update the FITS header with the correct dark time for use in a later step. However, we leave off the overhead, because ACSCCD (run in a later step) will automatically append the overhead to the dark time in the header. We still use the darktime variable with overhead to manually add the dark current to our model below.
hdr['DARKTIME'] = darktime - overhead
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. 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.
Note that these reference files are specific to the anneal cycle 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 Step 2 which uses CRDS bestrefs to download the correct reference files.
wfc1 = hdu[4].data
wfc2 = hdu[1].data
wfc1 *= flat_wfc1
wfc2 *= flat_wfc2
wfc1 += np.random.poisson(dkc_wfc1*darktime)
wfc2 += np.random.poisson(dkc_wfc2*darktime)
# wfc1 += np.random.poisson(flash_wfc1*flashdur)
# wfc2 += np.random.poisson(flash_wfc2*flashdur)
hdu.writeto('synth_blc_tmp.fits', overwrite=True)
3B. Run CTE forward model#
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.
acscteforwardmodel.acscteforwardmodel('synth_blc_tmp.fits')
os.rename('synth_blc_tmp_ctefmod.fits', 'synth_ctefmod_blv_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Setting max threads to 4 out of 4 available
Trying to open synth_blc_tmp.fits...
Read in Primary header from synth_blc_tmp.fits...
CALBEG*** ACSCTE -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:53:03 UTC
Input synth_blc_tmp.fits
Output synth_blc_tmp_ctefmod.fits
Trying to open synth_blc_tmp.fits...
Read in Primary header from synth_blc_tmp.fits...
APERTURE WFCENTER
FILTER1 F775W
FILTER2 CLEAR2L
DETECTOR WFC
CCDTAB jref$72m1821dj_ccd.fits
CCDTAB PEDIGREE=inflight
CCDTAB DESCRIP =CCD table with updated readnoise values for CCDGAIN=2.-------------
CCDTAB DESCRIP =July 2009
PCTECORR PERFORM
PCTEFILE jref$8ch1518tj_cte.fits
PCTEFILE PEDIGREE=INFLIGHT 01/03/2002 22/07/2010
PCTEFILE DESCRIP =Parameters needed for gen3 pixel-based CTE correction -----------
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
(pctecorr) Parallel and Serial PCTETAB file auto-detected.
(pctecorr) Reading CTE parameters from PCTETAB file: 'jref$8ch1518tj_cte.fits'...
(pctecorr) Collecting data for Correction Type: parallel.
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
CTE_NAME: Par/Serial PixelCTE 2023
CTE_VER: 3.0
PCTERNOI: 4.300000
PCTENSMD: 0
PCTETRSH: -10
FIXROCR: 1
Opening jref$8ch1518tj_cte.fits[1] to read QPROF table.
CTEDATE0: 52334.9
CTEDATE1: 57710.4
PCTETLEN: 60
PCTENFOR: 5
PCTENPAR: 7
Opening jref$8ch1518tj_cte.fits[2] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 1.
Reading in image from CPROF EXTVER 1.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
(pctecorr) The parallel CTE processing parameters have been read.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.300000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 5
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 7
(pctecorr) CTE_FRAC: 0.951805
(pctecorr) NOTE: No serial CTE correction is done for any subarray data.
(pctecorr) Collecting data for Correction Type: serial
Trying to open jref$8ch1518tj_cte.fits...
Read in Primary header from jref$8ch1518tj_cte.fits...
CTE_NAME: Par/Serial PixelCTE 2023
CTE_VER: 3.0
PCTERNOI: 4.300000
PCTENSMD: 0
PCTETRSH: -10
FIXROCR: 1
Opening jref$8ch1518tj_cte.fits[13] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[14] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 4.
Reading in image from CPROF EXTVER 4.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.300000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp C.
(pctecorr) Read noise level from CCDTAB: 4.050000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: C
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -7937.993652 (-0.003588%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: C
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp C.
(pctecorr) Read noise level from CCDTAB: 4.050000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -300488.468750 (-0.135819%)
(pctecorr) CTE run time for current chip: 22.16(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[17] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[18] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 5.
Reading in image from CPROF EXTVER 5.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.050000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp D.
(pctecorr) Read noise level from CCDTAB: 5.050000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: D
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -6649.498047 (-0.002859%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: D
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp D.
(pctecorr) Read noise level from CCDTAB: 5.050000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -312125.125000 (-0.134230%)
(pctecorr) CTE run time for current chip: 22.22(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[5] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[6] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 2.
Reading in image from CPROF EXTVER 2.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 5.050000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp A.
(pctecorr) Read noise level from CCDTAB: 4.350000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: A
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -6761.397461 (-0.003201%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: A
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp A.
(pctecorr) Read noise level from CCDTAB: 4.350000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -301597.031250 (-0.142797%)
(pctecorr) CTE run time for current chip: 21.60(s) with 4 procs/threads
(pctecorr) Collecting data for Correction Type: serial
Opening jref$8ch1518tj_cte.fits[9] to read QPROF table.
CTEDATE0: 49000
CTEDATE1: 60500
PCTETLEN: 100
PCTENFOR: 1
PCTENPAR: 1
Opening jref$8ch1518tj_cte.fits[10] to read SCLBYCOL table.
Reading in image from RPROF EXTVER 3.
Reading in image from CPROF EXTVER 3.
Begin attempt to read CTE keywords from input image header. Missing CTE keywords
from input image header are not a fatal error as the values from PCTETAB will be used.
ERROR: Keyword = `PCTENSMD'.
ERROR: Keyword = `PCTETLEN'.
ERROR: Keyword = `PCTERNOI'.
ERROR: Keyword = `PCTENFOR'.
ERROR: Keyword = `PCTENPAR'.
ERROR: Keyword = `FIXROCR'.
End attempt to read CTE keywords from input image header.
Warning (pctecorr) IGNORING read noise level PCTERNOI from PCTETAB: 4.350000. Using amp dependent values from CCDTAB instead
(pctecorr) Readout simulation forward modeling iterations PCTENFOR: 1
(pctecorr) Number of iterations used in the parallel transfer PCTENPAR: 1
(pctecorr) CTE_FRAC: 0.734902
(pctecorr) The serial CTE processing parameters have been read.
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type serial for amp B.
(pctecorr) Read noise level from CCDTAB: 3.750000.
(pctecorr) Invoking rotation for CTE Correction Type: serial
(pctecorr) Rotation for Amp: B
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -11495.261719 (-0.005086%)
(pctecorr) Invoking de-rotation for CTE Correction Type: serial
(pctecorr) Derotation for Amp: B
(pctecorr) Using multiprocessing provided by OpenMP inside CTE routine.
(pctecorr) Performing CTE correction type parallel for amp B.
(pctecorr) Read noise level from CCDTAB: 3.750000.
(pctecorr) ...complete.
(pctecorr) Creating charge trap image...
(pctecorr) Time taken to populate pixel trap map image: 0.01(s) with 4 threads
(pctecorr) ...complete.
(pctecorr) Running forward model simulation...
(pctecorr) ...complete.
(pctecorr) Total count difference (corrected-raw) incurred from correction: -311609.406250 (-0.137879%)
(pctecorr) CTE run time for current chip: 22.72(s) with 4 procs/threads
PCTECORR COMPLETE
End 02-Dec-2025 20:54:33 UTC
*** ACSCTE complete ***
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.
rn_A = hdr['READNSEA']
rn_B = hdr['READNSEB']
rn_C = hdr['READNSEC']
rn_D = hdr['READNSED']
img_rn_A = make_noise_image((shape[0], int(shape[1]/2)), distribution='gaussian',
mean=0., stddev=rn_A)
img_rn_B = make_noise_image((shape[0], int(shape[1]/2)), distribution='gaussian',
mean=0., stddev=rn_B)
img_rn_C = make_noise_image((shape[0], int(shape[1]/2)), distribution='gaussian',
mean=0., stddev=rn_C)
img_rn_D = make_noise_image((shape[0], int(shape[1]/2)), distribution='gaussian',
mean=0., stddev=rn_D)
wfc1_rn = np.hstack((img_rn_A, img_rn_B))
wfc2_rn = np.hstack((img_rn_C, img_rn_D))
hdu = fits.open('synth_ctefmod_blv_tmp.fits')
wfc1 = hdu[4].data
wfc2 = hdu[1].data
wfc1 += wfc1_rn
wfc2 += wfc2_rn
hdu.writeto('synth_ctefmod_rn_blv_tmp.fits', overwrite=True)
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
\(\mathrm{ERR} = \sqrt{\mathrm{SCI} + \mathrm{RN}^2 + (\mathrm{ERR}_{\mathrm{superbias}}g)^2}\),
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.
First, we access the header and SCI and ERR extensions of the forward-modeled data.
hdu = fits.open('synth_ctefmod_rn_blv_tmp.fits')
sci_wfc1 = hdu[4].data
sci_wfc2 = hdu[1].data
err_wfc1 = hdu[5].data
err_wfc2 = hdu[2].data
hdr = hdu[0].header
Next, we take the readnoise and gain values for each quadrant from the header.
rn_A = hdr['READNSEA']
rn_B = hdr['READNSEB']
rn_C = hdr['READNSEC']
rn_D = hdr['READNSED']
gain_A = hdr['ATODGNA']
gain_B = hdr['ATODGNB']
gain_C = hdr['ATODGNC']
gain_D = hdr['ATODGND']
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.
sci_wfc1_pos = np.copy(sci_wfc1)
sci_wfc2_pos = np.copy(sci_wfc2)
sci_wfc1_pos[sci_wfc1_pos < 0] = 0
sci_wfc2_pos[sci_wfc2_pos < 0] = 0
# The superbias ERR arrays contain 20 rows of virtual overscan at the edge of
# each CCD furthest from the amplifier and 24 columns of physical prescan on the
# left and right edges.
err_A = np.sqrt(sci_wfc1_pos[:, :2048] + rn_A**2 + (err_bias_wfc1[20:, 24:2072]*gain_A)**2)
err_B = np.sqrt(sci_wfc1_pos[:, 2048:] + rn_B**2 + (err_bias_wfc1[20:, 2072:-24]*gain_B)**2)
err_C = np.sqrt(sci_wfc2_pos[:, :2048] + rn_C**2 + (err_bias_wfc2[:-20, 24:2072]*gain_C)**2)
err_D = np.sqrt(sci_wfc2_pos[:, 2048:] + rn_D**2 + (err_bias_wfc2[:-20, 2072:-24]*gain_D)**2)
err_wfc1[:] = np.hstack((err_A, err_B))
err_wfc2[:] = np.hstack((err_C, err_D))
hdu.writeto('synth_ctefmod_rn_blv_tmp.fits', overwrite=True)
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.
This step will also add the proper overhead to DARKTIME header keyword, but only if using CALACS v10.3.3 or later. We first check the version.
os.system('calacs.e --version')
10.4.0 (07-May-2024)
0
If your version of CALCACS is prior to v10.3.3, please update. Now let’s run ACSCCD.
os.rename('synth_ctefmod_rn_blv_tmp.fits', 'synth_ctefmod_rn_raw.fits')
fits.setval('synth_ctefmod_rn_raw.fits', 'DQICORR', value='PERFORM')
fits.setval('synth_ctefmod_rn_raw.fits', 'SINKCORR', value='PERFORM')
acsccd.acsccd('synth_ctefmod_rn_raw.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open synth_ctefmod_rn_raw.fits...
Read in Primary header from synth_ctefmod_rn_raw.fits...
CALBEG*** ACSCCD -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:54:34 UTC
Input synth_ctefmod_rn_raw.fits
Output synth_ctefmod_rn_blv_tmp.fits
Trying to open synth_ctefmod_rn_raw.fits...
Read in Primary header from synth_ctefmod_rn_raw.fits...
APERTURE WFCENTER
FILTER1 F775W
FILTER2 CLEAR2L
DETECTOR WFC
CCDTAB jref$72m1821dj_ccd.fits
CCDTAB PEDIGREE=inflight
CCDTAB DESCRIP =CCD table with updated readnoise values for CCDGAIN=2.-------------
CCDTAB DESCRIP =July 2009
Warning Could not find appropriate row from OSCNTAB.
Warning Could not find appropriate row from OSCNTAB.
DQICORR PERFORM
DQITAB jref$25g1256nj_bpx.fits
DQITAB PEDIGREE=INFLIGHT 30/03/2002 30/05/2002
DQITAB DESCRIP =FITS reference table for bad pixel locations on ACS WFC
DQICORR COMPLETE
BIASCORR OMIT
BIASCORR COMPLETE
BLEVCORR OMIT
Full Frame adjusted Darktime: 300.000000
DARKTIME from SCI header: 300.000000 Offset from CCDTAB: 0.000000 Final DARKTIME: 300.000000
Warning
No Full-well saturation flagging being performed for imset 1.
Warning
No Full-well saturation flagging being performed for imset 2.
Uncertainty array initialized,
readnoise =4.35,3.75,4.05,5.05
gain =2.02,1.886,2.017,2.011
default bias levels =4242,4060.6,4481.8,4645.4
SINKCORR PERFORM
SNKCFILE jref$25e1534hj_snk.fits
SNKCFILE PEDIGREE=INFLIGHT 12/02/2016 09/03/2016
SNKCFILE DESCRIP =Sink pixel reference file ----------------------------
SINKCORR COMPLETE
End 02-Dec-2025 20:54:34 UTC
*** ACSCCD complete ***
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.
hdu = fits.open('synth_ctefmod_rn_blv_tmp.fits')
dq_wfc1 = hdu[6].data
dq_wfc2 = hdu[3].data
dq_wfc1[:] = np.bitwise_or(dq_wfc1, dq_bias_wfc1[20:, 24:-24])
dq_wfc2[:] = np.bitwise_or(dq_wfc2, dq_bias_wfc2[:-20, 24:-24])
Also, acsccd assumes the input image is in DN and converts it to counts by multiplying by the gain. We defined our model in electrons though, so the acsccd conversion to electrons was unnecessary. We divide by the gains to fix this and replace the image.
sci_wfc1 = hdu[4].data
sci_wfc2 = hdu[1].data
sci_wfc1[:, :2048] /= gain_A
sci_wfc1[:, 2048:] /= gain_B
sci_wfc2[:, :2048] /= gain_C
sci_wfc2[:, 2048:] /= gain_D
err_wfc1 = hdu[5].data
err_wfc2 = hdu[2].data
err_wfc1[:, :2048] /= gain_A
err_wfc1[:, 2048:] /= gain_B
err_wfc2[:, :2048] /= gain_C
err_wfc2[:, 2048:] /= gain_D
hdu.writeto('synth_ctefmod_rn_blv_tmp.fits', overwrite=True)
4B. (Optional) Run CTE correction#
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.
fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'PCTECORR', value='PERFORM')
acscte.acscte('synth_ctefmod_rn_blv_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Setting max threads to 4 out of 4 available
Trying to open synth_ctefmod_rn_blv_tmp.fits...
Read in Primary header from synth_ctefmod_rn_blv_tmp.fits...
CALBEG*** ACSCTE -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:54:35 UTC
Input synth_ctefmod_rn_blv_tmp.fits
Output synth_ctefmod_rn_blc_tmp.fits
Warning Output file `synth_ctefmod_rn_blc_tmp.fits' already exists.
ERROR: Error processing synth_ctefmod_rn_blv_tmp.fits.
ERROR: Error processing synth_ctefmod_rn_blv_tmp.fits.
ERROR: status = 1021
5B. Apply flat and dark correction#
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.
fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'DARKCORR', value='PERFORM')
fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'FLATCORR', value='PERFORM')
# fits.setval('synth_ctefmod_rn_blv_tmp.fits', 'FLSHCORR', value='PERFORM')
acs2d.acs2d('synth_ctefmod_rn_blv_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open synth_ctefmod_rn_blv_tmp.fits...
Read in Primary header from synth_ctefmod_rn_blv_tmp.fits...
CALBEG*** ACS2D -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:54:35 UTC
Input synth_ctefmod_rn_blv_tmp.fits
Output synth_ctefmod_rn_flt.fits
Warning Output file `synth_ctefmod_rn_flt.fits' already exists.
ERROR: Error processing synth_ctefmod_rn_blv_tmp.fits.
ERROR: Error processing synth_ctefmod_rn_blv_tmp.fits.
ERROR: status = 1021
If the forward-modeled image was CTE-corrected in Step 6, we run acs2d on the CTE-corrected image. The resulting filename will be *_flc.fits.
fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'DARKCORR', value='PERFORM')
fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'FLATCORR', value='PERFORM')
# fits.setval('synth_ctefmod_rn_blc_tmp.fits', 'FLSHCORR', value='PERFORM')
acs2d.acs2d('synth_ctefmod_rn_blc_tmp.fits')
git tag: 0090c701-dirty
git branch: HEAD
HEAD @: 0090c701d894003cfc690e9f8d5fde81e6939090
Trying to open synth_ctefmod_rn_blc_tmp.fits...
Read in Primary header from synth_ctefmod_rn_blc_tmp.fits...
CALBEG*** ACS2D -- Version 10.4.0 (07-May-2024) ***
Begin 02-Dec-2025 20:54:35 UTC
Input synth_ctefmod_rn_blc_tmp.fits
Output synth_ctefmod_rn_flc.fits
Warning Output file `synth_ctefmod_rn_flc.fits' already exists.
ERROR: Error processing synth_ctefmod_rn_blc_tmp.fits.
ERROR: Error processing synth_ctefmod_rn_blc_tmp.fits.
ERROR: status = 1021
The image(s) are now prepared for further analysis appropriate for the user’s science. The cells below plot a portion of the final images, the flt and, if produced, the flc.
synth_ctefmod = fits.getdata('synth_ctefmod_rn_flt.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(synth_ctefmod, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
synth_ctefmod_flc = fits.getdata('synth_ctefmod_rn_flc.fits', ext=1)
fig, ax = plt.subplots(1, 1, figsize=(9, 4))
ax.imshow(synth_ctefmod_flc, vmin=0, vmax=200, interpolation='nearest', cmap='Greys_r',
origin='lower')
ax.plot(sources['x_mean'], sources['y_mean'], marker='o', markersize=20,
markerfacecolor='none', markeredgecolor='red', linestyle='none')
ax.set_xlim(2000, 2800)
ax.set_ylim(800, 1300)
(800.0, 1300.0)
About this Notebook#
Author: Jenna Ryon, ACS Instrument Team
Updated On: 04/21/2022
For more help:#
More details may be found on the ACS website and in the ACS Instrument and Data Handbooks.
Please visit the HST Help Desk. Through the help desk portal, you can explore the HST Knowledge Base and request additional help from experts.
