Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: JP-3622 Update refpix step for NIR detectors to use convolution kernel #8726

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e646d20
initial code
penaguerrero Aug 26, 2024
8868e05
Merge branch 'master' into jp3622
penaguerrero Aug 27, 2024
503b8cb
Merge branch 'master' into jp3622
penaguerrero Aug 28, 2024
ee89fd2
minor change
penaguerrero Aug 28, 2024
f42375b
testing
penaguerrero Aug 28, 2024
afd5ccd
continuing with implementation
penaguerrero Aug 29, 2024
0499d27
add message when processing zero frame
penaguerrero Aug 30, 2024
29da573
Merge branch 'master' into jp3622
penaguerrero Aug 30, 2024
8875b13
adding the PR number
penaguerrero Aug 30, 2024
dfe6a59
Merge branch 'master' into jp3622
penaguerrero Sep 4, 2024
cbbecb0
Merge branch 'master' into jp3622
penaguerrero Sep 5, 2024
c83c338
adding unit tests
penaguerrero Sep 5, 2024
be3c9e3
adding missing argument
penaguerrero Sep 5, 2024
f81c798
Merge branch 'master' into jp3622
penaguerrero Sep 5, 2024
5d6798a
adding documentation
penaguerrero Sep 6, 2024
98ce09b
Merge branch 'master' into jp3622
penaguerrero Sep 9, 2024
d031c43
Merge branch 'master' into jp3622
penaguerrero Sep 11, 2024
2aa98c0
Merge branch 'master' into jp3622
penaguerrero Sep 11, 2024
89374dc
smoothing integration of code
penaguerrero Sep 11, 2024
06b21ec
Merge branch 'master' into jp3622
penaguerrero Sep 11, 2024
3c00577
fixing test to match changes
penaguerrero Sep 11, 2024
52a3dad
Merge branch 'master' into jp3622
penaguerrero Sep 12, 2024
d629b37
Merge branch 'master' into jp3622
penaguerrero Sep 13, 2024
7533039
Merge branch 'master' into jp3622
penaguerrero Sep 16, 2024
0c39e5b
Merge branch 'master' into jp3622
penaguerrero Sep 17, 2024
1b0310c
Merge branch 'master' into jp3622
penaguerrero Sep 18, 2024
4339dff
Merge branch 'master' into jp3622
penaguerrero Sep 19, 2024
c1dbe1c
Merge branch 'master' into jp3622
penaguerrero Sep 20, 2024
09eb003
Merge branch 'master' into jp3622
penaguerrero Sep 20, 2024
103da88
Merge branch 'master' into jp3622
penaguerrero Sep 23, 2024
f426fbb
Merge branch 'main' into jp3622
penaguerrero Sep 23, 2024
a4eb93f
adding PR changes
penaguerrero Sep 23, 2024
d3c67fc
Merge branch 'main' into jp3622
penaguerrero Sep 24, 2024
53cc1d5
Merge branch 'main' into jp3622
penaguerrero Sep 24, 2024
67072b7
Merge branch 'main' into jp3622
penaguerrero Sep 25, 2024
46c219b
Merge branch 'main' into jp3622
penaguerrero Sep 30, 2024
76eb300
Merge branch 'main' into jp3622
penaguerrero Oct 1, 2024
64ca640
Merge branch 'main' into jp3622
penaguerrero Oct 1, 2024
f16cc7a
Merge branch 'main' into jp3622
penaguerrero Oct 2, 2024
846004c
Merge branch 'main' into jp3622
penaguerrero Oct 7, 2024
0e49387
Merge branch 'main' into jp3622
penaguerrero Oct 10, 2024
1d76a49
Merge branch 'main' into jp3622
penaguerrero Oct 14, 2024
f0a511a
Merge branch 'main' into jp3622
penaguerrero Oct 22, 2024
1c4d97b
setting default for use_conv_kernel to False
penaguerrero Oct 22, 2024
9e8f04a
Merge branch 'main' into jp3622
penaguerrero Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ ramp_fitting

