예제 #1
0
def project_normalized_fft(field, dmat, window=None, ref=None, out=None):
    if ref is not None:
        fref = fft2(ref, out=out)
        intensity1 = field2intensity(fref)
        f1 = fft2(field, out=out)
    else:
        f1 = fft2(field, out=out)
        intensity1 = field2intensity(f1)
    f2 = dotmf(dmat, f1, out=f1)
    intensity2 = field2intensity(f2)
    f3 = normalize_field(f2, intensity1, intensity2, out=f2)
    out = ifft2(f3, out=out)
    if window is not None:
        out = np.multiply(out, window, out=out)
    return out
예제 #2
0
def _transfer_ray_4x4_1_windows(windows, field, wavenumbers, layer, dmat1, dmat2, betas, phis,
                    nsteps = 1, out = None,
                    betamax = BETAMAX):
        
    d, epsv, epsa = layer

    kd = wavenumbers*d 
    
    if out is None:
        out = np.zeros_like(field)

    for j in range(nsteps):
        field = dotmf(dmat1,field)
        for window, beta, phi in zip(windows, betas, phis):
            alpha, f = alphaf(beta,phi,epsv,epsa)
            p = phasem(alpha,kd[...,None,None])
            
            e = E_mat(f, mode = None)
            ei = inv(e)
            
            f = field * window
            
            
            f = ifft2(f, out = f)
            f = dotmdmf(e,p,ei,f, out = f)  
            f = fft2(field, out = f)
            out += f
            
        out = dotmf(dmat2,out, out = out)
                  
    return out
예제 #3
0
def project_normalized_local(field, dmat, window=None, ref=None, out=None):
    f1 = fft2(field)
    f2 = dotmf(dmat, f1, out=f1)
    f = ifft2(f2, out=f2)
    pmat1 = normal_polarizer(jonesvec(transpose(f[..., ::2, :, :])))
    pmat2 = -pmat1
    pmat2[..., 0, 0] += 1
    pmat2[..., 1, 1] += 1  #pmat1 + pmat2 = identity by definition
    pmat2[..., 2, 2] += 1  #pmat1 + pmat2 = identity by definition
    pmat2[..., 3, 3] += 1  #pmat1 + pmat2 = identity by definition

    if ref is not None:
        intensity1 = field2intensity(dotmf(pmat1, ref))
        ref = dotmf(pmat2, ref)

    else:
        intensity1 = field2intensity(dotmf(pmat1, field))
        ref = dotmf(pmat2, field)

    intensity2 = field2intensity(f)

    f = normalize_field(f, intensity1, intensity2)

    out = np.add(f, ref, out=out)
    if window is not None:
        out = np.multiply(out, window, out=out)
    return out
예제 #4
0
def mean_betaphi(field, k0):
    """Calculates mean beta and phi of a given field."""
    b = blackman(field.shape[-2:])
    f = fft2(field * b)  #filter it with blackman..
    betax, betay = betaxy(field.shape[-2:], k0)
    beta, phi = _fft_betaphi(f, betax, betay)
    return beta, phi
예제 #5
0
def propagate_4x4_full(field,
                       wavenumbers,
                       layer,
                       nsteps=1,
                       betamax=BETAMAX,
                       out=None):

    shape = field.shape[-2:]

    d, epsv, epsa = layer

    kd = wavenumbers * d / nsteps

    if out is None:
        out = np.empty_like(field)

    out_af = None
    pm = None

    ii, jj = np.meshgrid(range(shape[0]),
                         range(shape[1]),
                         copy=False,
                         indexing="ij")

    for step in range(nsteps):
        for i in range(len(wavenumbers)):
            ffield = fft2(field[..., i, :, :, :])
            ofield = np.zeros_like(out[..., i, :, :, :])
            b, p = betaphi(shape, wavenumbers[i])
            mask = b < betamax

            amplitude = ffield[..., mask]

            betas = b[mask]
            phis = p[mask]
            iind = ii[mask]
            jind = jj[mask]

            for bp in sorted(zip(range(len(betas)), betas, phis, iind, jind),
                             key=lambda el: el[1],
                             reverse=False):

                #for j,bp in enumerate(zip(betas,phis,iind,jind)):

                j, beta, phi, ieig, jeig = bp

                out_af = alphaffi(beta, phi, epsv, epsa, out=out_af)
                alpha, f, fi = out_af

                pm = phasem(alpha, kd[i], out=pm)
                w = eigenwave(amplitude.shape[:-1] + shape,
                              ieig,
                              jeig,
                              amplitude=amplitude[..., j])
                w = dotmdmf(f, pm, fi, w, out=w)
                np.add(ofield, w, ofield)

            out[..., i, :, :, :] = ofield
        field = out
    return out
예제 #6
0
def wave2eigenwave(wave, out=None):
    """Converts any wave to nearest eigenwave"""
    wave = np.asarray(wave)
    if out is None:
        out = np.empty(shape=wave.shape, dtype=CDTYPE)

    shape = wave.shape
    assert wave.ndim >= 2

    if len(shape) > 2:
        h = shape[-2]
        w = shape[-1]
        wave = wave.reshape(-1)  #flatten
        n = len(wave) // h // w
        wave = wave.reshape((n, h, w))
        o = out.reshape((n, h, w))
    else:
        o = out

    s = np.abs(fft.fft2(wave))**2

    if len(shape) == 2:
        s = s[None, ...]
        o = out[None, ...]

    for i, a in enumerate(s):
        avg = a.sum()
        indices = np.argmax(a)
        ii, jj = np.unravel_index(indices, a.shape)
        eigenwave(a.shape, ii, jj, amplitude=avg**0.5, out=o[i])

    return out
예제 #7
0
def _transfer_ray_4x4_1(field,
                        wavenumbers,
                        layer,
                        dmat1,
                        dmat2,
                        beta=0,
                        phi=0,
                        nsteps=1,
                        betamax=BETAMAX,
                        out=None):

    d, epsv, epsa = layer

    kd = wavenumbers * d

    alpha, f = alphaf(beta, phi, epsv, epsa)
    p = phasem(alpha, kd[..., None, None])

    e = E_mat(f, mode=None)
    ei = inv(e)

    for j in range(nsteps):
        field = dotmf(dmat1, field, out=out)
        field = ifft2(field, out=field)
        field = dotmdmf(e, p, ei, field, out=field)
        field = fft2(field, out=field)
        field = dotmf(dmat2, field, out=out)

    return field
