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

Extend NIRSpec wavelength ranges #82

Merged
merged 21 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[flake8]
count = true
select = E9,F63,F7,F82
show-source = true
statistics = true
exclude = .git,build,docs,scripts,binder

2 changes: 1 addition & 1 deletion .github/workflows/python-package-with-numba.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
pip install flake8
- name: Lint with flake8
run: |
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 .
test:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
pip install flake8
- name: Lint with flake8
run: |
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 .
test:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
904 changes: 904 additions & 0 deletions docs/examples/lookup-table-psf.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/msaexp/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Additional API
.. automodapi:: msaexp.pipeline
:no-inheritance-diagram:

.. automodapi:: msaexp.pipeline_extended
:no-inheritance-diagram:

.. automodapi:: msaexp.utils
:no-inheritance-diagram:

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
33 changes: 32 additions & 1 deletion msaexp/data/fwhm_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,36 @@
5.38 1.859
"""

# Measured again from 1493 with multiple Gaussians
fwhm_data_2024b = """# wave fwhm_pix
0.50 1.24
0.58 1.24
0.66 1.25
0.79 1.26
0.99 1.27
1.29 1.29
1.65 1.29
2.00 1.30
2.32 1.31
2.61 1.31
2.87 1.33
3.11 1.33
3.34 1.35
3.55 1.37
3.75 1.39
3.94 1.43
4.12 1.46
4.29 1.51
4.46 1.55
4.62 1.60
4.77 1.64
4.92 1.67
5.06 1.70
5.20 1.76
5.34 1.82
5.60 1.90
"""

# Set default
fwhm_data = fwhm_data_update
# fwhm_data = fwhm_data_update
fwhm_data = fwhm_data_2024b
Binary file added msaexp/data/nirspec_exp_psf_lookup.fits
Binary file not shown.
Binary file added msaexp/data/nirspec_gau_psf_lookup.fits
Binary file not shown.
15 changes: 10 additions & 5 deletions msaexp/drizzle.py
Original file line number Diff line number Diff line change
Expand Up @@ -908,8 +908,8 @@
"""
Find emission lines in 2D spectrum

Parameters:
-----------
Parameters
----------
hdul : HDUList
The HDUList object containing the 2D spectrum.

Expand All @@ -933,8 +933,8 @@
verbose : bool, optional
Whether to print verbose output. Default is True.

Returns:
--------
Returns
-------
xlim : tuple
A tuple containing the x-limits of the emission lines.

Expand Down Expand Up @@ -1467,7 +1467,12 @@
)

if prf_center is None:
prf_center = sci.header["SRCYPIX"] - (sci.data.shape[0] - 1) / 2.0
if "SRCYPIX" in sci.header:
y0 = sci.header["SRCYPIX"]
else:
y0 = (sci.data.shape[0] - 1) / 2

Check warning on line 1473 in msaexp/drizzle.py

View check run for this annotation

Codecov / codecov/patch

msaexp/drizzle.py#L1473

Added line #L1473 was not covered by tests

prf_center = y0 - (sci.data.shape[0] - 1) / 2.0

_data = make_optimal_extraction(
waves,
Expand Down
227 changes: 144 additions & 83 deletions msaexp/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,137 @@
)


def exposure_oneoverf(file, fix_rows=False, skip_completed=True, **kwargs):
"""
Remove column-averaged 1/f striping

Parameters
----------
file : str
Exposure (rate.fits) filename

fix_rows : bool
Apply 1/f correction to detector rows, as well as columns

skip_completed : bool
Skip steps that have already been completed

Returns
-------
status : bool
False if ``skip_completed`` and ``ONEFEXP`` keyword found, True if
executed without exception.

"""
with pyfits.open(file) as im:
if "ONEFEXP" in im[0].header:
if im[0].header["ONEFEXP"] & skip_completed:
return False

Check warning on line 438 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L435-L438

Added lines #L435 - L438 were not covered by tests

jwst_utils.exposure_oneoverf_correction(

Check warning on line 440 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L440

Added line #L440 was not covered by tests
file, erode_mask=False, in_place=True, axis=0, deg_pix=256
)

