def test_2d_autofocus_helmholtz_average_gradient_zero():
    field = 1 * np.exp(1j * np.linspace(.1, .5, 256)).reshape(16, 16)
    d = 0
    nm = 1.533
    res = 8.25
    method = "helmholtz"

    # first propagate the field
    rfield = nrefocus.refocus(field=field,
                              d=d,
                              nm=nm,
                              res=res,
                              method=method,
                              padding=False)
    # then try to refocus it
    _, nfield = nrefocus.autofocus(
        field=rfield,
        nm=nm,
        res=res,
        ival=(-1.5 * d, -0.5 * d),
        roi=None,
        metric="average gradient",
        minimizer="legacy",
        padding=False,  # without padding, result must be exact
        num_cpus=1,
    )
    assert np.allclose(nfield.flatten().view(float),
                       rfield.flatten().view(float))
Пример #2
0
def test_2d_refocus1():
    myname = sys._getframe().f_code.co_name
    rfield = nrefocus.refocus(field=np.arange(256).reshape(16, 16),
                              d=2.13,
                              nm=1.533,
                              res=8.25,
                              method="helmholtz",
                              padding=False)
    assert np.allclose(np.array(rfield).flatten().view(float), results[myname])
Пример #3
0
    def refocus(self, distance, method="helmholtz", h5file=None, h5mode="a"):
        """Compute a numerically refocused QPImage

        Parameters
        ----------
        distance: float
            Focusing distance [m]
        method: str
            Refocusing method, one of ["helmholtz","fresnel"]
        h5file: str, h5py.Group, h5py.File, or None
            A path to an hdf5 data file where the QPImage is cached.
            If set to `None` (default), all data will be handled in
            memory using the "core" driver of the :mod:`h5py`'s
            :class:`h5py:File` class. If the file does not exist,
            it is created. If the file already exists, it is opened
            with the file mode defined by `hdf5_mode`. If this is
            an instance of h5py.Group or h5py.File, then this will
            be used to internally store all data.
        h5mode: str
            Valid file modes are (only applies if `h5file` is a path)

            - "r": Readonly, file must exist
            - "r+": Read/write, file must exist
            - "w": Create file, truncate if exists
            - "w-" or "x": Create file, fail if exists
            - "a": Read/write if exists, create otherwise (default)

        Returns
        -------
        qpi: qpimage.QPImage
            Refocused phase and amplitude data

        See Also
        --------
        :mod:`nrefocus`: library used for numerical focusing
        """
        field2 = nrefocus.refocus(field=self.field,
                                  d=distance/self["pixel size"],
                                  nm=self["medium index"],
                                  res=self["wavelength"]/self["pixel size"],
                                  method=method
                                  )
        if "identifier" in self:
            ident = self["identifier"]
        else:
            ident = ""
        meta_data = self.meta
        meta_data["identifier"] = "{}@{}{:.5e}m".format(ident,
                                                        method[0],
                                                        distance)
        qpi2 = QPImage(data=field2,
                       which_data="field",
                       meta_data=meta_data,
                       h5file=h5file,
                       h5mode=h5mode)
        return qpi2
Пример #4
0
def test_refocus():
    nrkw = {
        "res": 2,
        "nm": 1,
        "method": "helmholtz",
        "padding": True,
        "d": 5.5
    }
    meta = {
        "wavelength": 1e-6,
        "pixel size": 1e-6 / nrkw["res"],
        "medium index": nrkw["nm"]
    }
    distance = 5.5 * meta["pixel size"]
    size = 40
    x = (np.arange(size) - size / 2).reshape(-1, 1)
    y = (np.arange(size) - size / 2).reshape(1, -1)
    pha = .1
    amp = .5 * (1 + (x**2 + y**2 < size / 3))
    # make smooth to reduce ringing
    amp = gaussian_filter(amp, 1)
    field = amp * np.exp(1j * pha)

    newfield = nrefocus.refocus(field=field, **nrkw)
    qpi0 = qpimage.QPImage(data=newfield, which_data="field", meta_data=meta)

    with pytest.warns(DeprecationWarning, match="kernel"):
        qpi1 = qpi0.refocus(distance=-distance, method=nrkw["method"])

    # sanity
    assert amp.min() < .51
    assert amp.max() > .99
    assert qpi1.amp.min() < .51
    assert qpi1.amp.max() > .99
    assert np.abs(qpi0.pha).max() > 2 * pha

    # refocusing result
    assert not np.allclose(qpi0.amp, amp, rtol=0, atol=8e-4)
    assert not np.allclose(qpi0.pha, pha, rtol=0, atol=3e-4)
    assert np.allclose(qpi1.amp, amp, rtol=0, atol=8e-4)
    assert np.allclose(qpi1.pha, pha, rtol=0, atol=3e-4)