예제 #8
0
def diffract(fieldv, dmat, window=None, out=None):
    f = fft2(fieldv, out=out)
    f2 = dotmf(dmat, f, out=f)
    out = ifft2(f2, out=out)
    if window is not None:
        out = np.multiply(out, window, out=out)
    return out
예제 #9
0
def filter_eps(eps, k, betamax=1):
    eps = np.moveaxis(eps, -1, -3)
    feps = fft2(eps)
    beta, phi = betaphi(feps.shape[-2:], k)
    mask = beta > betamax
    feps[..., mask] = 0.
    eps = ifft2(feps)
    eps = np.moveaxis(eps, -3, -1)
    return eps
예제 #10
0
def diffract(field,
             dmat,
             window=None,
             input_fft=False,
             output_fft=False,
             out=None):
    """Takes input field vector and diffracts it
    
    Parameters
    ----------
    field : (...,4,:,:) array
        Input field array.
    dmat : array
        Diffraction matrix. Use :func:`field_diffraction_matrix`to create one
    window : array, optional
        A window function applied to the result
    input_fft : bool
        Specifies whether input field array is the Fourier transform of the field.
        By default, input is assumed to be in real space.
    output_fft : bool
        Specifies whether the computed field array is the Fourier transform.
        By default, output is assumed to be in real space.
    out : ndarray, optional
        If specified, store the results here.
        
    Returns
    -------
    field : (...,4,:,:) array
        Diffracted field in real space (if output_fft == False )or in fft spaace
        (if output_fft == True).
            
    """
    if not input_fft:
        field = fft2(field, out=out)
        out = field
    if dmat is not None:
        out = dotmf(dmat, field, out=out)
    else:
        #make it work for dmat = None input... so just copy data
        if out is None:
            out = field.copy()
        else:
            if out is not field:
                out[...] = field
    if not output_fft:
        out = ifft2(out, out=out)
    if window is not None:
        if output_fft:
            raise ValueError(
                "Cannot use window function if ouput is fft field.")
        out = np.multiply(out, window, out=out)
    return out
예제 #11
0
def project_normalized_total(field, dmat, window=None, ref=None, out=None):
    if ref is not None:
        i1 = total_intensity(ref)
    else:
        i1 = total_intensity(field)
    f1 = fft2(field, out=out)

    f2 = dotmf(dmat, f1, out=f1)
    out = ifft2(f2, out=out)
    i2 = total_intensity(out)

    out = normalize_field_total(out, i1, i2, out=out)

    if window is not None:
        out = np.multiply(out, window, out=out)
    return out
예제 #12
0
파일: denoise.py 프로젝트: Alex-Vasile/dtmm
def denoise_field(field,
                  wavenumbers,
                  beta,
                  smooth=1,
                  filter_func=exp_notch_filter,
                  out=None):
    """Denoises field by attenuating modes around the selected beta parameter.
    """
    ffield = fft2(field, out=out)
    ffield = denoise_fftfield(ffield,
                              wavenumbers,
                              beta,
                              smooth=smooth,
                              filter_func=filter_func,
                              out=ffield)
    return ifft2(ffield, out=ffield)
예제 #13
0
def apply_mode_jonesmat(pmat, field, out=None):
    """Multiplies matrix with field data in fft space.
    
    Parameters
    ----------
    pmat : array 
        A 4x4 jones matrix of shape (...,:,:,4,4) for field data or
        2x2 jones matrix of shape (...,:,:,2,2) for E-field data or
    field :  array
        Field data array of shape (...,4,:,:) or (...,2,:,:).
    out : ndarray, optional
        If specified, the results are written here.
        
    Returns
    -------
    out : array
        Computed field array of shape (...,4,:,:) or (...,2,:,:).
    """
    fft = fft2(field, out=out)
    pfft = dotmf(pmat, fft, out=fft)
    return ifft2(fft, out=pfft)
예제 #14
0
def field2modes(field, k0, betamax=BETAMAX):
    """Converts 2D field array to modes array.
    
    Parameters
    ----------
    field : ndarray or tuple of ndarrays
        Input field array (or tuple of input fields for each wavenumber). The 
        shape of the input arrays must be (...,4,:,:) representing.
    k0 : float or a sequence of floats
        Defines the wavenumber. Fol multi-wavelength data, this must be a
        sequence of wawenumbers
    betamax : float, optional
        The beta cutoff parameter.
        
    Returns
    -------
    mask, modes : ndarray, ndarray or ndarray, tuple of ndarrays
        For a single-wavelength data it returns the mask array specifying
        the mode indices and modes coefficients array. For multi-wavelength data
        the modes is a tuple of ndarrays for each of the wavelengths. Length
        of the mask in this case equals length of the wavenumbers. 
            
    """
    if isinstance(field, tuple):
        out = tuple(
            (field2modes(field[i], k0[i], betamax) for i in range(len(field))))
        mask = tuple(o[0] for o in out)
        modes = tuple(o[1] for o in out)
        return mask, modes

    f = fft2(field)
    k0 = np.asarray(k0)
    mask = eigenmask(f.shape[-2:], k0, betamax)
    if k0.ndim == 0:
        return mask, np.moveaxis(f[..., mask], -2, -1)
    else:
        return mask, tuple((np.moveaxis(f[..., i, :, :, :][..., mask[i]], -2,
                                        -1) for i in range(len(k0))))
