def test_holo_reconstruction(lt_ctx, backend): if backend == 'cupy': d = detect() cudas = detect()['cudas'] if not d['cudas'] or not d['has_cupy']: pytest.skip("No CUDA device or no CuPy, skipping CuPy test") # Prepare image parameters and mesh nx, ny = (5, 7) sx, sy = (64, 64) slice_crop = (slice(None), slice(None), slice(sx // 4, sx // 4 * 3), slice(sy // 4, sy // 4 * 3)) lnx = np.arange(nx) lny = np.arange(ny) lsx = np.arange(sx) lsy = np.arange(sy) mnx, mny, msx, msy = np.meshgrid(lnx, lny, lsx, lsy) # Prepare phase image phase_ref = np.pi * msx * (mnx.max() - mnx) * mny / sx**2 \ + np.pi * msy * mnx * (mny.max() - mny) / sy**2 # Generate holograms holo = np.zeros_like(phase_ref) ref = np.zeros_like(phase_ref) for i in range(nx): for j in range(ny): holo[j, i, :, :] = hologram_frame(np.ones((sx, sy)), phase_ref[j, i, :, :]) ref[j, i, :, :] = hologram_frame(np.ones((sx, sy)), np.zeros((sx, sy))) # Prepare LT datasets and do reconstruction dataset_holo = MemoryDataSet(data=holo, tileshape=(ny, sx, sy), num_partitions=2, sig_dims=2) dataset_ref = MemoryDataSet(data=ref, tileshape=(ny, sx, sy), num_partitions=1, sig_dims=2) sb_position = [11, 6] sb_size = 6.26498204 holo_job = HoloReconstructUDF(out_shape=(sx, sy), sb_position=sb_position, sb_size=sb_size) try: if backend == 'cupy': set_use_cuda(cudas[0]) w_holo = lt_ctx.run_udf(dataset=dataset_holo, udf=holo_job)['wave'].data w_ref = lt_ctx.run_udf(dataset=dataset_ref, udf=holo_job)['wave'].data finally: set_use_cpu(0) w = w_holo / w_ref phase = np.angle(w) assert np.allclose(phase_ref[slice_crop], phase[slice_crop], rtol=0.12)
def test_holo_reconstruction(lt_ctx): # Prepare image parameters and mesh nx, ny = (5, 7) sx, sy = (64, 64) slice_crop = (slice(None), slice(None), slice(sx // 4, sx // 4 * 3), slice(sy // 4, sy // 4 * 3)) lnx = np.arange(nx) lny = np.arange(ny) lsx = np.arange(sx) lsy = np.arange(sy) mnx, mny, msx, msy = np.meshgrid(lnx, lny, lsx, lsy) # Prepare phase image phase_ref = np.pi * msx * (mnx.max() - mnx) * mny / sx**2 \ + np.pi * msy * mnx * (mny.max() - mny) / sy**2 # Generate holograms holo = np.zeros_like(phase_ref) ref = np.zeros_like(phase_ref) for i in range(nx): for j in range(ny): holo[j, i, :, :] = hologram_frame(np.ones((sx, sy)), phase_ref[j, i, :, :]) ref[j, i, :, :] = hologram_frame(np.ones((sx, sy)), np.zeros((sx, sy))) # Prepare LT datasets and do reconstruction dataset_holo = MemoryDataSet(data=holo, tileshape=(ny, sx, sy), num_partitions=2, sig_dims=2) dataset_ref = MemoryDataSet(data=ref, tileshape=(ny, sx, sy), num_partitions=1, sig_dims=2) sb_position = [11, 6] sb_size = 6.26498204 holo_job = HoloReconstructUDF(out_shape=(sx, sy), sb_position=sb_position, sb_size=sb_size) w_holo = lt_ctx.run_udf(dataset=dataset_holo, udf=holo_job)['wave'].data w_ref = lt_ctx.run_udf(dataset=dataset_ref, udf=holo_job)['wave'].data w = w_holo / w_ref phase = np.angle(w) assert np.allclose(phase_ref[slice_crop], phase[slice_crop], rtol=0.12)
def test_holo_frame_asserts(): # test asserts: with pytest.raises(ValueError): hologram_frame(np.ones((7, 5)), np.zeros((5, 7))) with pytest.raises(ValueError): hologram_frame(np.ones((5, 7)), np.zeros((5, 7)), gaussian_noise='a lot') with pytest.raises(ValueError): hologram_frame(np.ones((5, 7)), np.zeros((5, 7)), poisson_noise='a bit')
def test_hologram_frame(counts, sampling, visibility, f_angle, gauss, poisson, rtol1, rtol2): sx, sy = (32, 64) x, y = np.meshgrid(np.arange(sx), np.arange(sy)) kwargs = {} if counts: kwargs['counts'] = counts else: counts = 1000. if sampling: kwargs['sampling'] = sampling else: sampling = 5. if visibility: kwargs['visibility'] = visibility else: visibility = 1. if f_angle: kwargs['f_angle'] = f_angle else: f_angle = 30. if gauss: kwargs['gaussian_noise'] = gauss if poisson: kwargs['poisson_noise'] = poisson amp = 1 - np.random.randn(sy, sx) * 0.01 phase = np.random.random() * x / sx + np.random.random() * y / sy holo_test = hologram_frame(amp, phase, **kwargs) f_angle = f_angle / 180. * np.pi holo = counts / 2 * (1. + amp ** 2 + 2. * amp * visibility * np.cos(2. * np.pi * y / sampling * np.cos(f_angle) + 2. * np.pi * x / sampling * np.sin(f_angle) - phase)) if poisson: noise_scale = poisson * counts holo = noise_scale * np.random.poisson(holo / noise_scale) if gauss: holo = gaussian_filter(holo, gauss) assert np.allclose(holo, holo_test, rtol=rtol1) # test derived parameters: # test if mean value equals to counts assert np.isclose(holo_test.mean(), counts, rtol=5e-3) # test if calculated contrast is equals to teh input contrast = lambda a: (a.max(1).mean() - a.min(1).mean()) \ / (a.min(1).mean() + a.max(1).mean()) assert np.isclose(contrast(holo_test), visibility, rtol=rtol2) # test if fringe spacing equals to the input holo_fft = np.abs(np.fft.rfft2(holo_test[:sx, :sx])) holo_fft[:1, :1] = 0. holo_max = np.unravel_index(holo_fft.argmax(), holo_fft.shape) holo_max = np.hypot(holo_max[0], holo_max[1]) sampling_test = sx / holo_max error_sampling = sampling_test * (1. / holo_max) assert np.isclose(sampling_test, sampling, atol=error_sampling)