Example #1
0
def _layers_list(optical_data, eff_data, nin, nout, nstep):
    """Build optical data layers list and effective data layers list.
    It appends/prepends input and output layers. A layer consists of
    a tuple of (n, thickness, epsv, epsa) where n is number of sublayers"""
    d, epsv, epsa = validate_optical_data(optical_data)
    n = len(d)
    substeps = np.broadcast_to(np.asarray(nstep), (n, ))
    layers = [(n, (t / n, ev, ea))
              for n, t, ev, ea in zip(substeps, d, epsv, epsa)]
    #add input and output layers
    layers.insert(0,
                  (1,
                   (0., np.broadcast_to(refind2eps([nin] * 3), epsv[0].shape),
                    np.broadcast_to(np.array(
                        (0., 0., 0.), dtype=FDTYPE), epsa[0].shape))))
    layers.append(
        (1, (0., np.broadcast_to(refind2eps([nout] * 3), epsv[0].shape),
             np.broadcast_to(np.array((0., 0., 0.), dtype=FDTYPE),
                             epsa[0].shape))))
    if eff_data is None:
        d_eff, epsv_eff, epsa_eff = _isotropic_effective_data(optical_data)
    else:
        d_eff, epsv_eff, epsa_eff = validate_optical_data(eff_data,
                                                          homogeneous=True)
    eff_layers = [(n, (t / n, ev, ea))
                  for n, t, ev, ea in zip(substeps, d_eff, epsv_eff, epsa_eff)]
    eff_layers.insert(
        0, (1, (0., refind2eps([nin] * 3), np.array(
            (0., 0., 0.), dtype=FDTYPE))))
    eff_layers.append(
        (1, (0., refind2eps([nout] * 3), np.array((0., 0., 0.),
                                                  dtype=FDTYPE))))
    return layers, eff_layers
Example #2
0
def plot_angles(data, **kwargs):
    """Plots eps angles for optical data or angles data.
    
    Parameters
    ----------
    
    data : optical_data or material (eps)
        A valid optical data tuple, eps array
    eps : array or None, optional
        Specifies which eps values to plot. If not given, all data is plotted.
    center : bool, optional
        Whether to view coordinates from the center of the box.
    xlim : (low, high) or None, optional
        A tuple describing the coordinate limits in the x direction (width).
    ylim : (low, high) or None, optional
        A tuple describing the coordinate limits in the y direction (height).
    zlim : (low, high) or None, optional
        A tuple describing the coordinate limits in the z direction (layer index).
    ax : matplotlib.axes or None, optional
        If specified, plot to ax.
    """
    if isinstance(data, tuple):
        d, eps, angles = validate_optical_data(data)
    else:
        angles = data
    director = angles2director(angles)
    return plot_director(director, **kwargs)
Example #3
0
def _isotropic_effective_data(data):
    d, material, angles = data
    n = len(d)
    epseff = uniaxial_order(0., material).mean(axis=(0, 1, 2))
    epseff = np.broadcast_to(
        epseff, (n, 3)).copy()  #better to make copy.. to make it c contiguous
    aeff = np.array((0., 0., 0.))
    aeff = np.broadcast_to(
        aeff, (n, 3)).copy()  #better to make copy.. to make it c contiguous
    return validate_optical_data((d, epseff, aeff), homogeneous=True)
Example #4
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
Example #5
0
def plot_material(data,
                  eps=None,
                  center=False,
                  xlim=None,
                  ylim=None,
                  zlim=None,
                  ax=None):
    """Plots material (in color) of the optical data.
    
    Parameters
    ----------
    
    data : optical_data or material (eps)
        A valid optical data tuple, eps array
    eps : array or None, optional
        Specifies which eps values to plot. If not given, all data is plotted.
    center : bool, optional
        Whether to view coordinates from the center of the box.
    xlim : (low, high) or None, optional
        A tuple describing the coordinate limits in the x direction (width).
    ylim : (low, high) or None, optional
        A tuple describing the coordinate limits in the y direction (height).
    zlim : (low, high) or None, optional
        A tuple describing the coordinate limits in the z direction (layer index).
    ax : matplotlib.axes or None, optional
        If specified, plot to ax.
    """
    if isinstance(data, tuple):
        d, material, angles = validate_optical_data(data)
    else:
        material = data
    if material.ndim == 3:
        material = material[None, ...]
    material = np.asarray(material, dtype="float32")

    assert material.ndim == 4

    if eps is None:
        eps = unique_eps(material)
    else:
        eps = np.asarray(eps)
        if eps.ndim == 1:
            eps = eps[None, :]

    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        try:
            #this does not work in recent versions of matplotlib
            ax.set_aspect('equal')
        except NotImplementedError:
            pass
    xx, yy, zz = _r3(material.shape[0:-1], center)

    #mmin, mmax  = material.min(), material.max()
    #if mmax != mmin:
    #    colors = (material-mmin)/(mmax-mmin)
    #else:
    #    colors = material-mmin

    for e in eps:
        mask = (material[..., 0] == e[0]) & (material[..., 1] == e[1]) & (
            material[..., 2] == e[2])
        mask = _add_mask(mask, xx, xlim)
        mask = _add_mask(mask, yy, ylim)
        mask = _add_mask(mask, zz, zlim)
        xs = xx[mask]
        ys = yy[mask]
        zs = zz[mask]
        #cs = colors[mask,:]
        #ax.scatter(xs, ys, zs,depthshade = False, s = 1, marker = ".", c = cs)
        ax.scatter(xs, ys, zs, depthshade=False, s=1, marker=".", label=e)

    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    plt.legend()

    return ax.figure, ax