Source code for qpsphere.models.mod_mie

import nrefocus
import numpy as np
import qpimage
from skimage.restoration import unwrap

from ._bhfield import simulate_sphere

def field2ap_corr(field):
    """Determine amplitude and offset-corrected phase from a field

    The phase jumps sometimes appear after phase unwrapping.

    field: 2d complex np.ndarray
        Complex input field

    amp: 2d real np.ndarray
        Amplitude data
    pha: 2d real np.ndarray
        Phase data, corrected for 2PI offsets
    phase = unwrap.unwrap_phase(np.angle(field), seed=47)
    samples = []
    samples.append(phase[:, :3].flatten())
    samples.append(phase[:, -3:].flatten())
    samples.append(phase[:3, 3:-3].flatten())
    samples.append(phase[-3:, 3:-3].flatten())
    pha_offset = np.median(np.hstack(samples))
    num_2pi = np.round(pha_offset / (2 * np.pi))
    phase -= num_2pi * 2 * np.pi
    ampli = np.abs(field)
    return ampli, phase

[docs]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