예제 #15
0
    def _calculate_specter_mode(self, recalc=False, **params):
        self.set_parameters(**params)

        if self.ofield is None:
            recalc = True  #first time only trigger calculation

        if recalc or self._has_parameter_updated("analyzer", "sample"):
            sample = self.sample if self.sample is not None else 0.
            if self.analyzer is not None:
                angle = -np.pi / 180 * (self.analyzer - sample)
                c, s = np.cos(angle), np.sin(angle)
                self.pmat = mode_polarizer(self.ifield.shape[-2:],
                                           self.ks,
                                           jones=(c, s),
                                           epsv=self.epsv,
                                           epsa=self.epsa,
                                           betamax=self.betamax)
                if self.pmode != "mode":
                    self.pmat = self.pmat[..., 0:1, 0:1, :, :]

        if recalc or self._has_parameter_updated("focus"):
            if self.mode is None:
                self.ffield = fft2(self.ifield[self.focus])
            else:
                self.dmat = field_diffraction_matrix(self.ifield.shape[-2:],
                                                     self.ks,
                                                     d=0,
                                                     epsv=self.epsv,
                                                     epsa=self.epsa,
                                                     mode=self.mode,
                                                     betamax=self.betamax)
                self.ffield = fft2(self.ifield[self.focus])

            recalc = True  #trigger update of self.data

        if recalc or self._has_parameter_updated("sample", "polarizer"):
            sample = self.sample if self.sample is not None else 0.
            if self.polarizer is not None:
                angle = -np.pi / 180 * (self.polarizer - sample)
                c, s = np.cos(angle), np.sin(angle)

                self.data = _redim(self.ffield, ndim=6)
                x = c * self.data[:, 0]
                y = s * self.data[:, 1]
                self.data = x + y
            else:
                self.data = _redim(self.ffield, ndim=5)

        if recalc or self._has_parameter_updated(
                "analyzer", "sample", "polarizer", "focus", "intensity"):
            if self.dmat is not None:
                pmat = dotmm(self.pmat, self.dmat)
            else:
                pmat = self.pmat
            self.ofield = dotmf(pmat, self.data, out=self.ofield)
            self.ofield = ifft2(self.ofield, out=self.ofield)

            for i, data in enumerate(self.ofield):
                if i == 0:
                    self.specter = field2specter(data)
                else:
                    self.specter += field2specter(data)
            recalc = True

        if recalc or "intensity" in self._updated_parameters:
            self._updated_parameters.clear()
            self._updated_parameters.add(
                "intensity")  #trigger calculate_image call
        else:
            self._updated_parameters.clear()

        return self.specter
예제 #16
0
 def ffield(self):
     if self._ffield is None:
         self._ffield = fft2(self.ifield[self.focus])
     return self._ffield
예제 #17
0
    def _calculate_specter_mode(self, recalc=False, **params):
        self.set_parameters(**params)
        if self.ofield is None:
            recalc = True  #first time only trigger calculation
        if recalc or self._has_parameter_updated("sample", "polarizer"):
            sample = self.sample if self.sample is not None else 0.
            if self.polarizer is not None:
                if self.ffield is None:
                    self.ffield = fft2(self.ifield)
                angle = -np.pi / 180 * (self.polarizer - sample)
                c, s = np.cos(angle), np.sin(angle)

                self.data = _redim(self.ffield, ndim=6)
                x = c * self.data[:, 0]
                y = s * self.data[:, 1]
                self.data = x + y
            else:
                self.data = _redim(self.ffield, ndim=5)

        if recalc or self._has_parameter_updated("focus"):
            if self.diffraction == True or self.mode is not None:
                #if mode is selected, we need to project the field using diffraction
                d = 0 if self.focus is None else self.focus
                self.dmat = field_diffraction_matrix(self.ifield.shape[-2:],
                                                     self.ks,
                                                     d=d,
                                                     epsv=self.epsv,
                                                     epsa=self.epsa,
                                                     mode=self.mode,
                                                     betamax=self.betamax)
            else:
                self.dmat = np.asarray(np.diag((1, 1, 1, 1)), CDTYPE)
        if recalc or self._has_parameter_updated("analyzer", "sample"):
            sample = self.sample if self.sample is not None else 0.
            if self.analyzer is not None:
                angle = -np.pi / 180 * (self.analyzer - sample)
                c, s = np.cos(angle), np.sin(angle)
                self.pmat = mode_polarizer(self.ifield.shape[-2:],
                                           self.ks,
                                           jones=(c, s),
                                           epsv=self.epsv,
                                           epsa=self.epsa,
                                           betamax=self.betamax)
            else:
                self.pmat = None

        if recalc or self._has_parameter_updated(
                "analyzer", "sample", "polarizer", "focus", "intensity"):
            tmat = None
            if self.pmat is not None and self.dmat is not None:
                tmat = dotmm(self.pmat, self.dmat)
            if self.pmat is None and self.dmat is not None:
                tmat = self.dmat
            if self.pmat is not None and self.dmat is None:
                tmat = self.pmat
            if tmat is not None:
                self.ofield = dotmf(tmat, self.data, out=self.ofield)
            self.ofield = ifft2(self.ofield, out=self.ofield)

            for i, data in enumerate(self.ofield):
                if i == 0:
                    self.specter = field2specter(data)
                else:
                    self.specter += field2specter(data)

            recalc = True

        if recalc or "intensity" in self._updated_parameters:
            self._updated_parameters.clear()
            self._updated_parameters.add(
                "intensity")  #trigger calculate_image call
        else:
            self._updated_parameters.clear()

        return self.specter
예제 #18
0
 def ffield(self):
     if self._ffield is None:
         self._ffield = fft2(self.ifield)
     return self._ffield