def test_2d_autofocus_fresnel_average_gradient():
    field = 1 * np.exp(1j * np.linspace(.1, .5, 256)).reshape(16, 16)
    d = 5
    nm = 1.533
    res = 8.25
    method = "fresnel"

    # first propagate the field
    rfield = nrefocus.refocus(field=field, d=d, nm=nm, res=res, method=method)
    # then try to refocus it
    _, nfield = nrefocus.autofocus(field=rfield,
                                   nm=nm,
                                   res=res,
                                   ival=(-1.5 * d, -0.5 * d),
                                   roi=None,
                                   metric="average gradient",
                                   minimizer="legacy",
                                   padding=True,
                                   num_cpus=1)
    assert np.allclose(0, np.angle(nfield / rfield), atol=.125)
    assert np.allclose(1, np.abs(nfield / rfield), atol=.147)
Пример #6
0
def test_refocus_kernel_different():
    nrkw1 = {"res": 2, "nm": 1, "padding": True, "d": 5.5}
    meta = {
        "wavelength": 1e-6,
        "pixel size": 1e-6 / nrkw1["res"],
        "medium index": nrkw1["nm"]
    }
    distance = 5.5 * meta["pixel size"]
    size = 40
    x = (np.arange(size) - size / 2).reshape(-1, 1)
    y = (np.arange(size) - size / 2).reshape(1, -1)
    pha = .1
    amp = .5 * (1 + (x**2 + y**2 < size / 3))
    # make smooth to reduce ringing
    amp = gaussian_filter(amp, 1)
    field = amp * np.exp(1j * pha)

    newfield = nrefocus.refocus(field=field, **nrkw1)
    qpi0 = qpimage.QPImage(data=newfield, which_data="field", meta_data=meta)
    qpi1 = qpi0.refocus(distance=-distance, kernel="helmholtz")
    qpi2 = qpi0.refocus(distance=-distance, kernel="fresnel")
    assert not np.all(qpi1.pha == qpi2.pha)
Пример #7
0
def test_2d_autofocus_helmholtz_average_gradient():
    field = 1 * np.exp(1j * np.linspace(.1, .5, 256)).reshape(16, 16)
    d = 5
    nm = 1.533
    res = 8.25
    method = "helmholtz"

    # first propagate the field
    rfield = nrefocus.refocus(field=field, d=d, nm=nm, res=res, method=method)
    # then try to refocus it
    nfield = nrefocus.autofocus(
        field=rfield,
        nm=nm,
        res=res,
        ival=(-1.5 * d, -0.5 * d),
        roi=None,
        metric="average gradient",
        padding=True,
        ret_d=False,
        ret_grad=False,
        num_cpus=1,
    )
    assert np.allclose(0, np.angle(nfield / rfield), atol=.047)
    assert np.allclose(1, np.abs(nfield / rfield), atol=.081)
Пример #8
0
def refocus(img, pixels):
    img_sqrt = np.sqrt(img.clip(0))
    img_temp = nrefocus.refocus(img_sqrt, pixels, 1, 1)
    return (img_temp * np.conjugate(img_temp)).real
