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

Rename RcSelfCalStep to OpenPixelStep #9

Merged
merged 3 commits into from
Mar 6, 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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Algorithms for cleaning JWST data.
- `SnowblindStep`: mask cosmic ray showers and snowballs
- `JumpPlusStep`: Propagate JUMP_DET and SATURATED flags in GROUPDQ properly for frame-averaged groups
- `PersistenceFlagStep`: flag pixels effected by persistence exposure-to-exposure
- `RcSelfCalStep`: flag new hot pixels, open pixels or RC pixels
- `OpenPixelStep`: flag new open pixels, hot pixels, or open adjacent pixels


## Installation
Expand Down Expand Up @@ -31,6 +31,7 @@ In Python, we can insert `SnowblindStep` and `JumpPlusStep` after `JumpStep` as
steps = {
"jump": {
"save_results": True,
"flag_large_events": False,
"post_hooks": [
"snowblind.SnowblindStep",
"snowblind.JumpPlusStep",
Expand Down
6 changes: 3 additions & 3 deletions src/snowblind/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .snowblind import SnowblindStep
from .jump_plus import JumpPlusStep
from .rc_selfcal import RcSelfCalStep
from .selfcal import OpenPixelStep
from .persist import PersistenceFlagStep


Expand All @@ -16,7 +16,7 @@
'__version__',
'SnowblindStep',
'JumpPlusStep',
'RcSelfCalStep',
'OpenPixelStep',
'PersistenceFlagStep',
]

Expand All @@ -27,6 +27,6 @@ def _get_steps():
return [
("snowblind.SnowblindStep", 'snowblind', False),
("snowblind.JumpPlusStep", 'jump_plus', False),
("snowblind.RcSelfCalStep", 'rc_selfcal', False),
("snowblind.OpenPixelStep", 'open_pixel', False),
("snowblind.PersistenceFlagStep", 'persist', False),
]
36 changes: 17 additions & 19 deletions src/snowblind/rc_selfcal.py → src/snowblind/selfcal.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
from os.path import commonprefix
import warnings

from astropy.stats import sigma_clipped_stats
from astropy.io import fits
import numpy as np
from jwst import datamodels
from jwst.stpipe import Step


RC = datamodels.dqflags.pixel["RC"]
OPEN = datamodels.dqflags.pixel["OPEN"]
ADJ_OPEN = datamodels.dqflags.pixel["ADJ_OPEN"]
DO_NOT_USE = datamodels.dqflags.pixel["DO_NOT_USE"]


class RcSelfCalStep(Step):
"""Removes cross-shaped and other defects caused by RC-type bad pixels in NIR detectors
class OpenPixelStep(Step):
"""Flags cross-shaped and hot pixel defects caused by open pixels in NIR detectors

Input is an assocation (or glob pattern of files) of all images in visit or program ID
on which ones wishes to do a self-cal. These are split into separate detector stacks,
Expand All @@ -21,19 +22,19 @@ class RcSelfCalStep(Step):
stage 3 pipelines such as tweakreg, skymatch and outlier detection.

Like outlier_detection, the input and output science images are the same, and only the
data quality (DQ) array has new pixels flagged as DO_NOT_USE and RC.
data quality (DQ) array has new pixels flagged as DO_NOT_USE and ADJ_OPEN.

This should be run after flatfielding is finished in image2 pipeline. It is fine to
insert it anywhere in the level3 pipeline before resample.
"""
spec = """
threshold = float(default=3.0) # threshold in sigma to flag hot pixels above median
save_mask = boolean(default=False) # write out per-detector bad-pixel masks
threshold = float(default=3.0) # threshold in sigma to flag hot pixels above local background
save_mask = boolean(default=False) # write out per-detector bad-pixel mask and median
output_use_model = boolean(default=True)
output_use_index = boolean(default=False)
"""

class_alias = "rc_selfcal"
class_alias = "open_pixel"

def process(self, input_data):
with datamodels.open(input_data) as images:
Expand All @@ -55,20 +56,17 @@ def process(self, input_data):
mask, median = self.create_hotpixel_mask(image_stack)
self.log.info(f"Flagged {mask.sum()} pixels with {self.threshold} sigma")
if self.save_mask:
fits.HDUList(
fits.PrimaryHDU(
data=mask.astype(np.uint8)
)
).writeto(f"{detector.lower()}_rcflag_mask.fits", overwrite=True)
fits.HDUList(
fits.PrimaryHDU(
data=median
)
).writeto(f"{detector.lower()}_rcflag_median.fits", overwrite=True)
filename_prefix = f"{commonprefix([f.meta.filename for f in models])}_{detector.lower()}_{self.class_alias}"
mask_model = datamodels.MaskModel(data=mask.astype(np.uint8))
mask_model.meta.filename = f"{filename_prefix}.fits"
self.save_model(mask_model, suffix="mask", force=True)
median_model = datamodels.ImageModel(data=median)
median_model.meta.filename = f"{filename_prefix}.fits"
self.save_model(median_model, suffix="median", force=True)

for result in results:
if result.meta.instrument.detector == detector:
result.dq |= (mask * (DO_NOT_USE | RC)).astype(np.uint32)
result.dq |= (mask * (DO_NOT_USE | ADJ_OPEN)).astype(np.uint32)

return results

Expand Down
14 changes: 7 additions & 7 deletions tests/test_rc_selfcal.py → tests/test_selfcal.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import numpy as np
from jwst import datamodels

from snowblind import RcSelfCalStep
from snowblind import OpenPixelStep


RC = datamodels.dqflags.pixel["RC"]
ADJ_OPEN = datamodels.dqflags.pixel["ADJ_OPEN"]
DO_NOT_USE = datamodels.dqflags.pixel["DO_NOT_USE"]
GOOD = datamodels.dqflags.pixel["GOOD"]


def test_init():
step = RcSelfCalStep(threshold=4.5)
step = OpenPixelStep(threshold=4.5)

assert step.threshold == 4.5

Expand Down Expand Up @@ -41,11 +41,11 @@ def test_call():
image.data[8, 8] += 3 * stddev

# Run the step and see if they're recovered
results = RcSelfCalStep.call(images, threshold=3.0)
results = OpenPixelStep.call(images, threshold=3.0)

for result in results:
assert result.dq[2, 2] == RC | DO_NOT_USE
assert result.dq[3, 5] == RC | DO_NOT_USE
assert result.dq[8, 8] == RC | DO_NOT_USE
assert result.dq[2, 2] == ADJ_OPEN | DO_NOT_USE
assert result.dq[3, 5] == ADJ_OPEN | DO_NOT_USE
assert result.dq[8, 8] == ADJ_OPEN | DO_NOT_USE

assert result.dq[5, 5] == GOOD
Loading