if fix_rows:
jwst_utils.exposure_oneoverf_correction(

Check warning on line 445 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L444-L445

Added lines #L444 - L445 were not covered by tests
file, erode_mask=False, in_place=True, axis=1, deg_pix=2048
)

return True

Check warning on line 449 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L449

Added line #L449 was not covered by tests


def exposure_detector_effects(
file, fix_rows=False, scale_rnoise=True, skip_completed=True, **kwargs
):
"""
Remove 1/f striping, bias pedestal offset and rescale RNOISE extension

Parameters
----------
file : str
Exposure (rate.fits) filename

scale_rnoise : bool
Calculate the RNOISE scaling

skip_completed : bool
Skip steps that have already been completed

Returns
-------
status : bool
False if ``skip_completed`` and ``ONEFEXP`` keyword found, True if
executed without exception.

"""

status = exposure_oneoverf(

Check warning on line 477 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L477

Added line #L477 was not covered by tests
file, fix_rows=fix_rows, skip_completed=skip_completed, **kwargs
)

with pyfits.open(file, mode="update") as im:

Check warning on line 481 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L481

Added line #L481 was not covered by tests
# bias
dq = (im["DQ"].data & 1025) == 0

Check warning on line 483 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L483

Added line #L483 was not covered by tests

if im[0].header["DETECTOR"] == "NRS2":
dq[:, :1400] = False

Check warning on line 486 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L485-L486

Added lines #L485 - L486 were not covered by tests
else:
dq[:, 1400:] = False

Check warning on line 488 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L488

Added line #L488 was not covered by tests

if ("MASKBIAS" in im[0].header) & skip_completed:
bias_level = im[0].header["MASKBIAS"]
msg = f"msaexp.preprocess : {file} bias offset ="
msg += f" {bias_level:7.3f} (from MASKBIAS)"
utils.log_comment(

Check warning on line 494 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L490-L494

Added lines #L490 - L494 were not covered by tests
utils.LOGFILE, msg, verbose=True, show_date=False
)
else:
bias_level = np.nanmedian(im["SCI"].data[dq])
msg = f"msaexp.preprocess : {file} bias offset ="
msg += f" {bias_level:7.3f}"
utils.log_comment(

Check warning on line 501 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L498-L501

Added lines #L498 - L501 were not covered by tests
utils.LOGFILE, msg, verbose=True, show_date=False
)

im["SCI"].data -= bias_level
im[0].header["MASKBIAS"] = bias_level, "Bias level"
im[0].header["MASKNPIX"] = (

Check warning on line 507 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L505-L507

Added lines #L505 - L507 were not covered by tests
dq.sum(),
"Number of pixels used for bias level",
)

if scale_rnoise:

Check warning on line 512 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L512

Added line #L512 was not covered by tests

if ("SCLREADN" in im[0].header) & skip_completed:
rms = im[0].header["SCLREADN"]
msg = f"msaexp.preprocess : {file} rms scale ="
msg += f" {rms:>7.2f} (from SCLREADN)"
utils.log_comment(

Check warning on line 518 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L514-L518

Added lines #L514 - L518 were not covered by tests
utils.LOGFILE, msg, verbose=True, show_date=False
)
else:
resid = im["SCI"].data / np.sqrt(im["VAR_RNOISE"].data)
rms = utils.nmad(resid[dq])
msg = f"msaexp.preprocess : {file} rms scale ="
msg += f"{rms:>7.2f}"
utils.log_comment(

Check warning on line 526 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L522-L526

Added lines #L522 - L526 were not covered by tests
utils.LOGFILE, msg, verbose=True, show_date=False
)

im[0].header["SCLREADN"] = rms, "RNOISE Scale factor"

Check warning on line 530 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L530

Added line #L530 was not covered by tests

im["VAR_RNOISE"].data *= rms**2

Check warning on line 532 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L532

Added line #L532 was not covered by tests

im[0].header["SCLRNPIX"] = (

Check warning on line 534 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L534

Added line #L534 was not covered by tests
dq.sum(),
"Number of pixels used for rnoise scale",
)

im.flush()