Пример #9
0
def mie_avg(radius=5e-6,
            sphere_index=1.339,
            medium_index=1.333,
            wavelength=550e-9,
            pixel_size=1e-7,
            grid_size=(80, 80),
            center=(39.5, 39.5),
            interpolate=3,
            focus=0,
            arp=True):
    """Mie-simulated non-polarized field behind a dielectric sphere

    Parameters
    ----------
    radius: float
        Radius of the sphere [m]
    sphere_index: float
        Refractive index of the sphere
    medium_index: float
        Refractive index of the surrounding medium
    wavelength: float
        Vacuum wavelength of the imaging light [m]
    pixel_size: float
        Pixel size [m]
    grid_size: tuple of floats
        Resulting image size in x and y [px]
    center: tuple of floats
        Center position in image coordinates [px]
    interpolate: int
        Compute the radial field with sampling that is by a factor of
        `interpolate` higher than the required data and interpolate the
        2D field from there.
    focus: float
        .. versionadded:: 0.5.0

        Axial focus position [m] measured from the center of the
        sphere in the direction of light propagation.
    arp: bool
        Use arbitrary precision (ARPREC) in BHFIELD computations

    Returns
    -------
    qpi: qpimage.QPImage
        Quantitative phase data set
    """
    center = np.array(center)
    grid_size = np.array(grid_size)
    # simulation parameters
    radius_um = radius * 1e6  # radius of sphere in um
    propd_um = radius_um  # simulate propagation through full sphere
    propd_lamd = radius / wavelength  # radius in wavelengths
    wave_nm = wavelength * 1e9

    kwargs = {
        "radius_sphere_um": radius_um,
        "refractive_index_medium": medium_index,
        "refractive_index_sphere": sphere_index,
        "measurement_position_um": propd_um,
        "wavelength_nm": wave_nm
    }

    upres = wavelength / pixel_size * interpolate
    max_off = np.max(np.abs(grid_size / 2 - .5 - center))

    latsize = int(np.round((np.max(grid_size) + max_off)))

    num = latsize * upres / 2
    # find the maximum interpolation range in the 2d image

    bignum = int(
        np.ceil(np.sqrt(np.sum(
            (np.array(grid_size) / 2 + max_off)**2))) * interpolate)

    # Compare this number to the radius of the sphere and cut it off at
    # three times the radius.
    radnum = int(np.ceil(3 * radius / pixel_size) * interpolate)
    bignum = min(bignum, radnum)

    latsize *= bignum / num
    latsize *= wavelength * 1e6
    upres /= wavelength * 1e6

    background = np.exp(1j * 2 * np.pi * propd_lamd * medium_index)

    # [sic]: Not times upres
    ofx_px = grid_size[0] / 2 - center[0]
    ofy_px = grid_size[1] / 2 - center[1]

    kwargsx = kwargs.copy()
    kwargsx.update({
        "size_simulation_um": (latsize / 2, 1 / upres),
        "shape_grid": (bignum, 1),
        "offset_x_um": -latsize / 4,
        "offset_y_um": 0
    })

    fieldx = simulate_sphere(arp=arp, **kwargsx) / background

    kwargsy = kwargs.copy()
    kwargsy.update({
        "size_simulation_um": (1 / upres, latsize / 2),
        "shape_grid": (1, bignum),
        "offset_x_um": 0,
        "offset_y_um": -latsize / 4
    })
    fieldy = simulate_sphere(arp=arp, **kwargsy) / background

    field = (fieldx.flatten() + fieldy.flatten()) / 2

    xo = np.linspace(0, bignum, bignum, endpoint=True) / interpolate

    x = np.linspace(-grid_size[0] / 2,
                    grid_size[0] / 2,
                    grid_size[0] * interpolate,
                    endpoint=True)

    y = np.linspace(-grid_size[1] / 2,
                    grid_size[1] / 2,
                    grid_size[1] * interpolate,
                    endpoint=True)

    yv, xv = np.meshgrid(y, x)
    r = np.sqrt(xv**2 + yv**2)
    inpt_kwargs = {
        "kind": "linear",
        "assume_sorted": True,
        "bounds_error": False,
    }

    ipltph = spinterp.interp1d(xo,
                               np.unwrap(np.angle(field)),
                               fill_value=0,
                               **inpt_kwargs)
    ipltam = spinterp.interp1d(xo, np.abs(field), fill_value=1, **inpt_kwargs)
    phase2d = ipltph(r)
    field2d = ipltam(r) * np.exp(1j * phase2d)

    # Numerical refocusing
    # We need to perform numerical focusing with the upsampled array,
    # or else we will loose spatial information and the resulting
    # spherical image becomes asymmetric.
    refoc_field2d = nrefocus.refocus(field2d,
                                     d=-((radius + focus) / pixel_size) *
                                     interpolate,
                                     nm=medium_index,
                                     res=wavelength / pixel_size * interpolate)

    # Phase (2PI offset corrected) and amplitude
    ampli, phase = field2ap_corr(refoc_field2d)

    # Perform new interpolation on requested grid
    intpp = spinterp.RectBivariateSpline(x, y, phase, kx=1, ky=1)
    intpa = spinterp.RectBivariateSpline(x, y, ampli, kx=1, ky=1)

    xp = np.linspace(
        -grid_size[0] / 2, grid_size[0] / 2, grid_size[0],
        endpoint=False) + ofx_px

    yp = np.linspace(
        -grid_size[1] / 2, grid_size[1] / 2, grid_size[1],
        endpoint=False) + ofy_px

    amp_off = intpa(xp, yp)
    pha_off = intpp(xp, yp)

    meta_data = {
        "pixel size": pixel_size,
        "wavelength": wavelength,
        "medium index": medium_index,
        "sim center": center,
        "sim radius": radius,
        "sim index": sphere_index,
        "sim model": "mie-avg",
    }

    qpi = qpimage.QPImage(data=(pha_off, amp_off),
                          which_data="phase,amplitude",
                          meta_data=meta_data)

    return qpi
