Skip to content

Commit

Permalink
fixed slit flat field
Browse files Browse the repository at this point in the history
  • Loading branch information
gbrammer committed Nov 18, 2024
1 parent dbbb839 commit 49c8296
Showing 1 changed file with 231 additions and 1 deletion.
232 changes: 231 additions & 1 deletion msaexp/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,12 @@ def drizzled_hdu_figure(
lw=2,
)
ap.step(
ptab["pfit"] / pmax, xpr, color="coral", where="pre", alpha=0.5, lw=1
ptab["pfit"] / pmax,
xpr,
color="coral",
where="pre",
alpha=0.5,
lw=1,
)
ap.fill_betweenx(
xpr + 0.5, xpr * 0.0, ptab["pfit"] / pmax, color="coral", alpha=0.2
Expand Down Expand Up @@ -2614,6 +2619,231 @@ def get_prism_wave_bar_correction(
return bar, is_wrapped


def slit_shutter_scale(slit):
"""
Pixel scale of the ``slit_frame`` coordinate
Parameters
----------
slit : `~jwst.datamodels.SlitModel`
Slitlet data object
Returns
-------
pix_scale : float
delta ``slit_frame`` / delta pixel.
"""
sh = slit.data.shape
wcs = slit.meta.wcs
d2s = wcs.get_transform("detector", "slit_frame")

Check warning on line 2639 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2637-L2639

Added lines #L2637 - L2639 were not covered by tests

x0 = d2s(sh[1] // 2, sh[0] // 2)
x1 = d2s(sh[1] // 2, sh[0] // 2 + 1)

Check warning on line 2642 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2641-L2642

Added lines #L2641 - L2642 were not covered by tests

dx = np.array(x1) - np.array(x0)
pix_scale = np.sqrt(dx[0] ** 2 + dx[1] ** 2)

Check warning on line 2645 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2644-L2645

Added lines #L2644 - L2645 were not covered by tests

return pix_scale

Check warning on line 2647 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2647

Added line #L2647 was not covered by tests


def get_slit_coordinates(slit, trace_with_ypos=False, **kwargs):
"""
Get wavelength and cross-dispersion coordinate arrays for a 2D slitlet
Parameters
----------
slit : `~jwst.datamodels.SlitModel`
Slitlet data object
trace_with_ypos : bool
Include source y position in trace calculation
Returns
-------
wave : array-like
Wavelengths, microns
slit_frame_y : array-like
``slit_frame`` cross dispersion coordinate
yslit : array-like
Pixel offset relative to the trace center
"""
sh = slit.data.shape
yp, xp = np.indices(sh)

Check warning on line 2674 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2673-L2674

Added lines #L2673 - L2674 were not covered by tests

_res = slit_trace_center(

Check warning on line 2676 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2676

Added line #L2676 was not covered by tests
slit,
with_source_xpos=False,
with_source_ypos=trace_with_ypos,
index_offset=0.0,
)

_xtr, _ytr, _wtr, slit_ra, slit_dec = _res

Check warning on line 2683 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2683

Added line #L2683 was not covered by tests

xslit = xp
yslit = yp - _ytr
ypix = yp

Check warning on line 2687 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2685-L2687

Added lines #L2685 - L2687 were not covered by tests

wcs = slit.meta.wcs
d2w = wcs.get_transform("detector", "world")

Check warning on line 2690 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2689-L2690

Added lines #L2689 - L2690 were not covered by tests

_ypi, _xpi = np.indices(slit.data.shape)
_ras, _des, _wave = d2w(_xpi, _ypi)

Check warning on line 2693 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2692-L2693

Added lines #L2692 - L2693 were not covered by tests

d2s = wcs.get_transform("detector", "slit_frame")
_sx, _sy, _slam = np.array(d2s(_xpi, _ypi))
slit_frame_y = _sy

Check warning on line 2697 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2695-L2697

Added lines #L2695 - L2697 were not covered by tests

return _wave, slit_frame_y, yslit

Check warning on line 2699 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2699

Added line #L2699 was not covered by tests


def get_slit_data(slit, wrap=True, **kwargs):
"""
Parse slit coordinates and attributes
Parameters
----------
slit : `~jwst.datamodels.SlitModel`
Slitlet data object
wrap : bool
Parameter for `msaexp.utils.get_prism_wave_bar_correction`
Returns
-------
data : dict
Slit data
"""
slx = slice(slit.xstart - 1, slit.xstart - 1 + slit.xsize)
sly = slice(slit.ystart - 1, slit.ystart - 1 + slit.ysize)

Check warning on line 2721 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2720-L2721

Added lines #L2720 - L2721 were not covered by tests

wave, slit_frame_y, yslit = get_slit_coordinates(slit, **kwargs)
sh = wave.shape

Check warning on line 2724 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2723-L2724

Added lines #L2723 - L2724 were not covered by tests

shutter_scale = slit_shutter_scale(slit)

Check warning on line 2726 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2726

Added line #L2726 was not covered by tests

dy = 0.0

Check warning on line 2728 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2728

Added line #L2728 was not covered by tests

shutter_y = (slit_frame_y / shutter_scale + dy) / 5.0

Check warning on line 2730 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2730

Added line #L2730 was not covered by tests

if slit.meta.exposure.type == "NRS_FIXEDSLIT":
bar = np.ones_like(wave).reshape(sh)
bar_wrapped = False

Check warning on line 2734 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2732-L2734

Added lines #L2732 - L2734 were not covered by tests
else:
bar, bar_wrapped = get_prism_wave_bar_correction(

Check warning on line 2736 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2736

Added line #L2736 was not covered by tests
shutter_y.flatten(),
wave.flatten(),
num_shutters=np.minimum(len(slit.shutter_state), 3),
wrap=wrap,
)
bar = bar.reshape(sh)

Check warning on line 2742 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2742

Added line #L2742 was not covered by tests

corr = slit.data * 1 / bar
msk = ~np.isfinite(corr + wave + bar)

Check warning on line 2745 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2744-L2745

Added lines #L2744 - L2745 were not covered by tests

corr[msk] = 0
wave[msk] = 0
bar[msk] = 0

Check warning on line 2749 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2747-L2749

Added lines #L2747 - L2749 were not covered by tests

data = {

Check warning on line 2751 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2751

Added line #L2751 was not covered by tests
"wave": wave,
"slit_frame_y": slit_frame_y,
"shutter_y": shutter_y,
"yslit": yslit,
"shape": sh,
"corr": corr,
"bar": bar,
"slx": slx,
"sly": sly,
"shutter_state": slit.shutter_state,
"num_shutters": len(slit.shutter_state),
"bar_wrapped": bar_wrapped,
}

return data

Check warning on line 2766 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2766

Added line #L2766 was not covered by tests


def fixed_slit_flat_field(
slit, apply=True, verbose=True, force=False, **kwargs
):
"""
Fixed slit cross-dispersion profile flat field
Parameters
----------
slit : `~jwst.datamodels.SlitModel`
Slitlet data object
apply : bool
Apply to ``slit.data`` attribute
force : bool
Apply even if ``slit.flat_profile`` already found
Returns
-------
flat_profile : array-like
2D flat-field profile
"""
import yaml

Check warning on line 2792 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2792

Added line #L2792 was not covered by tests

if slit.meta.exposure.type != "NRS_FIXEDSLIT":
return None

Check warning on line 2795 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2794-L2795

Added lines #L2794 - L2795 were not covered by tests

profile_file = os.path.join(

Check warning on line 2797 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2797

Added line #L2797 was not covered by tests
os.path.dirname(__file__),
"data/extended_sensitivity/",
"fixed_slit_flat_profile_{0}.yaml".format(slit.name.lower()),
)

if not os.path.exists(profile_file):
msg = f"fixed_slit_flat_field: {profile_file} not found"
grizli.utils.log_comment(grizli.utils.LOGFILE, msg, verbose=verbose)
return None

Check warning on line 2806 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2803-L2806

Added lines #L2803 - L2806 were not covered by tests

msg = f"fixed_slit_flat_field: {profile_file} (apply={apply})"
grizli.utils.log_comment(grizli.utils.LOGFILE, msg, verbose=verbose)

Check warning on line 2809 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2808-L2809

Added lines #L2808 - L2809 were not covered by tests

with open(profile_file) as fp:
fs_data = yaml.load(fp, Loader=yaml.Loader)

Check warning on line 2812 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2811-L2812

Added lines #L2811 - L2812 were not covered by tests

slit_data = get_slit_data(slit)

Check warning on line 2814 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2814

Added line #L2814 was not covered by tests

bspl = grizli.utils.bspline_templates(

Check warning on line 2816 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2816

Added line #L2816 was not covered by tests
slit_data["yslit"].flatten(),
df=fs_data["ydf"],
minmax=fs_data["minmax"],
get_matrix=True,
)

coeffs = np.array(fs_data["coeffs"])
flat_profile = bspl.dot(coeffs).reshape(slit.data.shape)
flat_profile[flat_profile < 0] = 0.0

Check warning on line 2825 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2823-L2825

Added lines #L2823 - L2825 were not covered by tests

if apply:
if (not hasattr(slit, "flat_profile")) | force:
if hasattr(slit, "flat_profile"):
slit.flat_profile *= flat_profile

Check warning on line 2830 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2827-L2830

Added lines #L2827 - L2830 were not covered by tests
else:
slit.flat_profile = flat_profile

Check warning on line 2832 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2832

Added line #L2832 was not covered by tests

slit.data /= flat_profile
slit.err /= flat_profile
slit.var_rnoise /= flat_profile**2
slit.var_poisson /= flat_profile**2

Check warning on line 2837 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2834-L2837

Added lines #L2834 - L2837 were not covered by tests
else:
msg = f"fixed_slit_flat_field: existing flat_profile found"
grizli.utils.log_comment(

Check warning on line 2840 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2839-L2840

Added lines #L2839 - L2840 were not covered by tests
grizli.utils.LOGFILE, msg, verbose=verbose
)

return flat_profile

Check warning on line 2844 in msaexp/utils.py

View check run for this annotation

Codecov / codecov/patch

msaexp/utils.py#L2844

Added line #L2844 was not covered by tests


def slit_extended_flux_calibration(
slit,
sens_file=None,
Expand Down

0 comments on commit 49c8296

Please sign in to comment.