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
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
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
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
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
def normalize_total(field, dmat, window=None, ref=None, out=None): if ref is not None: i1 = total_intensity(ref) else: i1 = total_intensity(field) f2 = dotmf(dmat, field, out=out) i2 = total_intensity(out) out = normalize_field_total(out, i1, i2, out=f2) if window is not None: out = np.multiply(out, window, out=out) return out
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
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
def apply_ray_jonesmat(pmat, field, out=None): """Multiplies matrix with field data in real 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 : array, optional If specified, the results are written here. Returns ------- out : ndarray Computed field array of shape (...,4,:,:) or (...,2,:,:). """ return dotmf(pmat, field, out=out)
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)
beta=beta, phi=phi, diffraction=False, pixelsize=step) #: transfer input light through stack field_data_out = dtmm.transfer_field(field_data_in, optical_data, beta=beta, phi=phi, method="2x2", reflection=2, diffraction=False) f, w, p = field_data_out Txx2 = field2poynting(dotmf( x_polarizer, f[0]))[..., 0, 0] * 2 #times two, because field_data_in[0][0] has intensity of 0.5 Tyx2 = field2poynting(dotmf(y_polarizer, f[0]))[..., 0, 0] * 2 Txy2 = field2poynting(dotmf( x_polarizer, f[1]))[..., 0, 0] * 2 #times two, because field_data_in[0][1] has intensity of 0.5 Tyy2 = field2poynting(dotmf(y_polarizer, f[1]))[..., 0, 0] * 2 # uncomment below to see how the viewer calculates.. it is same for beta = 0, # but slightly different for beta > 0 #viewer = dtmm.field_viewer(field_data_out, diffraction = False) #Txx2 = viewer.calculate_specter(polarizer = 0, analyzer = 0)[0,0]*2 #Tyy2 = viewer.calculate_specter(polarizer = 90, analyzer = 90)[0,0]*2
def _calculate_specter_normal(self, recalc=False, **params): self.set_parameters(**params) if self.ofield is None: recalc = True #first time only trigger calculation if recalc or "focus" in self._updated_parameters: if self.mode is None: self.ofield = self.ifield[self.focus] else: 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.ofield = diffract(self.ifield[self.focus], dmat, window=self.window, out=self.ofield) recalc = True if recalc or "polarizer" in self._updated_parameters or "analyzer" in self._updated_parameters or "sample" in self._updated_parameters: sample = self.sample if sample is None: sample = 0. if self.polarizer is None: tmp = _redim(self.ofield, ndim=5) out = np.empty_like(tmp[0]) else: angle = -np.pi / 180 * (self.polarizer - sample) c, s = np.cos(angle), np.sin(angle) tmp = _redim(self.ofield, ndim=6) out = np.empty_like(tmp[0, 0]) if self.analyzer is not None: angle = -np.pi / 180 * (self.analyzer - sample) #pmat = linear_polarizer(angle) pmat = ray_polarizer((np.cos(angle), np.sin(angle)), epsv=self.epsv, epsa=self.epsa) for i, data in enumerate(tmp): if self.polarizer is not None: x = data[0] * c y = np.multiply(data[1], s, out=out) ffield = np.add( x, y, out=out) #numexpr.evaluate("x*c+y*s", out = out) else: ffield = data if self.analyzer is not None: pfield = dotmf(pmat, ffield, out=out) else: pfield = ffield if i == 0: self.specter = field2specter(pfield) else: self.specter += field2specter(pfield) 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
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
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
def _calculate_specter_normal(self, recalc=False, **params): """Calculates field specter. Parameters ---------- recalc : bool, optional If specified, it forces recalculation. Otherwise, result is calculated only if calculation parameters have changed. params: kwargs, optional Any additional keyword arguments that are passed dirrectly to set_parameters method. """ self.set_parameters(**params) if self.ofield is None: recalc = True #first time only trigger calculation if recalc or "focus" in self._updated_parameters: if self.diffraction == True or self.mode is not None: #if mode is selected, we need to project the filed using diffraction d = 0 if self.focus is None else self.focus dmat = field_diffraction_matrix(self.ifield.shape[-2:], self.ks, d=d, epsv=self.epsv, epsa=self.epsa, mode=self.mode, betamax=self.betamax) self.ofield = diffract(self.ifield, dmat, window=self.window, out=self.ofield) else: #no diffraction at all.. if self.window is not None: self.ofield = self.ifield * self.window else: self.ofield = self.ifield.copy() recalc = True if recalc or "polarizer" in self._updated_parameters or "analyzer" in self._updated_parameters or "sample" in self._updated_parameters: sample = self.sample if sample is None: sample = 0. if self.polarizer is None: tmp = _redim(self.ofield, ndim=5) out = np.empty_like(tmp[0]) else: angle = -np.pi / 180 * (self.polarizer - sample) c, s = np.cos(angle), np.sin(angle) tmp = _redim(self.ofield, ndim=6) out = np.empty_like(tmp[0, 0]) if self.analyzer is not None: angle = -np.pi / 180 * (self.analyzer - sample) #pmat = linear_polarizer(angle) pmat = normal_polarizer((np.cos(angle), np.sin(angle))) #pmat = ray_polarizer((np.cos(angle),np.sin(angle)),epsv = self.epsv, epsa = self.epsa) for i, data in enumerate(tmp): if self.polarizer is not None: x = data[0] * c y = np.multiply(data[1], s, out=out) ffield = np.add( x, y, out=out) #numexpr.evaluate("x*c+y*s", out = out) else: ffield = data if self.analyzer is not None: #pfield = apply_jones_matrix(pmat, ffield, out = out) pfield = dotmf(pmat, ffield, out=out) else: pfield = ffield if i == 0: self.specter = field2specter(pfield) else: self.specter += field2specter(pfield) 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
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
def test_dotmf(self): out = linalg.dotmf(self.a,self.f) self.compare_results(out,[self.a, self.f])
def _transfer_ray_2x2_2(field, wavenumbers, in_layer, out_layer, dmat=None, 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 if in_layer is not None: d, epsv, epsa = in_layer alpha, fmat_in = alphaf(beta, phi, epsv, epsa, out=_out.get("afin")) if tmpdata is not None: _out["afin"] = alpha, fmat_in d, epsv, epsa = out_layer alpha, fmat = alphaf(beta, phi, epsv, epsa, out=_out.get("afout")) e = E_mat(fmat, mode=mode, copy=False) #2x2 E-only view of fmat # if refl is not None: # ein = E_mat(fmat_in, mode = mode * (-1)) #reverse direction # # if reflection == 0: # kd = wavenumbers * d # else: kd = wavenumbers * d / 2 p = phase_mat(alpha, kd[..., None, None], mode=mode, out=_out.get("p")) ei0 = inv(e, out=_out.get("ei0")) ei = ei0 if tmpdata is not None: _out["afout"] = alpha, fmat _out["ei0"] = ei _out["p"] = p for j in range(nsteps): #reflect only at the beginning if j == 0 and reflection != 0: #if we need to track reflections (multipass) if refl is not None: #ei,eri = Etri_mat(fmat_in, fmat, mode = mode, out = _out.get("eieri")) tmat, rmat = tr_mat(fmat_in, fmat, mode=mode, out=_out.get("eieri")) if tmpdata is not None: #_out["eieri"] = ei,eri _out["eieri"] = tmat, rmat trans = refl.copy() #refl = dotmf(eri, field, out = refl) refl = dotmf(rmat, field, out=refl) #field = dotmf(ei,field, out = out) field = dotmf(tmat, field, out=out) field = np.add(field, trans, out=field) if mode == -1 and bulk is not None: #tmp_field = dotmf(e,field) tmp_field = field e2h = E2H_mat(fmat, mode=mode) bulk[..., ::2, :, :] += tmp_field bulk[..., 1::2, :, :] += dotmf(e2h, tmp_field) field = dotmf(ei, field, out=field) if d != 0.: field = dotmf(dotmd(e, p), field, out=field) else: field = dotmf(e, field, out=field) out = field # rmat = dotmm(ein, eri, out = eri) # trans = refl.copy() # refl = dotmf(rmat, field, out = refl) # ei0 = inv(e) # field = dotmf(ei,field, out = out) # field = dotmf(e,field) + trans # if d != 0.: # field = dotmdmf(e,p,ei0,field, out = out) ei = ei0 else: ei = Eti_mat(fmat_in, fmat, mode=mode, out=_out.get("eti")) field = dotmdmf(e, p, ei, field, out=out) out = field if tmpdata is not None: _out["eti"] = ei ei = ei0 else: #no need to compute if d == 0!.. identity if d != 0.: field = dotmdmf(e, p, ei, field, out=out) out = field if dmat is not None: field = diffract(field, dmat, out=out) out = field #no need to compute if d == 0!.. identity if d != 0.: field = dotmdmf(e, p, ei, field, out=out) if mode == +1 and bulk is not None: e2h = E2H_mat(fmat, mode=mode) bulk[..., 1::2, :, :] += dotmf(e2h, field) bulk[..., ::2, :, :] += field return field, refl
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
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