def __init__(self, input_tensor, output_tensor, linear=False, sess=None): self.input_tensor = input_tensor self.output_tensor = output_tensor domain = odl.tensor_space(input_tensor.shape.as_list(), dtype=input_tensor.dtype.as_numpy_dtype) range = odl.tensor_space(output_tensor.shape.as_list(), dtype=output_tensor.dtype.as_numpy_dtype) self.dx = tf.placeholder(input_tensor.dtype, shape=input_tensor.shape) self.dy = tf.placeholder(output_tensor.dtype, shape=output_tensor.shape) adjoint_of_derivative_tensor = tf.gradients( self.output_tensor, [self.input_tensor], [self.dy])[0] self.adjoint_of_derivative_tensor = (range.weighting.const * adjoint_of_derivative_tensor) # Since tensorflow does not support forward differentiation, use trick # that adjoint of the derivative of adjoint of the derivative is simply # the derivative. derivative_tensor = tf.gradients( adjoint_of_derivative_tensor, [self.dy], [self.dx])[0] self.derivative_tensor = (range.weighting.const * derivative_tensor) if sess is None: self.sess = tf.get_default_session() else: self.sess = sess super(TensorflowOperator, self).__init__(domain, range, linear=linear)
def test_nearest_interpolation_2d_string(): """Test nearest neighbor interpolation in 2d with string values.""" rect = odl.IntervalProd([0, 0], [1, 1]) part = odl.uniform_partition_fromintv(rect, [4, 2], nodes_on_bdry=False) # Coordinate vectors are: # [0.125, 0.375, 0.625, 0.875], [0.25, 0.75] fspace = odl.FunctionSpace(rect, out_dtype='U1') tspace = odl.tensor_space(part.shape, dtype='U1') interp_op = NearestInterpolation(fspace, part, tspace) values = np.array([c for c in 'mystring']).reshape(tspace.shape) function = interp_op(values) # Evaluate at single point val = function([0.3, 0.6]) # closest to index (1, 1) -> 3 assert val == 't' # Input array, with and without output array pts = np.array([[0.3, 0.6], [1.0, 1.0]]) true_arr = ['t', 'g'] assert all_equal(function(pts.T), true_arr) out = np.empty(2, dtype='U1') function(pts.T, out=out) assert all_equal(out, true_arr) # Input meshgrid, with and without output array mg = sparse_meshgrid([0.3, 1.0], [0.4, 1.0]) # Indices: (1, 3) x (0, 1) true_mg = [['s', 't'], ['n', 'g']] assert all_equal(function(mg), true_mg) out = np.empty((2, 2), dtype='U1') function(mg, out=out) assert all_equal(out, true_mg) assert repr(interp_op) != ''
def test_matrix_op_adjoint(matrix): """Test if the adjoint of matrix operators is correct.""" dense_matrix = matrix sparse_matrix = scipy.sparse.coo_matrix(dense_matrix) tol = 2 * matrix.size * np.finfo(matrix.dtype).resolution # Default 1d case dmat_op = MatrixOperator(dense_matrix) smat_op = MatrixOperator(sparse_matrix) x = noise_element(dmat_op.domain) y = noise_element(dmat_op.range) inner_ran = dmat_op(x).inner(y) inner_dom = x.inner(dmat_op.adjoint(y)) assert inner_ran == pytest.approx(inner_dom, rel=tol, abs=tol) inner_ran = smat_op(x).inner(y) inner_dom = x.inner(smat_op.adjoint(y)) assert inner_ran == pytest.approx(inner_dom, rel=tol, abs=tol) # Multi-dimensional case domain = odl.tensor_space((2, 2, 4), matrix.dtype) mat_op = MatrixOperator(dense_matrix, domain, axis=2) x = noise_element(mat_op.domain) y = noise_element(mat_op.range) inner_ran = mat_op(x).inner(y) inner_dom = x.inner(mat_op.adjoint(y)) assert inner_ran == pytest.approx(inner_dom, rel=tol, abs=tol)
def test_matrix_op_inverse(): """Test if the inverse of matrix operators is correct.""" dense_matrix = np.ones((3, 3)) + 4 * np.eye(3) # invertible sparse_matrix = scipy.sparse.coo_matrix(dense_matrix) # Default 1d case dmat_op = MatrixOperator(dense_matrix) smat_op = MatrixOperator(sparse_matrix) x = noise_element(dmat_op.domain) md_x = dmat_op(x) mdinv_md_x = dmat_op.inverse(md_x) assert all_almost_equal(x, mdinv_md_x) ms_x = smat_op(x) msinv_ms_x = smat_op.inverse(ms_x) assert all_almost_equal(x, msinv_ms_x) # Multi-dimensional case domain = odl.tensor_space((2, 2, 3), dense_matrix.dtype) mat_op = MatrixOperator(dense_matrix, domain, axis=2) x = noise_element(mat_op.domain) m_x = mat_op(x) minv_m_x = mat_op.inverse(m_x) assert all_almost_equal(x, minv_m_x)
def false_structures_mask(foreground, smoothness_factor=None): """Return mask emphasizing areas outside ``foreground``. Parameters ---------- foreground : `Tensor` or `array-like` The region that should be de-emphasized. If not a `Tensor`, an unweighted tensor space will be assumed. ground_truth : `array-like` Reference to which ``data`` should be compared. foreground : `FnBaseVector` The region that should be de-emphasized. smoothness_factor : float, optional Positive real number. Higher value gives smoother transition between foreground and its complement. Returns ------- result : `Tensor` or `numpy.ndarray` Euclidean distances of elements in ``foreground``. The return value is a `Tensor` if ``foreground`` is one, too, otherwise a NumPy array. Examples -------- >>> space = odl.uniform_discr(0, 1, 5) >>> foreground = space.element([0, 0, 1.0, 0, 0]) >>> mask = false_structures_mask(foreground) >>> np.asarray(mask) array([ 0.4, 0.2, 0. , 0.2, 0.4]) Raises ------ ValueError If foreground is all zero or all one, or contains values not in {0, 1}. Notes ----- This helper function computes the Euclidean distance transform from each point in ``foreground.space`` to ``foreground``. The weighting gives higher values to structures outside the foreground as defined by the mask. """ try: space = foreground.space has_space = True except AttributeError: has_space = False foreground = np.asarray(foreground) space = odl.tensor_space(foreground.shape, foreground.dtype) foreground = space.element(foreground) from scipy.ndimage.morphology import distance_transform_edt unique = np.unique(foreground) if not np.array_equiv(unique, [0., 1.]): raise ValueError('`foreground` is not a binary mask or has ' 'either only true or only false values {!r}' ''.format(unique)) result = distance_transform_edt(1.0 - foreground, sampling=getattr(space, 'cell_sides', 1.0)) if has_space: return space.element(result) else: return result
folder_out += '_noise_{}'.format(stddev) folder_out += '_NonNeg_{}'.format(NonNeg) folder_out += '_MS_coord' if not os.path.exists(folder_out): os.makedirs(folder_out) # Target space gt, sinfo = np.load('{}/{}.npy'.format(data_folder, data_fname)) simage = sinfo.shape complex_space = odl.uniform_discr([-1, -1], [1, 1], simage, dtype='complex', interp='linear') X = complex_space.real_space ** 2 V = X[0].tangent_bundle Yaff = odl.tensor_space(6) Z = odl.ProductSpace(X, Yaff) J = ops.Complex2Real(complex_space) M = ops.Magnitude(X) # Ground truth image phase = complex_space.element( lambda x: np.exp(1j * .8 * (np.sin(3 * x[0] ** 2) + np.cos(5 * x[1] ** 3)))) gt = J(complex_space.element(gt * phase)) sinfo = complex_space.real_space.element(sinfo) mask_bdr = np.zeros(sinfo.shape) mask_bdr[25:-24,25:-24] = 1
def test_matrix_op_init(matrix): """Test initialization and properties of matrix operators.""" dense_matrix = matrix sparse_matrix = scipy.sparse.coo_matrix(dense_matrix) # Just check if the code runs MatrixOperator(dense_matrix) MatrixOperator(sparse_matrix) # Test default domain and range mat_op = MatrixOperator(dense_matrix) assert mat_op.domain == odl.tensor_space(4, matrix.dtype) assert mat_op.range == odl.tensor_space(3, matrix.dtype) assert np.all(mat_op.matrix == dense_matrix) sparse_matrix = scipy.sparse.coo_matrix(dense_matrix) mat_op = MatrixOperator(sparse_matrix) assert mat_op.domain == odl.tensor_space(4, matrix.dtype) assert mat_op.range == odl.tensor_space(3, matrix.dtype) assert (mat_op.matrix != sparse_matrix).getnnz() == 0 # Explicit domain and range dom = odl.tensor_space(4, matrix.dtype) ran = odl.tensor_space(3, matrix.dtype) mat_op = MatrixOperator(dense_matrix, domain=dom, range=ran) assert mat_op.domain == dom assert mat_op.range == ran mat_op = MatrixOperator(sparse_matrix, domain=dom, range=ran) assert mat_op.domain == dom assert mat_op.range == ran # Bad 1d sizes with pytest.raises(ValueError): MatrixOperator(dense_matrix, domain=odl.cn(4), range=odl.cn(4)) with pytest.raises(ValueError): MatrixOperator(dense_matrix, range=odl.cn(4)) # Invalid range dtype with pytest.raises(ValueError): MatrixOperator(dense_matrix.astype(complex), range=odl.rn(4)) # Data type promotion # real space, complex matrix -> complex space dom = odl.rn(4) mat_op = MatrixOperator(dense_matrix.astype(complex), domain=dom) assert mat_op.domain == dom assert mat_op.range == odl.cn(3) # complex space, real matrix -> complex space dom = odl.cn(4) mat_op = MatrixOperator(dense_matrix.real, domain=dom) assert mat_op.domain == dom assert mat_op.range == odl.cn(3) # Multi-dimensional spaces dom = odl.tensor_space((6, 5, 4), matrix.dtype) ran = odl.tensor_space((6, 5, 3), matrix.dtype) mat_op = MatrixOperator(dense_matrix, domain=dom, axis=2) assert mat_op.range == ran mat_op = MatrixOperator(dense_matrix, domain=dom, range=ran, axis=2) assert mat_op.range == ran with pytest.raises(ValueError): bad_dom = odl.tensor_space((6, 6, 6), matrix.dtype) # wrong shape MatrixOperator(dense_matrix, domain=bad_dom) with pytest.raises(ValueError): dom = odl.tensor_space((6, 5, 4), matrix.dtype) bad_ran = odl.tensor_space((6, 6, 6), matrix.dtype) # wrong shape MatrixOperator(dense_matrix, domain=dom, range=bad_ran) with pytest.raises(ValueError): MatrixOperator(dense_matrix, domain=dom, axis=1) with pytest.raises(ValueError): MatrixOperator(dense_matrix, domain=dom, axis=0) with pytest.raises(ValueError): bad_ran = odl.tensor_space((6, 3, 4), matrix.dtype) MatrixOperator(dense_matrix, domain=dom, range=bad_ran, axis=2) with pytest.raises(ValueError): bad_dom_for_sparse = odl.rn((6, 5, 4)) MatrixOperator(sparse_matrix, domain=bad_dom_for_sparse, axis=2) # Init with uniform_discr space (subclass of TensorSpace) dom = odl.uniform_discr(0, 1, 4, dtype=dense_matrix.dtype) ran = odl.uniform_discr(0, 1, 3, dtype=dense_matrix.dtype) MatrixOperator(dense_matrix, domain=dom, range=ran) # Make sure this runs and returns something string-like assert str(mat_op) > '' assert repr(mat_op) > ''
def __init__(self, input_tensor, output_tensor, domain=None, range=None, linear=False, sess=None): """Wrap Tensorflow layers in ODL operator. Parameters ---------- input_tensor : `tf.Tensor` Input to the tensorflow graph (values will be fed to this). output_tensor : `tf.Tensor` Output node from the graph. domain : `TensorSpace`, optional Domain of the wrapping operator. Default: `tensor_space` with same shape and dtype as ``input_tensor``. range : `TensorSpace`, optional Range of the wrapping operator. Default: `tensor_space` with same shape and dtype as ``output_tensor``. linear : bool, optional If the created operator should be linear sess : `tf.Session`, optional Session to evaluate the graph in. Default: `tf.get_default_session` Notes ----- Both `Operator.derivative` and `Operator.adjoint` are implemented using automatic differentiation in tensorflow. """ self.input_tensor = input_tensor self.output_tensor = output_tensor if domain is None: domain = odl.tensor_space(input_tensor.shape.as_list(), dtype=input_tensor.dtype.as_numpy_dtype) if range is None: range = odl.tensor_space(output_tensor.shape.as_list(), dtype=output_tensor.dtype.as_numpy_dtype) # TODO: replace with #1177 self.adjoint_weight = domain.weighting.const / range.weighting.const self.dx = tf.placeholder(input_tensor.dtype, shape=input_tensor.shape) self.dy = tf.placeholder(output_tensor.dtype, shape=output_tensor.shape) adjoint_of_derivative_tensor = tf.gradients( self.output_tensor, [self.input_tensor], [self.dy])[0] self.adjoint_of_derivative_tensor = (range.weighting.const * adjoint_of_derivative_tensor) # Since tensorflow does not support forward differentiation, use trick # that adjoint of the derivative of adjoint of the derivative is simply # the derivative. derivative_tensor = tf.gradients( adjoint_of_derivative_tensor, [self.dy], [self.dx])[0] self.derivative_tensor = (range.weighting.const * derivative_tensor) if sess is None: self.sess = tf.get_default_session() else: self.sess = sess super(TensorflowOperator, self).__init__(domain, range, linear=linear)