- Updated the flow of the detector 1 pipeline when selecting the ``LIKELY`` algorithm
for ramp fitting. The ramps must contain a minimum number of groups (4).[#8631]

refpix
------

- Add optimized convolution kernel instead of the running median for NIR
fullframe data. [#8726]
zacharyburnett marked this conversation as resolved.
Show resolved Hide resolved

- Removed unnecessary copies, and created a single copy at step.py level. [#8676]

Expand Down
1 change: 1 addition & 0 deletions changes/8726.refpix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add optimized convolution kernel instead of the running median for NIR fullframe data.
27 changes: 27 additions & 0 deletions docs/jwst/refpix/arguments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,30 @@ in IRS2 mode will be processed along with the normal pixels and preserved
in the output. This option is intended for calibration or diagnostic reductions
only. For normal science operation, this argument should always be False,
so that interleaved pixels are stripped before continuing processing.

* ``--use_conv_kernel``

If the ``use_conv_kernel`` argument is set to False, all NIR full-frame data,
will be processed using the running median and the side-pixel correction. The
default value is set to True, which turns off the side-pixed correction and
use an optimized convolution kernel instead of the running median.

* ``--sigreject``

The ``sigreject`` argument is the number of sigmas to reject as outliers in the
optimized convolution kernel algorithm. The value is expected to be a float.

* ``--gaussmooth``

The ``gaussmooth`` argument is the width of Gaussian smoothing kernel to use as
a low-pass filter. The numerical value is expected to be a float.

* ``--halfwidth``

The ``halfwidth`` argument is the half-width of convolution kernel to build. The
numerical value is expected to be an integer.

* ``--user_supplied_reffile``

The ``user_supplied_reffile`` argument is the name of the ASDF user-supplied
reference file for the optimized convolution kernel algorithm.
2 changes: 2 additions & 0 deletions docs/jwst/refpix/description.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ NIR Detector Data
(set by the step parameter ``side_gain``, which defaults to 1.0) is
subtracted from the full group on a row-by-row basis. Note that the ``odd_even_rows``
parameter is ignored for NIR data when the side reference pixels are processed.
If the ``--use_conv_kernel`` option is set, the side-pixel correction will be
turned off and instead, an optimized convolution kernel will be used.
#. Transform the data back to the JWST focal plane, or DMS, frame.

MIR Detector Data
Expand Down
187 changes: 187 additions & 0 deletions jwst/refpix/optimized_convolution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#
# Module for using Reference Pixels to improve the 1/f noise, to be
# used be only for non-IRS2 NIR data
#

import logging
import numpy as np

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)


def make_kernels(conv_kernel_model, detector, gaussmooth, halfwidth):
"""
Make convolution kernels reference file's Fourier coefficients.

Parameters:
-----------

conv_kernel_model : `~jwst.datamodels.ConvKernelModel`
Data model containing the Fourier coefficients from the reference files

detector : str
Name of the detector of the input data

gaussmooth : float
Width of Gaussian smoothing kernel to use as a low-pass filter on reference file's coefficients

halfwidth : int
Half-width of convolution kernel to build from reference file's coefficients

Returns:
--------

kernels: list
Contains the kernels appropriate for convolution with the left and right reference pixels

"""

gamma, zeta = get_conv_kernel_coeffs(conv_kernel_model, detector)
if gamma is None or zeta is None:
log.info(f'Optimized convolution kernel coefficients NOT found for detector {detector}')
return None

Check warning on line 43 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L40-L43

Added lines #L40 - L43 were not covered by tests

kernel_left = []
kernel_right = []
for chan in range(gamma.shape[0]):
n = len(gamma[chan]) - 1
kernel_left = np.fft.fftshift(np.fft.irfft(gamma[chan]))[n - halfwidth:n + halfwidth + 1]
kernel_right = np.fft.fftshift(np.fft.irfft(zeta[chan]))[n - halfwidth:n + halfwidth + 1]

Check warning on line 50 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L45-L50

Added lines #L45 - L50 were not covered by tests

x = np.arange(-halfwidth, halfwidth + 1)
window = np.exp(-x ** 2 / (2 * gaussmooth ** 2))
window /= np.sum(window)

Check warning on line 54 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L52-L54

Added lines #L52 - L54 were not covered by tests

kernel_right = np.convolve(kernel_right, window, mode='same')
kernel_left = np.convolve(kernel_left, window, mode='same')

Check warning on line 57 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L56-L57

Added lines #L56 - L57 were not covered by tests

kernel_right += kernel_right
kernel_left += kernel_left

Check warning on line 60 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L59-L60

Added lines #L59 - L60 were not covered by tests

return [kernel_left, kernel_right]

Check warning on line 62 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L62

Added line #L62 was not covered by tests


def get_conv_kernel_coeffs(conv_kernel_model, detector):
"""
Get the convolution kernels coefficients from the reference file

Parameters:
-----------

conv_kernel_model : `~jwst.datamodels.ConvKernelModel`
Data model containing the Fourier coefficients from the reference files

detector : str
Name of the detector of the input data

Returns:
--------

gamma: numpy array
Fourier coefficients

zeta: numpy array
Fourier coefficients
"""
mdl_dict = conv_kernel_model.to_flat_dict()
gamma, zeta = None, None
for item in mdl_dict:
det = item.split(sep='.')[0]
if detector.lower() == det.lower():
arr_name = item.split(sep='.')[1]
if arr_name == 'gamma':
gamma = np.array(mdl_dict[item])
elif arr_name == 'zeta':
zeta = np.array(mdl_dict[item])
if gamma is not None and zeta is not None:
break
return gamma, zeta

Check warning on line 99 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L87-L99

Added lines #L87 - L99 were not covered by tests


def apply_conv_kernel(data, kernels, zeroim, sigreject=4.0):
"""
Apply the convolution kernel.

Parameters:
-----------

data : 2-D numpy array
Data to be corrected

kernels : list
List containing the left and right kernels

zeroim : 2-D numpy array
First group of first integration, to find outliers

sigreject: float
Number of sigmas to reject as outliers

Returns:
--------

data : 2-D numpy array
Data model with convolution
"""
data = data.astype(float)
npix = data.shape[-1]

Check warning on line 128 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L127-L128

Added lines #L127 - L128 were not covered by tests

kernels_l, kernels_r = kernels
nchan = len(kernels_l)

Check warning on line 131 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L130-L131

Added lines #L130 - L131 were not covered by tests

# The subtraction below is needed to flag outliers in the reference pixels.
zeroim = zeroim.astype(float)
data -= zeroim

Check warning on line 135 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L134-L135

Added lines #L134 - L135 were not covered by tests

L = data[:, :4]
R = data[:, -4:]

Check warning on line 138 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L137-L138

Added lines #L137 - L138 were not covered by tests

# Find the approximate standard deviations of the reference pixels
# using an outlier-robust median approach. Mask pixels that differ
# by more than sigreject sigma from this level.
# NOTE: The Median Absolute Deviation (MAD) is calculated as the
# median of the absolute differences between data values and their
# median. For normal distribution MAD is equal to 1.48 times the
# standard deviation but is a more robust estimate of the dispersion
# of data values.The calculation of MAD is straightforward but
# time-consuming, especially if MAD estimates are needed for the
# local environment around every pixel of a large image. The
# calculation is MAD = np.median(np.abs(x-np.median(x))).
# Reference: https://www.interstellarmedium.org/numerical_tools/mad/
MAD = 1.48
medL = np.median(L)
sigL = MAD * np.median(np.abs(L - medL))
medR = np.median(R)
sigR = MAD * np.median(np.abs(R - medR))

Check warning on line 156 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L152-L156

Added lines #L152 - L156 were not covered by tests

# nL and nR are the number of good reference pixels in the left and right
# channel in each row. These will be used in lieu of replacing the values
# of those pixels directly.
goodL = 1 * (np.abs(L - medL) <= sigreject * sigL)
nL = np.sum(goodL, axis=1)
goodR = 1 * (np.abs(R - medR) <= sigreject * sigR)
nR = np.sum(goodR, axis=1)

Check warning on line 164 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L161-L164

Added lines #L161 - L164 were not covered by tests

# Average of the left and right channels, replacing masked pixels with zeros.
# Appropriate normalization factors will be computed later.
L = np.sum(L * goodL, axis=1) / 4
R = np.sum(R * goodR, axis=1) / 4
for chan in range(nchan):
kernel_l = kernels_l[chan]
kernel_r = kernels_r[chan]

Check warning on line 172 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L168-L172

Added lines #L168 - L172 were not covered by tests

# Compute normalizations so that we don't have to directly
# replace the values of flagged/masked reference pixels.
normL = np.convolve(np.ones(nL.shape), kernel_l, mode='same')
normL /= np.convolve(nL / 4, kernel_l, mode='same')
normR = np.convolve(np.ones(nR.shape), kernel_r, mode='same')
normR /= np.convolve(nR / 4, kernel_r, mode='same')
template = np.convolve(L, kernel_l, mode='same') * normL
template += np.convolve(R, kernel_r, mode='same') * normR
data[:, chan * npix * 3 // 4:(chan + 1) * npix * 3 // 4] -= template[:, np.newaxis]

Check warning on line 182 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L176-L182

Added lines #L176 - L182 were not covered by tests

data += zeroim
log.debug('Optimized convolution kernel applied')
return data

Check warning on line 186 in jwst/refpix/optimized_convolution.py

View check run for this annotation

Codecov / codecov/patch

jwst/refpix/optimized_convolution.py#L184-L186

Added lines #L184 - L186 were not covered by tests

Loading
Loading