Example #1
0
def test_WFI_filters():
    wi = roman.WFI()
    filter_list = wi.filter_list
    for filter in filter_list:
        wi = roman.WFI()
        wi.filter = filter
        wi.calc_psf(fov_pixels=4, oversample=1, nlambda=3)
Example #2
0
def test_WFI_psf():
    """
    Test that instantiating WFI works and can compute a PSF without
    raising any exceptions
    """
    wfi = roman.WFI()
    wfi.calc_psf(fov_pixels=4)
Example #3
0
def test_WFI_limits_interpolation_range():
    wfi = roman.WFI()
    det = wfi._detectors['SCA01']
    det.get_aberration_terms(1.29e-6)
    det.field_position = (0, 0)
    det.get_aberration_terms(1.29e-6)

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (500000, 0)
    assert 'Requested pixel_x position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (-1, 0)
    assert 'Requested pixel_x position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (0, 500000)
    assert 'Requested pixel_y position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (0, -1)
    assert 'Requested pixel_y position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    det.field_position = (2048, 2048)

    # Get min and max valid wavelengths from aberration file
    zern = Table.read(wfi._aberration_files[wfi.mode], format='ascii.csv')
    min_wv = zern['wavelength'][0] * 1e-6  # convert from micron to meter
    max_wv = zern['wavelength'][-1] * 1e-6

    # Test that get_aberration_terms() uses an approximated wavelength when
    # called with an out-of-bounds wavelength.
    too_lo_wv = min_wv * .9
    too_hi_wv = max_wv / .9
    valid_wv = np.mean([min_wv, max_wv])

    assert allclose(
        det.get_aberration_terms(min_wv),
        det.get_aberration_terms(too_lo_wv)), (
            "Aberration below wavelength range did not return closest value.")

    assert allclose(
        det.get_aberration_terms(max_wv),
        det.get_aberration_terms(too_hi_wv)), (
            "Aberration above wavelength range did not return closest value.")

    # Test border pixels outside the ref data. In Cycle 9, (0, 37) is the first
    # pixel, so we check if (0, 0) is approximated to it as the nearest point.
    det.field_position = (0, 0)
    coefficients_outlier = det.get_aberration_terms(valid_wv)

    det.field_position = (0, 37)
    coefficients_data = det.get_aberration_terms(valid_wv)

    assert np.allclose(coefficients_outlier, coefficients_data), "nearest point extrapolation " \
                                                                 "failed for outlier field point"
Example #4
0
def test_swapping_modes(wfi=None):

    if wfi is None:
        wfi = roman.WFI()

    # change detector string to match file format (e.g., "SCA01" -> "SCA_1")
    detector_substr = lambda det: f"{det[:3]}_{str(int((det[3:])))}"

    # dynamically generate current pupil path for a given WFI instance
    pupil_path = (lambda self, mask=None: os.path.join(
        self._pupil_controller._pupil_basepath, self._pupil_controller.
        pupil_file_formatters[
            self._pupil_controller._get_filter_mask(self.filter)
            if mask is None else mask]).format(detector_substr(self.detector)))

    tests = [
        # [filter, mode, pupil_file]
        ['F146', 'imaging', pupil_path],
        ['F213', 'imaging', pupil_path],
        [PRISM_FILTERS[0], 'prism', pupil_path],
        [GRISM_FILTERS[0], 'grism', pupil_path],
    ]

    for test_filter, test_mode, test_pupil in tests:
        wfi.filter = test_filter

        fail_str = (f"failed on {test_filter}, {test_mode}, "
                    f"{test_pupil(wfi).split('/')[-1]}")

        assert wfi.filter == test_filter, fail_str
        assert wfi.mode == test_mode, fail_str
        assert wfi._current_aberration_file == wfi._aberration_files[
            test_mode], fail_str
        assert wfi.pupil == test_pupil(wfi), fail_str
Example #5
0
def test_WFI_includes_aberrations():
    wfi = roman.WFI()
    wfi.detector = 'SCA01'
    osys = wfi.get_optical_system()
    assert isinstance(osys[2], roman.FieldDependentAberration), (
        "Third plane of Roman WFI optical system should be the "
        "field dependent aberration virtual optic")