Check warning on line 539 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L539

Added line #L539 was not covered by tests

return True

Check warning on line 541 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L541

Added line #L541 was not covered by tests


class NirspecPipeline:
def __init__(
self,
Expand Down Expand Up @@ -735,83 +866,15 @@
snowball_dilate=24,
)

# 1/f correction
# 1/f, bias & rnoise
for file in self.files:
with pyfits.open(file) as im:
if "ONEFEXP" in im[0].header:
if im[0].header["ONEFEXP"] & skip_completed:
continue

jwst_utils.exposure_oneoverf_correction(
file, erode_mask=False, in_place=True, axis=0, deg_pix=256
exposure_detector_effects(

Check warning on line 871 in msaexp/pipeline.py

View check run for this annotation

Codecov / codecov/patch

msaexp/pipeline.py#L871

Added line #L871 was not covered by tests
file,
fix_rows=fix_rows,
scale_rnoise=scale_rnoise,
skip_completed=skip_completed,
)

if fix_rows:
jwst_utils.exposure_oneoverf_correction(
file, erode_mask=False, in_place=True, axis=1, deg_pix=2048
)

# bias
for file in self.files:
with pyfits.open(file, mode="update") as im:
dq = (im["DQ"].data & 1025) == 0

if im[0].header["DETECTOR"] == "NRS2":
dq[:, :1400] = False
else:
dq[:, 1400:] = False

if ("MASKBIAS" in im[0].header) & skip_completed:
bias_level = im[0].header["MASKBIAS"]
msg = f"msaexp.preprocess : {file} bias offset ="
msg += f" {bias_level:7.3f} (from MASKBIAS)"
utils.log_comment(
utils.LOGFILE, msg, verbose=True, show_date=False
)
else:
bias_level = np.nanmedian(im["SCI"].data[dq])
msg = f"msaexp.preprocess : {file} bias offset ="
msg += f" {bias_level:7.3f}"
utils.log_comment(
utils.LOGFILE, msg, verbose=True, show_date=False
)

im["SCI"].data -= bias_level
im[0].header["MASKBIAS"] = bias_level, "Bias level"
im[0].header["MASKNPIX"] = (
dq.sum(),
"Number of pixels used for bias level",
)

if scale_rnoise:

if ("SCLREADN" in im[0].header) & skip_completed:
rms = im[0].header["SCLREADN"]
msg = f"msaexp.preprocess : {file} rms scale ="
msg += f" {rms:>7.2f} (from SCLREADN)"
utils.log_comment(
utils.LOGFILE, msg, verbose=True, show_date=False
)
else:
resid = im["SCI"].data / np.sqrt(im["VAR_RNOISE"].data)
rms = utils.nmad(resid[dq])
msg = f"msaexp.preprocess : {file} rms scale ="
msg += f"{rms:>7.2f}"
utils.log_comment(
utils.LOGFILE, msg, verbose=True, show_date=False
)

im[0].header["SCLREADN"] = rms, "RNOISE Scale factor"

im["VAR_RNOISE"].data *= rms**2

im[0].header["SCLRNPIX"] = (
dq.sum(),
"Number of pixels used for rnoise scale",
)

im.flush()

return True

def run_jwst_pipeline(
Expand Down Expand Up @@ -1571,8 +1634,7 @@
center2d=False,
trace_sign=1,
min_dyoffset=0.2,
**kwargs,
):
**kwargs):
"""
Main function for extracting 2D/1D spectra from individual slitlets

Expand Down Expand Up @@ -1637,8 +1699,8 @@
min_dyoffset: float
The minimum value for the y offset. Default is 0.2.

Returns:
----------
Returns
-------
If 'key' is not found in 'slitlets', returns None.

Else:
Expand Down Expand Up @@ -2487,17 +2549,16 @@
"""
Make a summary table of all extracted sources

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

Parameters
----------
root : str
The root directory where the data is stored. Default is "msaexp".

zout : astropy.table.Table
Optional table containing photometric redshift information. Default is None.

Returns:
--------
Returns
-------
tabs : list
List of astropy tables containing the extracted source information.

Expand Down
Loading
Loading