예제 #19
0
def transfer_2x2(field_data,
                 optical_data,
                 beta=None,
                 phi=None,
                 eff_data=None,
                 nin=1.,
                 nout=1.,
                 npass=1,
                 nstep=1,
                 diffraction=True,
                 reflection=True,
                 multiray=False,
                 split_diffraction=False,
                 betamax=BETAMAX,
                 ret_bulk=False,
                 out=None):
    """Tranfers input field data through optical data using the 2x2 method
    See transfer_field for documentation.
    """
    if reflection not in (0, 1, 2):
        raise ValueError(
            "Invalid reflection. The 2x2 method supports reflection mode 0,1 or 2."
        )

    verbose_level = DTMMConfig.verbose
    if verbose_level > 1:
        print(" * Initializing.")

    #create layers lists
    layers, eff_layers = _layers_list(optical_data, eff_data, nin, nout, nstep)
    #define input field data
    field_in, wavelengths, pixelsize = field_data
    #wavenumbers
    ks = k0(wavelengths, pixelsize)
    n = len(layers) - 1  #number of interfaces

    if beta is None and phi is None:
        ray_tracing = False
        beta, phi = field2betaphi(field_in, ks, multiray)
    else:
        ray_tracing = False
    if diffraction != 1:
        ray_tracing = False
    beta, phi = _validate_betaphi(beta, phi, extendeddim=field_in.ndim - 2)

    #define output field
    if out is None:
        if ret_bulk == True:
            bulk_out = np.zeros((n + 1, ) + field_in.shape, field_in.dtype)
            bulk_out[0] = field_in
            field_in = bulk_out[0]
            field_out = bulk_out[-1]
        else:
            bulk_out = None
            field_out = np.zeros_like(field_in)
    else:
        out[...] = 0.
        if ret_bulk == True:
            bulk_out = out
            bulk_out[0] = field_in
            field_in = bulk_out[0]
            field_out = bulk_out[-1]
        else:
            bulk_out = None
            field_out = out

    indices = list(range(n))

    #make sure we take only the forward propagating part of the field
    if diffraction:
        field0 = transmitted_field(field_in, ks, n=nin, betamax=betamax)
    else:
        field0 = transmitted_field_direct(field_in, beta, phi, n=nin)

    field = field0[..., ::2, :, :].copy()

    if npass > 1:
        if reflection == 0:
            raise ValueError(
                "Reflection mode `0` not compatible with npass > 1")
        field_in[
            ...] = field0  #modify input field so that it has no back reflection
        #keep reference to reflected waves
        refl = np.zeros(shape=(n + 1, ) + field.shape[:-3] + (2, ) +
                        field.shape[-2:],
                        dtype=field.dtype)
    else:
        #no need to store reflected waves
        refl = [None] * n

    if reflection in (0, 1) and 0 <= diffraction and diffraction < np.inf:
        work_in_fft = True
    else:
        work_in_fft = False

    if work_in_fft:
        field = fft2(field, out=field)

    tmpdata = {}

    for i in range(npass):
        if verbose_level > 0:
            prefix = " * Pass {:2d}/{}".format(i + 1, npass)
            suffix = ""
        else:
            prefix = ""
            suffix = "{}/{}".format(i + 1, npass)

        if i > 0:
            field[...] = 0.

        direction = (-1)**i
        _nstep, (thickness, ev, ea) = layers[indices[0]]

        for pindex, j in enumerate(indices):
            print_progress(pindex,
                           n,
                           level=verbose_level,
                           suffix=suffix,
                           prefix=prefix)

            jin = j + (1 - direction) // 2
            jout = j + (1 + direction) // 2
            _nstep, (thickness, ev, ea) = layers[jin]
            input_layer = (thickness, ev, ea)
            nstep, (thickness, ev, ea) = layers[jout]
            output_layer = (thickness * direction, ev, ea)

            _nstep, input_layer_eff = eff_layers[jin]
            _nstep, output_layer_eff = eff_layers[jout]

            d, e, a = input_layer_eff
            input_layer_eff = d * direction, e, a
            d, e, a = output_layer_eff
            output_layer_eff = d * direction, e, a

            if jout == 0:
                bulk = field_in
            elif jout == len(indices):
                bulk = field_out
            else:
                if bulk_out is None:
                    bulk = None
                else:
                    bulk = bulk_out[jout]

            if ray_tracing == True:
                if work_in_fft:
                    beta, phi = field2betaphi(ifft2(field), ks, multiray)
                else:
                    beta, phi = field2betaphi(field, ks, multiray)
                beta, phi = _validate_betaphi(beta,
                                              phi,
                                              extendeddim=field_in.ndim - 2)

            if diffraction >= 0 and diffraction < np.inf:

                if reflection <= 1:
                    field, refli = propagate_2x2_effective_1(
                        field,
                        ks,
                        input_layer,
                        output_layer,
                        input_layer_eff,
                        output_layer_eff,
                        beta=beta,
                        phi=phi,
                        nsteps=nstep,
                        diffraction=diffraction,
                        split_diffraction=split_diffraction,
                        reflection=reflection,
                        betamax=betamax,
                        mode=direction,
                        refl=refl[j],
                        bulk=bulk,
                        tmpdata=tmpdata)
                else:
                    field, refli = propagate_2x2_effective_2(
                        field,
                        ks,
                        input_layer,
                        output_layer,
                        input_layer_eff,
                        output_layer_eff,
                        beta=beta,
                        phi=phi,
                        nsteps=nstep,
                        diffraction=diffraction,
                        split_diffraction=split_diffraction,
                        reflection=reflection,
                        betamax=betamax,
                        mode=direction,
                        refl=refl[j],
                        bulk=bulk,
                        tmpdata=tmpdata)

            else:
                field, refli = propagate_2x2_full(field,
                                                  ks,
                                                  output_layer,
                                                  input_layer=input_layer,
                                                  nsteps=1,
                                                  reflection=reflection,
                                                  mode=direction,
                                                  betamax=betamax,
                                                  refl=refl[j],
                                                  bulk=bulk)

        print_progress(n, n, level=verbose_level, suffix=suffix, prefix=prefix)

        indices.reverse()

    if ret_bulk == True:
        return bulk_out, wavelengths, pixelsize
    else:
        return field_out, wavelengths, pixelsize
예제 #20
0
def _field2modes(field, k0, betamax=BETAMAX):
    f = fft2(field)
    mask = eigenmask(f.shape[-2:], k0, betamax)
    f = f[mask]
    return np.moveaxis(f, -2, -1)
예제 #21
0
def field2jones(field,
                ks=None,
                beta=None,
                phi=None,
                epsv=(1., 1., 1.),
                epsa=(0., 0., 0.),
                mode=+1,
                input_fft=False,
                output_fft=False,
                betamax=BETAMAX):
    """Converts (..., 4,n,m) field array to (..., 2,n,m) jones array
    
    The conversion is done either in reciprocal space (default) or in real space,
    if you provide the beta or phi parameter.
    
    Parameters
    ----------
    field : ndarray
        Input field array data of shape (..., 4,n,m).
    ks : array
        A list of k-values (wave numbers). Required if beta and phi are not provided.
    beta : float, optional
        If set, it defines the field beta parameter, conversion is then done
        in real space.
    phi : float, optional
        If set, it defines the field phi parameter, conversion is then done
        in real space.
    epsv : array
        The epsilon eigenvalues of the medium
    epsv : array
        The Euler rotation angles.
    mode : [+1 | -1]
        Propagation mode, +1 (forward) by default 
    input_fft : bool
        Specifies whether input array is fft data or not.
    output_fft : bool
        Specifies whether output array is fft data or not.
    betamax : float
        Defines the betamax parameter if transformation is done in Fourier space.
        
    Returns
    -------
    jones : ndarray
        Output jones array of shape (..., 2,n,m).
    """
    modal = beta is None and phi is None
    if modal and ks is None:
        raise ValueError(
            "For modal fields, you need to define the wave number(s).")
    elif not modal and ks is not None:
        import warnings
        warnings.warn(
            "`ks`, was set, although it is not required - field is not modal",
            UserWarning)

    field = np.asarray(field)
    out = np.empty(field.shape[:-3] + (2, ) + field.shape[-2:], field.dtype)
    if input_fft == False and modal:
        field = fft2(field)
    elif input_fft == True and not modal:
        field = ifft2(field)
    shape = field.shape[-3:]
    if modal:
        a, fmat = diffraction_alphaf(shape, ks, epsv, epsa, betamax=betamax)
    else:
        a, fmat, = alphaf(beta, phi, epsv, epsa)
    fvec = field2fvec(field)
    evec = field2fvec(out)
    evec[...] = fvec2E(fvec, fmat=fmat, mode=mode)
    if output_fft == False and modal:
        ifft2(out, out=out)
    elif output_fft == True and not modal:
        fft2(out, out=out)
    return out