Example #6
0
def test_WFI_chooses_pupil_masks():
    wfi = roman.WFI()

    def autopupil():
        """Helper to trigger pupil selection in testing"""
        wavelengths, _ = wfi._get_weights()
        wfi._validate_config(wavelengths=wavelengths)

    wfi.filter = 'F087'
    autopupil()
    assert wfi.pupil == wfi._unmasked_pupil_path, "WFI did not select unmasked pupil for F087"
    wfi.filter = 'F184'
    autopupil()
    assert wfi.pupil == wfi._masked_pupil_path, "WFI did not select masked pupil for F158"
    wfi.filter = 'F087'
    autopupil()
    assert wfi.pupil == wfi._unmasked_pupil_path, "WFI did not re-select unmasked pupil for F087"

    def _test_filter_pupil(filter_name, expected_pupil):
        wfi.filter = 'F087'
        autopupil()
        wfi.filter = filter_name
        autopupil()
        assert wfi.pupil == expected_pupil, "Expected pupil {} " \
                                            "for filter {}".format(filter_name, expected_pupil)

    _test_filter_pupil('F106', wfi._unmasked_pupil_path)
    _test_filter_pupil('F129', wfi._unmasked_pupil_path)
    _test_filter_pupil('F062', wfi._unmasked_pupil_path)
    _test_filter_pupil('F158', wfi._unmasked_pupil_path)
    _test_filter_pupil('F146', wfi._unmasked_pupil_path)

    _test_filter_pupil('F184', wfi._masked_pupil_path)
Example #7
0
def test_WFI_detector_position_setter():
    wfi = roman.WFI()
    wfi.detector = 'SCA01'
    valid_pos = (4000, 1000)
    wfi.detector_position = valid_pos
    assert wfi._detectors[wfi._detector].field_position == valid_pos, (
        "Setting field position through Instrument.detector_position did not update field_position "
        "for the detector's aberration optic")
    assert wfi.detector_position == valid_pos, "`detector_position` getter doesn't reflect " \
                                               "assignment to setter"
Example #8
0
def test_WFI_fwhm():
    """
    Test that computed PSFs are physically realistic, at least relatively.
    Loose test...
    """
    wfi = roman.WFI()

    wfi.pupilopd = None
    wfi.options['jitter'] = None

    wfi.filter = 'F062'
    fwhm_f062 = measure_fwhm(wfi.calc_psf(oversample=6))

    wfi.filter = 'F184'
    fwhm_f184 = measure_fwhm(wfi.calc_psf(oversample=6))

    assert (4.0 > fwhm_f184 / fwhm_f062 > 2.0)
Example #9
0
def test_custom_aberrations():

    wfi = roman.WFI()

    # Use grism aberration_file for testing
    test_aberration_file = wfi._aberration_files['grism']

    # Test override
    # -------------
    wfi.lock_aberrations(test_aberration_file)

    for filter in wfi.filter_list:
        wfi.filter = filter
        assert wfi._current_aberration_file == test_aberration_file, "Filter change caused override to fail"

    # Test Release Override
    # ---------------------
    wfi.unlock_aberrations()
    assert wfi._aberration_files['custom'] is None, "Custom aberration file not deleted on override release."
    test_swapping_modes(wfi)
Example #10
0
def test_WFI_limits_interpolation_range():
    wfi = roman.WFI()
    det = wfi._detectors['SCA01']
    det.get_aberration_terms(1.29e-6)
    det.field_position = (0, 0)
    det.get_aberration_terms(1.29e-6)

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (500000, 0)
    assert 'Requested pixel_x position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (-1, 0)
    assert 'Requested pixel_x position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (0, 500000)
    assert 'Requested pixel_y position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    with pytest.raises(ValueError) as excinfo:
        det.field_position = (0, -1)
    assert 'Requested pixel_y position' in str(excinfo.value), (
        "FieldDependentAberration did not error on out-of-bounds field point")

    det.field_position = (2048, 2048)

    # Test the get_aberration_terms function uses approximated wavelength when
    # called with an out-of-bound wavelength.
    assert allclose(
        det.get_aberration_terms(2.0e-6), det.get_aberration_terms(2.5e-6)
    ), ("Aberration outside wavelength range did not return closest value.")

    assert allclose(
        det.get_aberration_terms(0.48e-6), det.get_aberration_terms(0.40e-6)
    ), ("Aberration outside wavelength range did not return closest value.")
