Exemple #1
0
def stack_mat2d(k, d, epsv, epsa, betay=0., method="4x4", mask=None):
    n = len(d)
    indices = range(n)
    if method.startswith("2x2"):
        indices = reversed(indices)
    verbose_level = DTMMConfig.verbose
    if verbose_level > 1:
        print("Building stack matrix.")
    for i in range(n):
        print_progress(i, n, level=verbose_level)
        mat = layer_mat2d(k,
                          d[i],
                          epsv[i],
                          epsa[i],
                          betay=betay,
                          mask=mask,
                          method=method)

        if i == 0:
            if isinstance(mat, tuple):
                out = tuple((m.copy() for m in mat))
            else:
                out = mat.copy()
        else:
            if isinstance(mat, tuple):
                out = tuple((bdotmm(o, m) for o, m in zip(out, mat)))
            else:
                out = bdotmm(out, mat)

    print_progress(n, n, level=verbose_level)

    return out
Exemple #2
0
def stack_mat(kd, epsv, epsa, beta=0, phi=0, method="4x4", out=None):
    """Computes a stack characteristic matrix M = M_1.M_2....M_n if method is
    4x4, 4x2(2x4) and a characteristic matrix M = M_n...M_2.M_1 if method is
    2x2.
    
    Note that this function calls :func:`layer_mat`, so numpy broadcasting 
    rules apply to kd[i], epsv[i], epsa[], beta and phi. 
    
    Parameters
    ----------
    kd : array_like
        A sequence of phase values (layer thickness times wavenumber in vacuum).
        len(kd) must match len(epsv) and len(epsa).
    epsv : array_like
        A sequence of epsilon eigenvalues.
    epsa : array_like
        A sequence of optical axes orientation angles (psi, theta, phi).
    beta : float
        Beta angle of input light.
    phi : float
        Phi angle of input light.
    method : str
        One of `4x4` (4x4 berreman), `2x2` (2x2 jones) or `4x2` (4x4 single reflections)
    out : ndarray, optional
    
    Returns
    -------
    cmat : ndarray
        Characteristic matrix of the stack.
    """
    t0 = time.time()
    mat = None
    n = len(kd)
    indices = range(n)
    if method == "2x2":
        indices = reversed(indices)
    verbose_level = DTMMConfig.verbose
    if verbose_level > 1:
        print("Building stack matrix.")
    for pi, i in enumerate(range(n)):
        print_progress(pi, n, level=verbose_level)
        mat = layer_mat(kd[i],
                        epsv[i],
                        epsa[i],
                        beta=beta,
                        phi=phi,
                        method=method,
                        out=mat)
        if pi == 0:
            if out is None:
                out = mat.copy()
            else:
                out[...] = mat
        else:
            dotmm(out, mat, out)
    print_progress(n, n, level=verbose_level)
    t = time.time() - t0
    if verbose_level > 1:
        print("     Done in {:.2f} seconds!".format(t))
    return out
Exemple #3
0
def reflection_mat2d(smat):
    verbose_level = DTMMConfig.verbose
    if verbose_level > 1:
        print("Building reflectance and transmittance matrix.")
    if isinstance(smat, tuple):
        out = []
        n = len(smat)
        for i, s in enumerate(smat):
            print_progress(i, n, level=verbose_level)
            out.append(_reflection_mat2d(s))
        print_progress(n, n, level=verbose_level)
        return tuple(out)
    else:
        return _reflection_mat2d(smat)
Exemple #4
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
Exemple #5
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