diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..c660077 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,12 @@ +# ref: https://gist.github.com/peterhurford/09f7dcda0ab04b95c026c60fa49c2a68?permalink_comment_id=3453153#gistcomment-3453153 + +from glob import glob + + +def refactor(string: str) -> str: + return string.replace("/", ".").replace("\\", ".").replace(".py", "") + + +pytest_plugins = [ + refactor(fixture) for fixture in glob("tests/fixtures/*.py") if "__" not in fixture +] diff --git a/tests/fixtures/airy2.py b/tests/fixtures/airy2.py new file mode 100644 index 0000000..66432ee --- /dev/null +++ b/tests/fixtures/airy2.py @@ -0,0 +1,36 @@ +import pytest + +import numpy as np +import scipy.special + +@pytest.fixture +def airy2(): + + def _airy2(diameter, focal_length, wavelength, pixelscale, shape, oversample): + # https://en.wikipedia.org/wiki/Airy_disk#Mathematical_Formulation + + f_number = focal_length / diameter + + shape = np.asarray(shape) + shape *= oversample + + c = (shape - 1) / 2 + y, x = np.indices(shape, dtype=float) + + x -= c[1] + y -= c[0] + + x *= (pixelscale[0] / oversample) + y *= (pixelscale[1] / oversample) + + q = np.sqrt(x ** 2 + y ** 2) + X = (np.pi * q) / (wavelength * f_number) + + # if length is odd, the center value will be zero which will throw a + # divide by zero error. To avoid this, we'll set any zeros to machine + # epsilon (eps) + X[X == 0] = np.finfo(X.dtype).eps + + return (2 * scipy.special.jn(1, X) / X) ** 2 + + return _airy2 \ No newline at end of file diff --git a/tests/fixtures/pupil.py b/tests/fixtures/pupil.py new file mode 100644 index 0000000..e81e290 --- /dev/null +++ b/tests/fixtures/pupil.py @@ -0,0 +1,25 @@ +import pytest + +import lentil + +@pytest.fixture +def pupil(): + + def _pupil(focal_length, diameter, shape, radius, coeffs=None): + + amplitude = lentil.circle(shape, radius) + pixelscale = diameter/(2*radius) + + if coeffs is not None: + opd = lentil.zernike_compose(amplitude, coeffs) + else: + opd = 0 + + p = lentil.Pupil(amplitude=amplitude, + phase=opd, + pixelscale=pixelscale, + focal_length=focal_length) + + return p + + return _pupil \ No newline at end of file diff --git a/tests/test_propagate_fft.py b/tests/test_propagate_fft.py new file mode 100644 index 0000000..90a0199 --- /dev/null +++ b/tests/test_propagate_fft.py @@ -0,0 +1,28 @@ +import lentil +import numpy as np + + +def test_propagate_airy(airy2, pupil): + diameter = 1 + focal_length = 10 + wavelength = 500e-9 + pixelscale = (5e-6, 5e-6) + shape = (511, 511) + oversample = 1 + + psf_airy = airy2(diameter, focal_length, wavelength, pixelscale, shape, oversample) + psf_airy = psf_airy/np.max(psf_airy) + + p = pupil(focal_length=focal_length, + diameter=diameter, + shape=(512, 512), + radius=256, + coeffs=None) + + w = lentil.Wavefront(wavelength=500e-9) + w *= p + w = lentil.propagate_fft(w, shape=(511,511), pixelscale=5e-6, oversample=1) + psf = w.intensity + psf = psf/np.max(psf) + + np.all(np.isclose(psf, psf_airy, atol=1e-3)) \ No newline at end of file