예제 #22
0
def apply_mode_polarizer(pmat, field, out=None):
    """Multiplies mode polarizer with field data in fft space."""
    fft = fft2(field, out=out)
    pfft = dotmf(pmat, fft, out=fft)
    return ifft2(fft, out=pfft)
예제 #23
0
def propagate_4x4_effective_4(field,
                              wavenumbers,
                              layer,
                              effective_layer,
                              beta=0,
                              phi=0,
                              nsteps=1,
                              diffraction=True,
                              betamax=BETAMAX,
                              out=None):

    d_eff, epsv_eff, epsa_eff = effective_layer

    if diffraction <= 1:

        if diffraction != 0:
            dmat = corrected_field_diffraction_matrix(field.shape[-2:],
                                                      wavenumbers,
                                                      beta,
                                                      phi,
                                                      d=d_eff,
                                                      epsv=epsv_eff,
                                                      epsa=epsa_eff,
                                                      betamax=betamax)

        else:
            dmat = None

        return _transfer_ray_4x4_4(field,
                                   wavenumbers,
                                   layer,
                                   beta=beta,
                                   phi=phi,
                                   nsteps=nsteps,
                                   dmat=dmat,
                                   out=out)
    else:
        fout = np.zeros_like(field)
        _out = None
        field = fft2(field)

        try:
            broadcast_shape = beta.shape
            beta = beta[..., 0]
            phi = phi[..., 0]
        except IndexError:
            broadcast_shape = ()

        windows, (betas, phis) = fft_mask(field.shape,
                                          wavenumbers,
                                          int(diffraction),
                                          betax_off=beta * np.cos(phi),
                                          betay_off=beta * np.sin(phi),
                                          betamax=betamax)

        n = len(windows)
        betas = betas.reshape((n, ) + broadcast_shape)
        phis = phis.reshape((n, ) + broadcast_shape)

        if diffraction != 0:
            dmats = corrected_field_diffraction_matrix(field.shape[-2:],
                                                       wavenumbers,
                                                       betas,
                                                       phis,
                                                       d=d_eff,
                                                       epsv=epsv_eff,
                                                       epsa=epsa_eff)
        else:
            dmats = [None] * n

        for window, b, p, dmat in zip(windows, betas, phis, dmats):
            fpart = np.multiply(field, window, out=_out)
            fpart_re = ifft2(fpart, out=fpart)

            _out = _transfer_ray_4x4_4(fpart_re,
                                       wavenumbers,
                                       layer,
                                       beta=b,
                                       phi=p,
                                       nsteps=nsteps,
                                       dmat=dmat)
            fout = np.add(fout, _out, out=fout)


#        for window, b, p  in zip(windows, betas, phis):
#            fpart = field * window
#            fpart_re = ifft2(fpart)
#
#            b = b.reshape(beta_shape)
#            p = p.reshape(beta_shape)
#
#            if diffraction != 0:
#                dmat = corrected_field_diffraction_matrix(field.shape[-2:], wavenumbers, b,p, d=d_eff,
#                                     epsv = epsv_eff, epsa = epsa_eff)
#            else:
#                dmat = None
#
#            _out =  _transfer_ray_4x4_2(fpart_re, wavenumbers, layer,
#                                beta = b, phi = p, nsteps =  nsteps,
#                                dmat = dmat,_reuse = _reuse)
#            fout += _out

        if out is not None:
            out[...] = fout
        else:
            out = fout
        return out
예제 #24
0
def propagate_2x2_full(field,
                       wavenumbers,
                       layer,
                       input_layer=None,
                       nsteps=1,
                       mode=+1,
                       reflection=True,
                       betamax=BETAMAX,
                       refl=None,
                       bulk=None,
                       out=None):

    shape = field.shape[-2:]

    d, epsv, epsa = layer
    if input_layer is not None:
        d_in, epsv_in, epsa_in = input_layer

    kd = wavenumbers * d / nsteps

    if out is None:
        out = np.empty_like(field)

    ii, jj = np.meshgrid(range(shape[0]),
                         range(shape[1]),
                         copy=False,
                         indexing="ij")

    for step in range(nsteps):
        for i in range(len(wavenumbers)):
            ffield = fft2(field[..., i, :, :, :])
            ofield = np.zeros_like(out[..., i, :, :, :])

            b, p = betaphi(shape, wavenumbers[i])
            mask = b < betamax

            amplitude = ffield[..., mask]

            betas = b[mask]
            phis = p[mask]
            iind = ii[mask]
            jind = jj[mask]

            if bulk is not None:
                obulk = bulk[..., i, :, :, :]

            if refl is not None:
                tampl = fft2(refl[..., i, :, :, :])[..., mask]
                orefl = refl[..., i, :, :, :]
                orefl[...] = 0.

            for bp in sorted(zip(range(len(betas)), betas, phis, iind, jind),
                             key=lambda el: el[1],
                             reverse=False):
                #for j,bp in enumerate(zip(betas,phis,iind,jind)):

                j, beta, phi, ieig, jeig = bp

                out_af = alphaf(beta, phi, epsv, epsa)
                alpha, fmat_out = out_af
                e = E_mat(fmat_out, mode=mode)
                ei0 = inv(e)
                ei = ei0
                pm = phase_mat(alpha, kd[i, None, None], mode=mode)
                w = eigenwave(amplitude.shape[:-1] + shape,
                              ieig,
                              jeig,
                              amplitude=amplitude[..., j])
                if step == 0 and reflection != False:
                    alphain, fmat_in = alphaf(beta, phi, epsv_in, epsa_in)
                    if refl is not None:
                        ei, eri = Etri_mat(fmat_in, fmat_out, mode=mode)
                        ein = E_mat(fmat_in, mode=-1 * mode)
                        t = eigenwave(amplitude.shape[:-1] + shape,
                                      ieig,
                                      jeig,
                                      amplitude=tampl[..., j])
                        r = dotmf(eri, w)
                        r = dotmf(ein, r, out=r)
                        np.add(orefl, r, orefl)

                        w = dotmf(ei, w, out=w)
                        t = dotmf(ei0, t, out=t)
                        w = np.add(t, w, out=w)

                    else:
                        ei = Eti_mat(fmat_in, fmat_out, mode=mode)
                        w = dotmf(ei, w, out=w)
                    w = dotmf(dotmd(e, pm), w, out=w)
                    np.add(ofield, w, ofield)

                else:
                    w = dotmdmf(e, pm, ei, w, out=w)
                    np.add(ofield, w, ofield)

                if bulk is not None:
                    e2h = E2H_mat(fmat_out, mode=mode)
                    obulk[..., 1::2, :, :] += dotmf(e2h, w)
                    obulk[..., ::2, :, :] += w

            out[..., i, :, :, :] = ofield

        field = out
    return out, refl