Example #11
0
def test_WFI_pupil_controller():
    wfi = roman.WFI()

    for detector in wfi.detector_list:
        wfi.detector = detector

        assert os.path.isfile(
            pupil_path(wfi)), f"Pupil file missing: {pupil_path(wfi)}"

        # Test detector change was successful
        assert wfi.detector == detector, "WFI detector was not set correctly"
        assert wfi.pupil == pupil_path(wfi), "pupil path was not set correctly"

        # Test pupil mask lock/unlock
        for mask in wfi.pupil_mask_list:
            # test lock
            wfi.lock_pupil_mask(mask)

            assert wfi.pupil == pupil_path(
                wfi, mask), "Pupil path was not set correctly"

            # introduce differing filter to modify
            wfi.filter = "PRISM" if mask != "PRISM" else "F062"

            assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "Pupil mask was not set correctly"

            # test unlock
            wfi.unlock_pupil_mask()

            assert wfi.pupil == pupil_path(wfi), f"Pupil mask unlock failed"

        assert wfi._pupil_controller._auto_pupil, "Pupil is locked and should not be"
        assert wfi._pupil_controller._auto_pupil_mask, "Pupil mask is locked and should not be"

        # Test pupil lock/unlock
        with pytest.raises(FileNotFoundError) as err:
            assert wfi.lock_pupil("file_that_does_not_exist.fits"
                                  ), "FileNotFoundError was not raised"

        this_file = __file__
        wfi.lock_pupil(this_file)
        assert wfi.pupil == this_file, "Pupil did not lock to proper file."

        wfi.unlock_pupil()
        assert wfi.pupil == pupil_path(wfi), f"Pupil unlock failed."

        assert wfi._pupil_controller._auto_pupil, "Pupil is locked and should  not be"
        assert wfi._pupil_controller._auto_pupil_mask, "Pupil mask is locked and should not be"

        # Test effect of changing the filter on pupil path
        for filter in wfi.filter_list:
            wfi.filter = filter

            assert wfi.pupil == pupil_path(
                wfi), f"Pupil was not set to correct value for filter {filter}"

    # Test persistence of pupil and pupil mask locks through a PSF calculation
    wfi2 = roman.WFI()
    wfi2.detector = detector
    valid_pos = (4000, 1000)
    wfi2.detector_position = valid_pos

    wfi2.filter = "F129"
    wfi2.lock_pupil_mask("GRISM")
    wfi2.filter = "F129"
    assert wfi2.pupil == pupil_path(
        wfi2, "GRISM"), "Pupil path was not set correctly"
    wfi2.calc_psf(monochromatic=1.3e-6, fov_pixels=4)

    assert wfi.pupil_mask == "GRISM", "Pupil mask changed during PSF calculation"
    assert wfi2.pupil == pupil_path(
        wfi2, "GRISM"), "Pupil path changed during PSF calculation"