Пример #10
0
        MNIST_DIGIT_TRAIN_IMGS_PATH)[0] / 255
    ten_input = tf.reshape(tf.convert_to_tensor(num_input), (1, 28, 28))

    rect_input_no_pad = np.ones((28, 28))
    ten_rect_input_no_pad = tf.reshape(tf.convert_to_tensor(rect_input_no_pad),
                                       (1, 28, 28))

    rect_input = np.zeros((28, 28))
    rect_input[10:18, 10:18] = 1
    ten_rect_inputs = tf.reshape(tf.convert_to_tensor(rect_input), (1, 28, 28))

    import nrefocus

    for d in D:
        tensor_out = my_fft_prop(ten_rect_inputs, d)
        out = nrefocus.refocus(rect_input, d, 1, 1)

        plt.subplot(311)
        plt.imshow(tf.abs(tensor_out[0])**2)
        plt.title("my func")

        plt.subplot(312)
        plt.imshow(np.abs(out**2))
        plt.title("NREFOCUS")

        plt.subplot(313)
        distance = tf.abs(tf.abs(tensor_out[0])**2 - np.abs(out)**2)
        max = np.max(distance)
        mean = np.mean(distance)
        plt.imshow(distance)
        plt.title("Distance, max = {},mean err = {}".format(max, mean))