예제 #25
0
def propagate_2x2_effective_2(field,
                              wavenumbers,
                              layer_in,
                              layer_out,
                              effective_layer_in,
                              effective_layer_out,
                              beta=0,
                              phi=0,
                              nsteps=1,
                              diffraction=True,
                              split_diffraction=False,
                              reflection=True,
                              betamax=BETAMAX,
                              mode=+1,
                              refl=None,
                              bulk=None,
                              out=None,
                              tmpdata=None):

    shape = field.shape[-2:]
    d_eff, epsv_eff, epsa_eff = effective_layer_out

    if diffraction <= 1:
        if diffraction:
            dmat = corrected_E_diffraction_matrix(shape,
                                                  wavenumbers,
                                                  beta,
                                                  phi,
                                                  d=d_eff,
                                                  epsv=epsv_eff,
                                                  epsa=epsa_eff,
                                                  mode=mode,
                                                  betamax=betamax)
        else:
            dmat = None

        return _transfer_ray_2x2_2(field,
                                   wavenumbers,
                                   layer_in,
                                   layer_out,
                                   dmat=dmat,
                                   beta=beta,
                                   phi=phi,
                                   nsteps=nsteps,
                                   reflection=reflection,
                                   betamax=betamax,
                                   mode=mode,
                                   refl=refl,
                                   bulk=bulk,
                                   out=out,
                                   tmpdata=tmpdata)
    else:
        fout = 0.
        fpart = None
        ffield = fft2(field)
        if refl is not None:
            frefl = fft2(refl)
            _refl = 0.
        else:
            _refl = None
        try:
            broadcast_shape = beta.shape
            beta = beta[..., 0]
            phi = phi[..., 0]
        except IndexError:
            broadcast_shape = ()

        windows, (betas, phis) = fft_mask(field.shape,
                                          wavenumbers,
                                          int(diffraction),
                                          betax_off=beta * np.cos(phi),
                                          betay_off=beta * np.sin(phi),
                                          betamax=betamax)

        n = len(windows)
        betas = betas.reshape((n, ) + broadcast_shape)
        phis = phis.reshape((n, ) + broadcast_shape)

        if split_diffraction == False:

            dmats = corrected_E_diffraction_matrix(shape,
                                                   wavenumbers,
                                                   betas,
                                                   phis,
                                                   d=d_eff,
                                                   epsv=epsv_eff,
                                                   epsa=epsa_eff,
                                                   mode=mode,
                                                   betamax=betamax)

            idata = zip(windows, betas, phis, dmats)
        else:
            idata = zip(windows, betas, phis)

        for data in idata:
            if split_diffraction == False:
                window, beta, phi, dmat = data
            else:
                window, beta, phi = data
                dmat = corrected_E_diffraction_matrix(shape,
                                                      wavenumbers,
                                                      beta,
                                                      phi,
                                                      d=d_eff,
                                                      epsv=epsv_eff,
                                                      epsa=epsa_eff,
                                                      mode=mode,
                                                      betamax=betamax)

            fpart = np.multiply(ffield, window, out=fpart)
            fpart_re = ifft2(fpart, out=fpart)

            if refl is not None:
                reflpart = frefl * window
                reflpart_re = ifft2(reflpart)
            else:
                reflpart_re = None
            _out, __refl = _transfer_ray_2x2_2(fpart_re,
                                               wavenumbers,
                                               layer_in,
                                               layer_out,
                                               dmat=dmat,
                                               beta=beta,
                                               phi=phi,
                                               nsteps=nsteps,
                                               betamax=betamax,
                                               reflection=reflection,
                                               mode=mode,
                                               bulk=bulk,
                                               out=out,
                                               refl=reflpart_re,
                                               tmpdata=tmpdata)

            fout += _out
            if refl is not None and reflection != 0:
                _refl += __refl

    if out is not None:
        out[...] = fout
    else:
        out = fout
    if refl is not None:
        refl[...] = _refl

    return out, refl
예제 #26
0
def _transfer_ray_2x2_1(fft_field,
                        wavenumbers,
                        layer,
                        effective_layer_in,
                        effective_layer_out,
                        dmat1,
                        dmat2,
                        beta=0,
                        phi=0,
                        nsteps=1,
                        mode=+1,
                        reflection=True,
                        betamax=BETAMAX,
                        refl=None,
                        bulk=None,
                        out=None,
                        tmpdata=None):
    _out = {} if tmpdata is None else tmpdata
    #fft_field = fft2(fft_field, out = out)
    shape = fft_field.shape[-2:]
    d_in, epsv_in, epsa_in = effective_layer_in

    d_out, epsv_out, epsa_out = effective_layer_out

    if reflection:
        tmat, rmat = E_tr_matrix(shape,
                                 wavenumbers,
                                 epsv_in=epsv_in,
                                 epsa_in=epsa_in,
                                 epsv_out=epsv_out,
                                 epsa_out=epsa_out,
                                 mode=mode,
                                 betamax=betamax)

    d, epsv, epsa = layer
    alpha, fmat = alphaf(beta, phi, epsv, epsa, out=_out.get("alphaf"))

    e = E_mat(fmat, mode=mode, copy=False)  #2x2 E-only view of fmat
    ei = inv(e, out=_out.get("ei"))
    #
    kd = wavenumbers * d
    p = phase_mat(alpha, kd[..., None, None], mode=mode, out=_out.get("p"))

    if tmpdata is not None:
        _out["alphaf"] = alpha, fmat
        _out["ei"] = ei
        _out["p"] = p

    for j in range(nsteps):
        if j == 0 and reflection:
            #reflect only at the beginning
            if refl is not None:
                trans = refl.copy()
                refl = dotmf(rmat, fft_field, out=refl)
                fft_field = dotmf(tmat, fft_field, out=out)
                fft_field = np.add(fft_field, trans, out=fft_field)

                if mode == -1 and bulk is not None:
                    field = ifft2(fft_field)
                    e2h = E2H_mat(fmat, mode=mode)
                    bulk[..., ::2, :, :] += field
                    bulk[..., 1::2, :, :] += dotmf(e2h, field, out=field)

                fft_field = dotmf(dmat1, fft_field, out=fft_field)
                out = fft_field
            else:
                fft_field = dotmf(tmat, fft_field, out=out)
                fft_field = dotmf(dmat1, fft_field, out=fft_field)
                out = fft_field
        else:
            if dmat1 is not None:
                fft_field = dotmf(dmat1, fft_field, out=out)
            out = fft_field
        field = ifft2(fft_field, out=out)
        field = dotmdmf(e, p, ei, field, out=field)
        fft_field = fft2(field, out=field)
        if dmat2 is not None:
            fft_field = dotmf(dmat2, fft_field, out=fft_field)
    #return fft_field, refl

    #out = ifft2(fft_field, out = out)

    if mode == +1 and bulk is not None:
        field = ifft2(fft_field)
        e2h = E2H_mat(fmat, mode=mode)
        bulk[..., 1::2, :, :] += dotmf(e2h, field)
        bulk[..., ::2, :, :] += field

    return fft_field, refl
