예제 #1
0
def test_doesnt_recalculate_when_psf_caches_mtf():
    from prysm import Pupil, PSF
    pu = Pupil()
    ps = PSF.from_pupil(pu, 2)
    mt = otf.MTF.from_psf(ps)
    ps._mtf = mt
    mt2 = otf.MTF.from_psf(ps)
    assert id(mt) == id(mt2)
예제 #2
0
def test_diffprop_matches_airydisk(efl, epd, wvl):
    fno = efl / epd

    p = Pupil(wavelength=wvl, epd=epd)
    psf = PSF.from_pupil(p, efl)
    u, sx = psf.slice_x
    u, sy = psf.slice_y
    analytic = airydisk(u, fno, wvl)
    assert np.allclose(sx, analytic, rtol=PRECISION, atol=PRECISION)
    assert np.allclose(sy, analytic, rtol=PRECISION, atol=PRECISION)
예제 #3
0
def test_diffprop_matches_airydisk(efl, epd, wvl):
    fno = efl / epd

    p = Pupil(wavelength=wvl, epd=epd)
    psf = PSF.from_pupil(p, efl, Q=3)  # use Q=3 not Q=4 for improved accuracy
    u, sx = psf.slice_x
    u, sy = psf.slice_y
    analytic = _airydisk(u, fno, wvl)
    assert np.allclose(sx, analytic, atol=PRECISION)
    assert np.allclose(sy, analytic, atol=PRECISION)
예제 #4
0
def test_diffprop_matches_airydisk(efl, epd, wvl):
    fno = efl / epd

    p = Pupil(dia=epd, xy_unit=u.mm, z_unit=u.nm, wavelength=mkwvl(wvl, u.um))
    psf = PSF.from_pupil(p, efl, Q=3)  # use Q=3 not Q=4 for improved accuracy
    s = psf.slices()
    u_, sx = s.x
    u_, sy = s.y
    analytic = airydisk(u_, fno, wvl)
    assert np.allclose(sx, analytic, atol=PRECISION)
    assert np.allclose(sy, analytic, atol=PRECISION)
예제 #5
0
def test_diffprop_matches_analyticmtf(efl, epd, wvl):
    fno = efl / epd
    p = Pupil(wavelength=wvl, epd=epd)
    psf = PSF.from_pupil(p, efl)
    mtf = MTF.from_psf(psf)
    u, t = mtf.tan
    uu, s = mtf.sag

    analytic_1 = diffraction_limited_mtf(fno, wvl, frequencies=u)
    analytic_2 = diffraction_limited_mtf(fno, wvl, frequencies=uu)
    assert np.allclose(analytic_1, t, rtol=PRECISION, atol=PRECISION)
    assert np.allclose(analytic_2, s, rtol=PRECISION, atol=PRECISION)
예제 #6
0
def test_diffprop_matches_analyticmtf(efl, epd, wvl):
    fno = efl / epd
    p = Pupil(dia=epd, xy_unit=u.mm, z_unit=u.nm, wavelength=mkwvl(wvl, u.um))
    psf = PSF.from_pupil(p, efl)
    mtf = MTF.from_psf(psf)
    s = mtf.slices()
    u_, x = s.x
    u__, y = s.y

    analytic_1 = diffraction_limited_mtf(fno, wvl, frequencies=u_)
    analytic_2 = diffraction_limited_mtf(fno, wvl, frequencies=u__)
    assert np.allclose(analytic_1, x, atol=PRECISION)
    assert np.allclose(analytic_2, y, atol=PRECISION)
예제 #7
0
def test_array_orientation_consistency_tilt():
    ''' The pupil array should be shaped as arr[x,y], as should the psf and MTF.
        A linear phase error in the pupil along y should cause a motion of the
        PSF in y.  Specifically, for a positive-signed phase, that should cause
        a shift in the +y direction.
    '''
    samples = 128
    p = Seidel(W111=1, samples=samples)
    ps = PSF.from_pupil(p, 1)
    idx_y, idx_x = np.unravel_index(ps.data.argmax(),
                                    ps.data.shape)  # row-major y, x
    assert idx_x == ps.center_x
    assert idx_y > ps.center_y
예제 #8
0
exit()

plt.style.use('bmh')
if 0:
    dia = 10
    fnos = [1, 4]
    opds = [.4, .1]
    mtfs = []
    for fno, opd in zip(fnos, opds):
        z = NollZernike(Z11=opd,
                        norm=True,
                        dia=dia,
                        opd_unit='um',
                        wavelength=0.1,
                        samples=1024)
        ps = PSF.from_pupil(z, efl=dia * fno)
        mt = MTF.from_psf(ps)
        mtfs.append(mt.tan)

    fig, ax = plt.subplots()
    for curve, fno, opd in zip(mtfs, fnos, opds):
        # each element in mtfs is a tuple of (frequency, MTF).
        # * unpacks this and provides the x, y positional arguments to ax.plot
        ax.plot(*curve, label=f'F/{fno}, opd={opd}')

    ax.legend()
    ax.set(xlim=(0, 120),
           xlabel='Spatial Frequency [cy/mm]',
           ylim=(0, 1),
           ylabel='MTF [Rel. 1.0]')
    plt.show()
예제 #9
0
def sample_psf_bigger():
    p = Pupil()
    return PSF.from_pupil(p, 20)
예제 #10
0
def sample_psf():
    p = Pupil()
    return PSF.from_pupil(p, 10)