def nufft2(field, fx, fy, size=None, sign=1, eps=10**(-12)): """ """ if np.__name__ == 'cupy': fx = np.asnumpy(fx).astype(np.float64) fy = np.asnumpy(fy).astype(np.float64) image = np.asnumpy(np.copy(field)).astype(np.complex128) else: image = np.copy(field).astype(np.complex128) if type(size) == type(None): result = finufft.nufft2d1(fx.flatten(), fy.flatten(), image.flatten(), image.shape, eps=eps, isign=sign) else: result = finufft.nufft2d1(fx.flatten(), fy.flatten(), image.flatten(), (size[0], size[1]), eps=eps, isign=sign) if np.__name__ == 'cupy': result = np.asarray(result) return result
def crop_center(field, size=None): """ Definition to crop the center of a field with 2Mx2N size. The outcome is a MxN array. Parameters ---------- field : ndarray Input field 2Mx2N array. Returns ---------- cropped : ndarray Cropped version of the input field. """ if type(size) == type(None): qx = int(np.ceil(field.shape[0]) / 4) qy = int(np.ceil(field.shape[1]) / 4) cropped = np.copy(field[qx:3 * qx, qy:3 * qy]) else: cx = int(np.ceil(field.shape[0] / 2)) cy = int(np.ceil(field.shape[1] / 2)) hx = int(np.ceil(size[0] / 2)) hy = int(np.ceil(size[1] / 2)) cropped = np.copy(field[cx - hx:cx + hx, cy - hy:cy + hy]) return cropped
def draw_a_ray(self, point0, point1, k=0.02, color=[255, 255, 255]): """ Definition to draw a ray. Parameters ---------- point0 : list List that contains X, Y, and Z start locations of a ray. point1 : list List that contains X, Y, and Z end locations of a ray. k : float Thickness of a ray. color : list List that contains red, green and blue color channel values (8 bit). """ import numpy as np_cpu point0 = np_cpu.reshape(np_cpu.array(point0), (3)) point1 = np_cpu.reshape(np_cpu.array(point1), (3)) if type(self.pnts) == type(None): a = 0 elif type(self.pnts) != type(None): a = np_cpu.asarray(self.pnts).shape[0] pnts = np_cpu.array([(point0[0], point0[1], point0[2]), (point0[0] + k, point0[1], point0[2]), (point0[0] + k, point0[1] + k, point0[2]), (point0[0], point0[1] + k, point0[2]), (point1[0], point1[1], point1[2]), (point1[0] + k, point1[1], point1[2]), (point1[0] + k, point1[1] + k, point1[2]), (point1[0], point1[1] + k, point1[2])], dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]) tris = np_cpu.array( [([0 + a, 3 + a, 1 + a], color[0], color[1], color[2]), ([1 + a, 3 + a, 2 + a], color[0], color[1], color[2]), ([0 + a, 4 + a, 7 + a], color[0], color[1], color[2]), ([0 + a, 7 + a, 3 + a], color[0], color[1], color[2]), ([4 + a, 5 + a, 6 + a], color[0], color[1], color[2]), ([4 + a, 6 + a, 7 + a], color[0], color[1], color[2]), ([5 + a, 1 + a, 2 + a], color[0], color[1], color[2]), ([5 + a, 2 + a, 6 + a], color[0], color[1], color[2]), ([2 + a, 3 + a, 6 + a], color[0], color[1], color[2]), ([3 + a, 7 + a, 6 + a], color[0], color[1], color[2]), ([0 + a, 1 + a, 5 + a], color[0], color[1], color[2]), ([0 + a, 5 + a, 4 + a], color[0], color[1], color[2])], dtype=[('vertex_indices', 'i4', (3, )), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')]) if type(self.pnts) != type(None): self.tris = np_cpu.concatenate([np.copy(self.tris), np.copy(tris)]) self.pnts = np_cpu.concatenate([np.copy(self.pnts), np.copy(pnts)]) else: self.tris = np_cpu.copy(tris) self.pnts = np_cpu.copy(pnts)
def propagate_a_ray(ray, distance): """ Definition to propagate a ray at a certain given distance. Parameters ---------- ray : ndarray A ray. distance : float Distance. Returns ---------- new_ray : ndarray Propagated ray. """ if len(ray.shape) == 2: ray = ray.reshape((1, 2, 3)) new_ray = np.copy(ray) new_ray[:, 0, 0] = distance * new_ray[:, 1, 0] + new_ray[:, 0, 0] new_ray[:, 0, 1] = distance * new_ray[:, 1, 1] + new_ray[:, 0, 1] new_ray[:, 0, 2] = distance * new_ray[:, 1, 2] + new_ray[:, 0, 2] if new_ray.shape[0] == 1: new_ray = new_ray.reshape((2, 3)) return new_ray
def gerchberg_saxton(field,n_iterations,distance,dx,wavelength,slm_range=6.28,propagation_type='IR Fresnel'): """ Definition to compute a hologram using an iterative method called Gerchberg-Saxton phase retrieval algorithm. For more on the method, see: Gerchberg, Ralph W. "A practical algorithm for the determination of phase from image and diffraction plane pictures." Optik 35 (1972): 237-246. Parameters ---------- field : np.complex Complex field (MxN). distance : float Propagation distance. dx : float Size of one single pixel in the field grid (in meters). wavelength : float Wavelength of the electric field. slm_range : float Typically this is equal to two pi. See odak.wave.adjust_phase_only_slm_range() for more. propagation_type : str Type of the propagation (IR Fresnel, TR Fresnel, Fraunhofer). Result --------- hologram : np.complex Calculated complex hologram. reconstruction : np.complex Calculated reconstruction using calculated hologram. """ k = wavenumber(wavelength) reconstruction = np.copy(field) for i in tqdm(range(n_iterations)): hologram = propagate_beam(reconstruction,k,-distance,dx,wavelength,propagation_type) hologram = produce_phase_only_slm_pattern(hologram,slm_range) reconstruction = propagate_beam(hologram,k,distance,dx,wavelength,propagation_type) reconstruction = set_amplitude(hologram,field) reconstruction = propagate_beam(hologram,k,distance,dx,wavelength,propagation_type) return hologram,reconstruction
def fraunhofer_equal_size_adjust(field,distance,dx,wavelength): """ A definition to match the physical size of the original field with the propagated field. Parameters ---------- field : np.complex Complex field (MxN). distance : float Propagation distance. dx : float Size of one single pixel in the field grid (in meters). wavelength : float Wavelength of the electric field. Returns ======= new_field : np.complex Final complex field (MxN). """ nv,nu = field.shape l1 = nu*dx l2 = wavelength*distance/dx m = l1/l2 px = int(m*nu) py = int(m*nv) nx = int(field.shape[0]/2-px/2) ny = int(field.shape[1]/2-py/2) new_field = np.copy(field[nx:nx+px,ny:ny+py]) return new_field
def nuifft2(field, fx, fy, size=None, sign=1, eps=10**(-12)): """ A definition to take 2D Adjoint Non-Uniform Fast Fourier Transform (NUFFT). Parameters ---------- field : ndarray Input field. fx : ndarray Frequencies along x axis. fy : ndarray Frequencies along y axis. size : list or ndarray Shape of the NUFFT calculated for an input field. sign : float Sign of the exponential used in NUFFT kernel. eps : float Accuracy of NUFFT. Returns ---------- result : ndarray NUFFT of the input field. """ if np.__name__ == 'cupy': fx = np.asnumpy(fx).astype(np.float64) fy = np.asnumpy(fy).astype(np.float64) image = np.asnumpy(np.copy(field)).astype(np.complex128) else: image = np.copy(field).astype(np.complex128) if type(size) == type(None): result = finufft.nufft2d1(fx.flatten(), fy.flatten(), image.flatten(), image.shape, eps=eps, isign=sign) else: result = finufft.nufft2d1(fx.flatten(), fy.flatten(), image.flatten(), (size[0], size[1]), eps=eps, isign=sign) if np.__name__ == 'cupy': result = np.asarray(result) return result
def nuifft2(field, fx, fy, sign=1, eps=10**(-12)): """ """ if np.__name__ == 'cupy': fx = np.asnumpy(fx).astype(np.float64) fy = np.asnumpy(fy).astype(np.float64) image = np.asnumpy(np.copy(field)).astype(np.complex128) else: image = np.copy(field).astype(np.complex128) result = finufft.nufft2d2(fx.flatten(), fy.flatten(), image, eps=eps, isign=sign) result = result.reshape(field.shape) if np.__name__ == 'cupy': result = np.asarray(result) return result
def get_field(self): """ A definition to return the field measured on the detector. Returns ---------- field : ndarray A copy of the field measured by the detector. """ return np.copy(self.field)
def save_image(fn, img, cmin=0, cmax=255): """ Definition to save a Numpy array as an image. Parameters ---------- fn : str Filename. img : ndarray A numpy array with NxMx3 or NxMx1 shapes. cmin : int Minimum value that will be interpreted as 0 level in the final image. cmax : int Maximum value that will be interpreted as 255 level in the final image. Returns ---------- bool : bool True if successful. """ input_img = np.copy(img).astype(np.float) colorflag = False if len(input_img.shape) == 3: if input_img.shape[2] > 1: input_img = input_img[:, :, 0:3] colorflag = True input_img[input_img < cmin] = cmin input_img[input_img > cmax] = cmax input_img /= cmax input_img *= 255 input_img = input_img.astype(np.uint8) if np.__name__ == 'cupy': input_img = np.asnumpy(input_img) if colorflag == True: result_img = Image.fromarray(input_img) elif colorflag == False: result_img = Image.fromarray(input_img).convert("L") result_img.save(fn) return True