예제 #27
0
파일: field.py 프로젝트: xj361685640/dtmm
def jones2field(jones,
                ks,
                beta=None,
                phi=None,
                epsv=(1., 1., 1.),
                epsa=(0., 0., 0.),
                mode=+1,
                input_fft=False,
                output_fft=False,
                betamax=BETAMAX):
    """Converts (..., 2,n,m) jones array to (..., 4,n,m) field array
    
    The conversion is done either in reciprocal space (default) or in real space,
    if you provide the beta or phi parameter.
    
    Parameters
    ----------
    jones : ndarray
        Input jones array data of shape (..., 2,n,m).
    ks : array
        A list of k-values (wave numbers).
    beta : float, optional
        If set, it defines the field beta parameter, conversion is then done
        in real space.
    phi : float, optional
        If set, it defines the field phi parameter, conversion is then done
        in real space.
    epsv : array
        The epsilon eigenvalues of the medium
    epsv : array
        The Euler rotation angles.
    mode : [+1 | -1]
        Propagation mode, +1 (forward) by default 
    input_fft : bool
        Specifies whether input array is fft data or not.
    output_fft : bool
        Specifies whether output array is fft data or not.
    betamax : float
        Defines the betamax parameter if transformation is done in Fourier space.
        
    Returns
    -------
    field : ndarray
        Output field array of shape (..., 4,n,m).
    """

    jones = np.asarray(jones)
    modal = beta is None and phi is None

    out = np.empty(jones.shape[:-3] + (4, ) + jones.shape[-2:], jones.dtype)
    if input_fft == False and modal:
        jones = fft2(jones)
    elif input_fft == True and not modal:
        jones = ifft2(jones)

    shape = jones.shape[-3:]
    if modal:
        a, fmat = diffraction_alphaf(shape, ks, epsv, epsa, betamax=betamax)
    else:
        a, fmat, = alphaf(beta, phi, epsv, epsa)
    fvec = field2fvec(out)
    jvec = field2fvec(jones)
    E2fvec(jvec, fmat=fmat, mode=mode, out=fvec)
    if output_fft == False and modal:
        ifft2(out, out=out)
    elif output_fft == True and not modal:
        fft2(out, out=out)
    return out