Example #12
0
def test_WFI_pupil_controller():
    wfi = roman.WFI()

    for detector in wfi.detector_list:
        wfi.detector = detector

        detector_cropped = detector[:3] + str(int(
            (detector[3:])))  # example "SCA01" -> "SCA1"

        unmasked_pupil_path = os.path.join(
            wfi._pupil_controller._pupil_basepath,
            '{}_rim_mask.fits.gz'.format(detector_cropped))

        masked_pupil_path = os.path.join(
            wfi._pupil_controller._pupil_basepath,
            '{}_full_mask.fits.gz'.format(detector_cropped))

        assert os.path.isfile(
            unmasked_pupil_path), "Pupil file missing {}".format(
                unmasked_pupil_path)
        assert os.path.isfile(
            masked_pupil_path), "Pupil file missing {}".format(
                masked_pupil_path)

        # Test detector change was successful
        assert wfi.detector == detector, "WFI detector was not set correctly"
        assert wfi._unmasked_pupil_path == unmasked_pupil_path, "unmasked_pupil_path was not set correctly"
        assert wfi._masked_pupil_path == masked_pupil_path, "masked_pupil_path was not set correctly"
        assert wfi.pupil in [unmasked_pupil_path,
                             masked_pupil_path], "pupil was not set correctly"

        # Test mask overriding
        wfi.pupil_mask = MASKED_FLAG
        assert wfi.pupil == masked_pupil_path, "pupil was not set correctly"
        assert wfi._pupil_controller.auto_pupil is False, "auto_pupil is active after user override"
        assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "pupil mask was not set correctly"

        wfi.pupil_mask = UNMASKED_FLAG
        assert wfi.pupil == unmasked_pupil_path, "pupil was not set correctly"
        assert wfi._pupil_controller.auto_pupil is False, "auto_pupil is active after user override"
        assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "pupil mask was not set correctly"

        # Outdated mask overriding backward comparability test:
        wfi.pupil_mask = "COLD_PUPIL"
        assert wfi.pupil == masked_pupil_path, "pupil was not set correctly"
        assert wfi._pupil_controller.auto_pupil is False, "auto_pupil is active after user override"
        assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "pupil mask was not set correctly"

        wfi.pupil_mask = "UNMASKED"
        assert wfi.pupil == unmasked_pupil_path, "pupil was not set correctly"
        assert wfi._pupil_controller.auto_pupil is False, "auto_pupil is active after user override"
        assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "pupil mask was not set correctly"

        wfi.pupil_mask = AUTO_FLAG
        assert wfi._pupil_controller.auto_pupil is True, "auto_pupil is inactive after mask is set to AUTO"
        assert wfi._pupil_controller._pupil_mask == wfi.pupil_mask, "pupil mask was not set correctly"

        # Test filters
        for filter in wfi.filter_list:
            wfi.filter = filter
            if filter in wfi._pupil_controller._masked_filters:
                assert wfi.pupil == masked_pupil_path, \
                    "Pupil did not set to correct value according to filter {}".format(filter)
            else:
                assert wfi.pupil == unmasked_pupil_path, \
                    "Pupil did not set to correct value according to filter {}".format(filter)

    # Test calculating a single PSF
    wfi = roman.WFI()
    wfi.detector = detector
    valid_pos = (4000, 1000)
    wfi.detector_position = valid_pos
    wfi.pupil_mask = "COLD_PUPIL"
    assert wfi.pupil == masked_pupil_path, "Pupil did not set to correct value according to override"
    wfi.calc_psf(fov_pixels=4)
    assert wfi.pupil == masked_pupil_path, "Pupil did not set to correct value according to override"
Example #13
0
import matplotlib.pyplot as plt
from webbpsf import display_psf, roman

#### Create webbpsf-roman_page_header.png
wfi = roman.WFI()

all_filters = [f for f in wfi.filter_list]

long = 6
wide = 2

fig, axs = plt.subplots(wide, long, figsize=(12, 6), sharey=True)

for i, filter in enumerate(sorted(all_filters)):
    r = int(np.floor(i / long))
    c = (i % long if i < long else
         (i % long) + 1)  # remove else for left-justified bottom row
    ax = axs[r][c]

    wfi.filter = filter
    psf = wfi.calc_psf(oversample=4)

    display_psf(psf, ax=ax, colorbar=False, title=filter)
    ax.title.set_fontsize(20)
    ax.tick_params(axis='both', labelsize=10)
    ax.xaxis.label.set_visible(False)
    ax.yaxis.label.set_visible(False)

axs[-1][0].remove()  # change last index to -1 to justify left

fig.tight_layout(w_pad=.1, h_pad=0)