Пример #11
0
interferometry (SID4Bio, Phasics S.A., France).
The diameter of the cell is about 20µm.
"""
import matplotlib.pylab as plt
import numpy as np
import unwrap

import nrefocus

from example_helper import load_cell

# load initial cell
cell1 = load_cell("HL60_field.zip")

# refocus to two different positions
cell2 = nrefocus.refocus(cell1, 15, 1, 1)  # forward
cell3 = nrefocus.refocus(cell1, -15, 1, 1)  # backward

# amplitude range
vmina = np.min(np.abs(cell1))
vmaxa = np.max(np.abs(cell1))
ampkw = {"cmap": plt.get_cmap("gray"), "vmin": vmina, "vmax": vmaxa}

# phase range
cell1p = unwrap.unwrap(np.angle(cell1))
cell2p = unwrap.unwrap(np.angle(cell2))
cell3p = unwrap.unwrap(np.angle(cell3))
vminp = np.min(cell1p)
vmaxp = np.max(cell1p)
phakw = {"cmap": plt.get_cmap("coolwarm"), "vmin": vminp, "vmax": vmaxp}
Пример #12
0
def mie(radius=5e-6, sphere_index=1.339, medium_index=1.333,
        wavelength=550e-9, pixel_size=1e-7, grid_size=(80, 80),
        center=(39.5, 39.5), focus=0, arp=True):
    """Mie-simulated field behind a dielectric sphere

    Parameters
    ----------
    radius: float
        Radius of the sphere [m]
    sphere_index: float
        Refractive index of the sphere
    medium_index: float
        Refractive index of the surrounding medium
    wavelength: float
        Vacuum wavelength of the imaging light [m]
    pixel_size: float
        Pixel size [m]
    grid_size: tuple of floats
        Resulting image size in x and y [px]
    center: tuple of floats
        Center position in image coordinates [px]
    focus: float
        .. versionadded:: 0.5.0

        Axial focus position [m] measured from the center of the
        sphere in the direction of light propagation.
    arp: bool
        Use arbitrary precision (ARPREC) in BHFIELD computations

    Returns
    -------
    qpi: qpimage.QPImage
        Quantitative phase data set
    """
    # simulation parameters
    radius_um = radius * 1e6  # radius of sphere in um
    propd_um = radius_um  # simulate propagation through full sphere
    propd_lamd = radius / wavelength  # radius in wavelengths
    wave_nm = wavelength * 1e9
    # Qpsphere models define the position of the sphere with an index in
    # the array (because it is easier to work with). The pixel
    # indices run from (0, 0) to grid_size (without endpoint). BHFIELD
    # requires the extent to be given in µm. The distance in µm between
    # first and last pixel (measured from pixel center) is
    # (grid_size - 1) * pixel_size,
    size_um = (np.array(grid_size) - 1) * pixel_size * 1e6
    # The same holds for the offset. If we use size_um here,
    # we already take into account the half-pixel offset.
    offset_um = np.array(center) * pixel_size * 1e6 - size_um / 2

    kwargs = {"radius_sphere_um": radius_um,
              "refractive_index_medium": medium_index,
              "refractive_index_sphere": sphere_index,
              "measurement_position_um": propd_um,
              "wavelength_nm": wave_nm,
              "size_simulation_um": size_um,
              "shape_grid": grid_size,
              "offset_x_um": offset_um[0],
              "offset_y_um": offset_um[1]}

    background = np.exp(1j * 2 * np.pi * propd_lamd * medium_index)

    field = simulate_sphere(arp=arp, **kwargs) / background

    # refocus
    refoc = nrefocus.refocus(field,
                             d=-((radius+focus) / pixel_size),
                             nm=medium_index,
                             res=wavelength / pixel_size)

    # Phase (2PI offset corrected) and amplitude
    amp, pha = field2ap_corr(refoc)

    meta_data = {"pixel size": pixel_size,
                 "wavelength": wavelength,
                 "medium index": medium_index,
                 "sim center": center,
                 "sim radius": radius,
                 "sim index": sphere_index,
                 "sim model": "mie",
                 }

    qpi = qpimage.QPImage(data=(pha, amp),
                          which_data="phase,amplitude",
                          meta_data=meta_data)
    return qpi
A = 200

print("Example: Backpropagation from 3D Mie scattering")
print("Refractive index of medium:", cfg["nm"])
print("Measurement position from object center:", cfg["lD"])
print("Wavelength sampling:", cfg["res"])
print("Number of angles for reconstruction:", A)
print("Performing backpropagation.")

# Reconstruction angles
angles = np.linspace(0, 2 * np.pi, A, endpoint=False)

# Perform focusing
Ex = nrefocus.refocus(
    Ex,
    d=-cfg["lD"] * cfg["res"],
    nm=cfg["nm"],
    res=cfg["res"],
)

# Create sinogram
u_sin = np.tile(Ex.flat, A).reshape(A, int(cfg["size"]), int(cfg["size"]))

# Apply the Rytov approximation
u_sinR = odt.sinogram_as_rytov(u_sin)

# Backpropagation
fR = odt.backpropagate_3d(uSin=u_sinR,
                          angles=angles,
                          res=cfg["res"],
                          nm=cfg["nm"],
                          lD=0,