예제 #28
0
def transfer_4x4(field_data,
                 optical_data,
                 beta=0.,
                 phi=0.,
                 eff_data=None,
                 nin=1.,
                 nout=1.,
                 npass=1,
                 nstep=1,
                 diffraction=True,
                 reflection=1,
                 multiray=False,
                 norm=DTMM_NORM_FFT,
                 smooth=SMOOTH,
                 betamax=BETAMAX,
                 ret_bulk=False,
                 out=None):
    """Transfers input field data through optical data. See transfer_field.
    """
    if reflection not in (1, 2, 3, 4):
        raise ValueError(
            "Invalid reflection. The 4x4 method is either reflection mode 1 or 2."
        )
    if smooth > 1.:
        pass
        #smooth =1.
    elif smooth < 0:
        smooth = 0.
    verbose_level = DTMMConfig.verbose
    if verbose_level > 1:
        print(" * Initializing.")

    calc_reference = bool(norm & DTMM_NORM_REF)

    if (norm & DTMM_NORM_FFT):
        norm = "fft"
    else:
        if calc_reference:
            norm = "local"
        else:
            norm = "total"

    #define optical data
    d, epsv, epsa = validate_optical_data(optical_data)

    layers, eff_layers = _layers_list(optical_data, eff_data, nin, nout, nstep)

    #define input field data
    field_in, wavelengths, pixelsize = field_data

    #define constants
    ks = k0(wavelengths, pixelsize)

    n = len(layers)

    if beta is None and phi is None:
        ray_tracing = False
        beta, phi = field2betaphi(field_in, ks, multiray)
    else:
        ray_tracing = False
    if diffraction != 1:
        ray_tracing = False
    beta, phi = _validate_betaphi(beta, phi, extendeddim=field_in.ndim - 2)

    #define output field
    if out is None:
        if ret_bulk == True:
            bulk_out = np.zeros((n, ) + field_in.shape, field_in.dtype)
            bulk_out[0] = field_in
            field_in = bulk_out[0]
            field_out = bulk_out[-1]
        else:
            bulk_out = None
            field_out = np.zeros_like(field_in)
    else:
        out[...] = 0.
        if ret_bulk == True:
            bulk_out = out
            bulk_out[0] = field_in
            field_in = bulk_out[0]
            field_out = bulk_out[-1]
        else:
            bulk_out = None
            field_out = out
    indices = list(range(1, n - 1))
    #if npass > 1:
    #    field0 = field_in.copy()

    field0 = field_in.copy()
    field = field_in.copy()

    field_in[...] = 0.

    if norm == 2:
        #make sure we take only the forward propagating part of the field
        transmitted_field(field,
                          ks,
                          n=nin,
                          betamax=min(betamax, nin),
                          out=field)

    if calc_reference:
        ref = field.copy()
    else:
        ref = None

    i0 = field2intensity(transmitted_field(field0, ks, n=nin, betamax=betamax))
    i0 = i0.sum(tuple(range(i0.ndim))[-2:])

    if reflection not in (2, 4) and 0 <= diffraction and diffraction < np.inf:
        work_in_fft = True
    else:
        work_in_fft = False

    if work_in_fft:
        field = fft2(field, out=field)
    _reuse = False
    tmpdata = {}

    #:projection matrices.. set when needed
    if npass > 1:
        pin_mat = projection_matrix(field.shape[-2:],
                                    ks,
                                    epsv=refind2eps([nin] * 3),
                                    mode=+1,
                                    betamax=betamax)
        pout_mat = projection_matrix(field.shape[-2:],
                                     ks,
                                     epsv=refind2eps([nout] * 3),
                                     mode=+1,
                                     betamax=betamax)

    for i in range(npass):
        if verbose_level > 0:
            prefix = " * Pass {:2d}/{}".format(i + 1, npass)
            suffix = ""
        else:
            prefix = ""
            suffix = "{}/{}".format(i + 1, npass)

        _bulk_out = bulk_out
        direction = (-1)**i
        _nstep, (thickness, ev, ea) = layers[indices[0]]

        if direction == 1:
            _betamax = betamax
        else:
            _betamax = betamax

        for pindex, j in enumerate(indices):
            print_progress(pindex,
                           n,
                           level=verbose_level,
                           suffix=suffix,
                           prefix=prefix)

            nstep, (thickness, ev, ea) = layers[j]
            output_layer = (thickness * direction, ev, ea)

            _nstep, output_layer_eff = eff_layers[j]

            d, e, a = output_layer_eff
            output_layer_eff = d * direction, e, a

            if ray_tracing == True:
                if work_in_fft:
                    beta, phi = field2betaphi(ifft2(field), ks, multiray)
                else:
                    beta, phi = field2betaphi(field, ks, multiray)
                beta, phi = _validate_betaphi(beta,
                                              phi,
                                              extendeddim=field_in.ndim - 2)

            if calc_reference and i % 2 == 0:
                _nstep, (thickness_in, ev_in, ea_in) = layers[j - 1]
                input_layer = (thickness_in, ev_in, ea_in)
                ref2, refl = propagate_2x2_effective_2(ref[..., ::2, :, :],
                                                       ks,
                                                       input_layer,
                                                       output_layer,
                                                       None,
                                                       output_layer_eff,
                                                       beta=beta,
                                                       phi=phi,
                                                       nsteps=nstep,
                                                       diffraction=diffraction,
                                                       reflection=0,
                                                       betamax=_betamax,
                                                       mode=direction,
                                                       out=ref[..., ::2, :, :])

            if bulk_out is not None:
                out_field = _bulk_out[j]
            else:
                out_field = field

            if diffraction >= 0 and diffraction < np.inf:
                if reflection == 4:
                    field = propagate_4x4_effective_4(field,
                                                      ks,
                                                      output_layer,
                                                      output_layer_eff,
                                                      beta=beta,
                                                      phi=phi,
                                                      nsteps=nstep,
                                                      diffraction=diffraction,
                                                      betamax=_betamax,
                                                      out=out_field)
                elif reflection == 3:
                    field = propagate_4x4_effective_3(field,
                                                      ks,
                                                      output_layer,
                                                      output_layer_eff,
                                                      beta=beta,
                                                      phi=phi,
                                                      nsteps=nstep,
                                                      diffraction=diffraction,
                                                      betamax=_betamax,
                                                      out=out_field)

                elif reflection == 2:
                    field = propagate_4x4_effective_2(field,
                                                      ks,
                                                      output_layer,
                                                      output_layer_eff,
                                                      beta=beta,
                                                      phi=phi,
                                                      nsteps=nstep,
                                                      diffraction=diffraction,
                                                      betamax=_betamax,
                                                      out=out_field,
                                                      tmpdata=tmpdata)
                else:
                    field = propagate_4x4_effective_1(field,
                                                      ks,
                                                      output_layer,
                                                      output_layer_eff,
                                                      beta=beta,
                                                      phi=phi,
                                                      nsteps=nstep,
                                                      diffraction=diffraction,
                                                      betamax=_betamax,
                                                      out=out_field,
                                                      _reuse=_reuse)
            else:
                field = propagate_4x4_full(field,
                                           ks,
                                           output_layer,
                                           nsteps=nstep,
                                           betamax=_betamax,
                                           out=out_field)
            _reuse = True
        if ref is not None:
            ref[..., 1::2, :, :] = jones2H(ref2, ks, betamax=_betamax, n=nout)
        print_progress(n, n, level=verbose_level, suffix=suffix, prefix=prefix)

        indices.reverse()

        if work_in_fft == True:
            field = ifft2(field)

        if npass > 1:
            #smooth = 1. - i/(npass-1.)
            if i % 2 == 0:
                if i != npass - 1:
                    if verbose_level > 1:
                        print(" * Normalizing transmissions.")
                    if calc_reference:
                        np.multiply(ref, (nin / nout)**0.5, ref)

                    sigma = smooth * (npass - i) / (npass)

                    if norm == "fft":
                        field = project_normalized_fft(field,
                                                       pout_mat,
                                                       ref=ref,
                                                       out=field)
                    elif norm == "local":
                        field = project_normalized_local(field,
                                                         pout_mat,
                                                         ref=ref,
                                                         out=field)
                    elif norm == "total":
                        field = project_normalized_total(field,
                                                         pout_mat,
                                                         ref=ref,
                                                         out=field)

                    field = denoise_field(field, ks, nin, sigma, out=field)

                np.add(field_out, field, field_out)
                field = field_out.copy()

            else:
                field_in[...] = field
                if i != npass - 1:
                    if verbose_level > 1:
                        print(" * Normalizing reflections.")

                    sigma = smooth * (npass - i) / (npass)

                    ffield = fft2(field, out=field)
                    ffield = dotmf(pin_mat, ffield, out=ffield)
                    ffield = denoise_fftfield(ffield,
                                              ks,
                                              nin,
                                              sigma,
                                              out=ffield)
                    field = ifft2(field, out=ffield)

                    i0f = total_intensity(field)
                    fact = ((i0 / i0f))
                    fact = fact[..., None, None, None]
                    np.multiply(field, fact, out=field)

                    np.multiply(field_out, fact, out=field_out)
                    np.multiply(field_in, fact, out=field_in)

                    np.subtract(field0, field, out=field)

                    np.add(field_in, field, field_in)

                    if calc_reference:
                        ref = field.copy()

            if work_in_fft == True:
                field = fft2(field, out=field)

        else:
            field_out[...] = field
            field_in[...] = field0
    #denoise(field_out, ks, nout, smooth*10, out = field_out)

    if ret_bulk == True:
        if work_in_fft:
            ifft2(bulk_out[1:-1], out=bulk_out[1:-1])
        return bulk_out, wavelengths, pixelsize
    else:
        return field_out, wavelengths, pixelsize