def test_fspace_simple_attributes(): intv = odl.IntervalProd(0, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) assert fspace.domain == intv assert fspace.range == odl.RealNumbers() assert fspace_r.range == odl.RealNumbers() assert fspace_c.range == odl.ComplexNumbers()
def test_fourier_trafo_range(exponent, odl_floating_dtype): # Check if the range is initialized correctly. Encompasses the init test dtype = odl_floating_dtype # Testing R2C for real dtype, else C2C # 1D shape = 10 space_discr = odl.uniform_discr(0, 1, shape, exponent=exponent, impl='numpy', dtype=dtype) dft = FourierTransform(space_discr, halfcomplex=True, shift=True) assert dft.range.field == odl.ComplexNumbers() halfcomplex = True if is_real_dtype(dtype) else False assert dft.range.grid == reciprocal_grid(dft.domain.grid, halfcomplex=halfcomplex, shift=True) assert dft.range.exponent == conj_exponent(exponent) # 3D shape = (3, 4, 5) space_discr = odl.uniform_discr([0] * 3, [1] * 3, shape, exponent=exponent, impl='numpy', dtype=dtype) dft = FourierTransform(space_discr, halfcomplex=True, shift=True) assert dft.range.field == odl.ComplexNumbers() halfcomplex = True if is_real_dtype(dtype) else False assert dft.range.grid == reciprocal_grid(dft.domain.grid, halfcomplex=halfcomplex, shift=True) assert dft.range.exponent == conj_exponent(exponent) # shift must be True in the last axis if halfcomplex: with pytest.raises(ValueError): FourierTransform(space_discr, shift=(True, True, False)) if exponent != 2.0: with pytest.raises(NotImplementedError): dft.adjoint with pytest.raises(TypeError): FourierTransform(dft.domain.partition)
def test_init(exponent): # Validate that the different init patterns work and do not crash. space = odl.FunctionSpace(odl.IntervalProd(0, 1)) part = odl.uniform_partition_fromintv(space.domain, 10) rn = odl.rn(10, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent, interp='linear') # Normal discretization of unit interval with complex complex_space = odl.FunctionSpace(odl.IntervalProd(0, 1), field=odl.ComplexNumbers()) cn = odl.cn(10, exponent=exponent) odl.DiscreteLp(complex_space, part, cn, exponent=exponent) space = odl.FunctionSpace(odl.IntervalProd([0, 0], [1, 1])) part = odl.uniform_partition_fromintv(space.domain, (10, 10)) rn = odl.rn(100, exponent=exponent) odl.DiscreteLp(space, part, rn, exponent=exponent, interp=['nearest', 'linear']) # Real space should not work with complex with pytest.raises(ValueError): odl.DiscreteLp(space, part, cn) # Complex space should not work with reals with pytest.raises(ValueError): odl.DiscreteLp(complex_space, part, rn) # Wrong size of underlying space rn_wrong_size = odl.rn(20) with pytest.raises(ValueError): odl.DiscreteLp(space, part, rn_wrong_size)
def test_dspace_type_numpy(): # Plain function set -> Ntuples-like fset = odl.FunctionSet(odl.Interval(0, 1), odl.Strings(2)) assert dspace_type(fset, 'numpy') == odl.Ntuples, None assert dspace_type(fset, 'numpy', np.int) == odl.Ntuples # Real space rspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.RealNumbers()) assert dspace_type(rspc, 'numpy') == odl.Fn assert dspace_type(rspc, 'numpy', np.float32) == odl.Fn assert dspace_type(rspc, 'numpy', np.int) == odl.Fn with pytest.raises(TypeError): dspace_type(rspc, 'numpy', np.complex) with pytest.raises(TypeError): dspace_type(rspc, 'numpy', np.dtype('<U2')) # Complex space cspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) assert dspace_type(cspc, 'numpy') == odl.Fn assert dspace_type(cspc, 'numpy', np.complex64) == odl.Fn with pytest.raises(TypeError): dspace_type(cspc, 'numpy', np.float) with pytest.raises(TypeError): assert dspace_type(cspc, 'numpy', np.int) with pytest.raises(TypeError): dspace_type(cspc, 'numpy', np.dtype('<U2'))
def test_nearest_interpolation_1d_complex(fn_impl): intv = odl.IntervalProd(0, 1) part = odl.uniform_partition_fromintv(intv, 5, nodes_on_bdry=False) # Coordinate vectors are: # [0.1, 0.3, 0.5, 0.7, 0.9] space = odl.FunctionSpace(intv, field=odl.ComplexNumbers()) dspace = odl.cn(part.size) interp_op = NearestInterpolation(space, part, dspace) function = interp_op([0 + 1j, 1 + 2j, 2 + 3j, 3 + 4j, 4 + 5j]) # Evaluate at single point val = function(0.35) # closest to index 1 -> 1 + 2j assert val == 1.0 + 2.0j # Input array, with and without output array pts = np.array([0.4, 0.0, 0.65, 0.95]) true_arr = [1 + 2j, 0 + 1j, 3 + 4j, 4 + 5j] assert all_equal(function(pts), true_arr) # Should also work with a (1, N) array pts = pts[None, :] assert all_equal(function(pts), true_arr) out = np.empty(4, dtype='complex128') function(pts, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array # Same as array for 1d mg = sparse_meshgrid([0.4, 0.0, 0.65, 0.95]) true_mg = [1 + 2j, 0 + 1j, 3 + 4j, 4 + 5j] assert all_equal(function(mg), true_mg) function(mg, out=out) assert all_equal(out, true_mg)
def test_dspace_type_cuda(): # Plain function set -> Ntuples-like fset = odl.FunctionSet(odl.Interval(0, 1), odl.Strings(2)) assert dspace_type(fset, 'cuda') == odl.CudaNtuples assert dspace_type(fset, 'cuda', np.int) == odl.CudaNtuples # Real space rspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.RealNumbers()) assert dspace_type(rspc, 'cuda') == odl.CudaFn assert dspace_type(rspc, 'cuda', np.float64) == odl.CudaFn assert dspace_type(rspc, 'cuda', np.int) == odl.CudaFn with pytest.raises(TypeError): dspace_type(rspc, 'cuda', np.complex) with pytest.raises(TypeError): dspace_type(rspc, 'cuda', np.dtype('<U2')) # Complex space (not implemented) cspc = odl.FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) with pytest.raises(NotImplementedError): dspace_type(cspc, 'cuda') with pytest.raises(NotImplementedError): dspace_type(cspc, 'cuda', np.complex64) with pytest.raises(TypeError): dspace_type(cspc, 'cuda', np.float) with pytest.raises(TypeError): assert dspace_type(cspc, 'cuda', np.int)
def test_fspace_vector_real_imag(): rect, _, mg = _standard_setup_2d() cspace = FunctionSpace(rect, field=odl.ComplexNumbers()) f = cspace.element(cfunc_2d_vec_oop) # real / imag on complex functions assert all_equal(f.real(mg), cfunc_2d_vec_oop(mg).real) assert all_equal(f.imag(mg), cfunc_2d_vec_oop(mg).imag) out_mg = np.empty((2, 3)) f.real(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).real) f.imag(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).imag) # real / imag on real functions, should be the function itself / zero rspace = FunctionSpace(rect) f = rspace.element(func_2d_vec_oop) assert all_equal(f.real(mg), f(mg)) assert all_equal(f.imag(mg), rspace.zero()(mg)) # Complex conjugate f = cspace.element(cfunc_2d_vec_oop) fbar = f.conj() assert all_equal(fbar(mg), cfunc_2d_vec_oop(mg).conj()) out_mg = np.empty((2, 3), dtype='complex128') fbar(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).conj())
def test_fspace_vector_init(): # 1d, real intv = odl.IntervalProd(0, 1) fspace = FunctionSpace(intv) fspace.element(func_1d_oop) fspace.element(func_1d_oop, vectorized=False) fspace.element(func_1d_oop, vectorized=True) fspace.element(func_1d_ip, vectorized=True) fspace.element(func_1d_dual, vectorized=True) # 2d, real rect = odl.IntervalProd([0, 0], [1, 2]) fspace = FunctionSpace(rect) fspace.element(func_2d_novec, vectorized=False) fspace.element(func_2d_vec_oop) fspace.element(func_2d_vec_oop, vectorized=True) fspace.element(func_2d_vec_ip, vectorized=True) fspace.element(func_2d_vec_dual, vectorized=True) # 2d, complex fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) fspace.element(cfunc_2d_novec, vectorized=False) fspace.element(cfunc_2d_vec_oop) fspace.element(cfunc_2d_vec_oop, vectorized=True) fspace.element(cfunc_2d_vec_ip, vectorized=True) fspace.element(cfunc_2d_vec_dual, vectorized=True)
def test_uniform_discr_init_complex(tspace_impl): """Test initialization and basic properties with uniform_discr, complex.""" if tspace_impl != 'numpy': pytest.xfail(reason='complex dtypes not supported') discr = odl.uniform_discr(0, 1, 10, dtype='complex', impl=tspace_impl) assert discr.is_complex assert discr.dtype == discr.tspace.default_dtype(odl.ComplexNumbers())
def test_fspace_vector_eval_complex(): rect, points, mg = _standard_setup_2d() fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) f_novec = fspace.element(cfunc_2d_novec, vectorized=False) f_vec_oop = fspace.element(cfunc_2d_vec_oop, vectorized=True) f_vec_ip = fspace.element(cfunc_2d_vec_ip, vectorized=True) f_vec_dual = fspace.element(cfunc_2d_vec_dual, vectorized=True) true_arr = cfunc_2d_vec_oop(points) true_mg = cfunc_2d_vec_oop(mg) # Out-of-place assert f_novec([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert f_vec_oop([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_oop(points), true_arr) assert all_equal(f_vec_oop(mg), true_mg) # In-place standard implementation out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_oop(points, out=out_arr) f_vec_oop(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) with pytest.raises(TypeError): # ValueError: invalid vectorized input f_vec_oop(points[0]) # In-place-only out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_ip(points, out=out_arr) f_vec_ip(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # Standard out-of-place evaluation assert f_vec_ip([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_ip(points), true_arr) assert all_equal(f_vec_ip(mg), true_mg) # Dual use assert f_vec_dual([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_dual(points), true_arr) assert all_equal(f_vec_dual(mg), true_mg) out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_dual(points, out=out_arr) f_vec_dual(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg)
def test_fspace_init(): intv = odl.IntervalProd(0, 1) FunctionSpace(intv) FunctionSpace(intv, field=odl.RealNumbers()) FunctionSpace(intv, field=odl.ComplexNumbers()) rect = odl.IntervalProd([0, 0], [1, 2]) FunctionSpace(rect) FunctionSpace(rect, field=odl.RealNumbers()) FunctionSpace(rect, field=odl.ComplexNumbers()) cube = odl.IntervalProd([0, 0, 0], [1, 2, 3]) FunctionSpace(cube) FunctionSpace(cube, field=odl.RealNumbers()) FunctionSpace(cube, field=odl.ComplexNumbers()) ndbox = odl.IntervalProd([0] * 10, np.arange(1, 11)) FunctionSpace(ndbox) FunctionSpace(ndbox, field=odl.RealNumbers()) FunctionSpace(ndbox, field=odl.ComplexNumbers())
def test_fspace_equality(): intv = odl.Interval(0, 1) intv2 = odl.Interval(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) fspace_intv2 = FunctionSpace(intv2) assert fspace == fspace_r assert fspace != fspace_c assert fspace != fspace_intv2
def test_equals(): """Test equality check and hash.""" intv = odl.IntervalProd(0, 1) intv2 = odl.IntervalProd(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) fspace_intv2 = FunctionSpace(intv2) _test_eq(fspace, fspace) _test_eq(fspace, fspace_r) _test_eq(fspace_c, fspace_c) _test_neq(fspace, fspace_c) _test_neq(fspace, fspace_intv2)
def test_factory(exponent): discr = odl.uniform_discr(0, 1, 10, impl='numpy', exponent=exponent) assert isinstance(discr.dspace, odl.Fn) assert discr.is_rn assert discr.dspace.exponent == exponent assert discr.dtype == odl.Fn.default_dtype(odl.RealNumbers()) # Complex discr = odl.uniform_discr(0, 1, 10, dtype='complex', impl='numpy', exponent=exponent) assert isinstance(discr.dspace, odl.Fn) assert discr.is_cn assert discr.dspace.exponent == exponent assert discr.dtype == odl.Fn.default_dtype(odl.ComplexNumbers())
def test_fspace_attributes(): """Check attribute access and correct values.""" intv = odl.IntervalProd(0, 1) # Scalar-valued function spaces fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, out_dtype=float) fspace_c = FunctionSpace(intv, out_dtype=complex) fspace_s = FunctionSpace(intv, out_dtype='U1') scalar_spaces = (fspace, fspace_r, fspace_c, fspace_s) assert fspace.domain == intv assert fspace.field == odl.RealNumbers() assert fspace_r.field == odl.RealNumbers() assert fspace_c.field == odl.ComplexNumbers() assert fspace_s.field is None assert fspace.out_dtype == float assert fspace_r.out_dtype == float assert fspace_r.real_out_dtype == float assert fspace_r.complex_out_dtype == complex assert fspace_c.out_dtype == complex assert fspace_c.real_out_dtype == float assert fspace_c.complex_out_dtype == complex assert fspace_s.out_dtype == np.dtype('U1') assert fspace.is_real assert not fspace.is_complex assert fspace_r.is_real assert not fspace_r.is_complex assert fspace_c.is_complex assert not fspace_c.is_real with pytest.raises(AttributeError): fspace_s.real_out_dtype with pytest.raises(AttributeError): fspace_s.complex_out_dtype assert all(spc.scalar_out_dtype == spc.out_dtype for spc in scalar_spaces) assert all(spc.out_shape == () for spc in scalar_spaces) assert all(not spc.tensor_valued for spc in scalar_spaces) # Vector-valued function space fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) assert fspace_vec.field == odl.RealNumbers() assert fspace_vec.out_dtype == np.dtype((float, (2, ))) assert fspace_vec.scalar_out_dtype == float assert fspace_vec.out_shape == (2, ) assert fspace_vec.tensor_valued
def test_fspace_one(): rect, points, mg = _standard_setup_2d() # real fspace = FunctionSpace(rect) one_vec = fspace.one() assert one_vec([0.5, 1.5]) == 1.0 assert all_equal(one_vec(points), np.ones(5, dtype=float)) assert all_equal(one_vec(mg), np.ones((2, 3), dtype=float)) # complex fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) one_vec = fspace.one() assert one_vec([0.5, 1.5]) == 1.0 + 1j * 0.0 assert all_equal(one_vec(points), np.ones(5, dtype=complex)) assert all_equal(one_vec(mg), np.ones((2, 3), dtype=complex))
def test_fspace_astype(): rspace = FunctionSpace(odl.IntervalProd(0, 1)) cspace = FunctionSpace(odl.IntervalProd(0, 1), field=odl.ComplexNumbers()) rspace_s = FunctionSpace(odl.IntervalProd(0, 1), out_dtype='float32') cspace_s = FunctionSpace(odl.IntervalProd(0, 1), out_dtype='complex64') assert rspace.astype('complex64') == cspace_s assert rspace.astype('complex128') == cspace assert rspace.astype('complex128') is rspace.complex_space assert rspace.astype('float32') == rspace_s assert rspace.astype('float64') is rspace.real_space assert cspace.astype('float32') == rspace_s assert cspace.astype('float64') == rspace assert cspace.astype('float64') is cspace.real_space assert cspace.astype('complex64') == cspace_s assert cspace.astype('complex128') is cspace.complex_space
def test_fourier_trafo_scaling(): # Test if the FT scales correctly # Characteristic function of [0, 1], its Fourier transform is # given by exp(-1j * y / 2) * sinc(y/2) def char_interval(x): return (x >= 0) & (x <= 1) def char_interval_ft(x): return np.exp(-1j * x / 2) * sinc(x / 2) / np.sqrt(2 * np.pi) fspace = odl.FunctionSpace(odl.IntervalProd(-2, 2), field=odl.ComplexNumbers()) discr = odl.uniform_discr_fromspace(fspace, 40, impl='numpy') dft = FourierTransform(discr) for factor in (2, 1j, -2.5j, 1 - 4j): func_true_ft = factor * dft.range.element(char_interval_ft) func_dft = dft(factor * fspace.element(char_interval)) assert (func_dft - func_true_ft).norm() < 1e-6