def transl_op_fixed_vf(self, disp):

        deform_op = defm.LinDeformFixedDispAffine(self.embedding(disp), disp)

        if isinstance(self.image_space, odl.ProductSpace):
            deform_op = odl.DiagonalOperator(deform_op, len(self.image_space))

        return deform_op
def gradient(space,
             sinfo=None,
             mode=None,
             gamma=1,
             eta=1e-2,
             show_sinfo=False,
             prefix=None):

    grad = odl.Gradient(space, method='forward', pad_mode='symmetric')

    if sinfo is not None:
        if mode == 'direction':
            norm = odl.PointwiseNorm(grad.range)
            grad_sinfo = grad(sinfo)
            ngrad_sinfo = norm(grad_sinfo)

            for i in range(len(grad_sinfo)):
                grad_sinfo[i] /= ngrad_sinfo.ufuncs.max()

            ngrad_sinfo = norm(grad_sinfo)
            ngrad_sinfo_eta = np.sqrt(ngrad_sinfo**2 + eta**2)

            xi = grad.range.element([g / ngrad_sinfo_eta
                                     for g in grad_sinfo])  # UGLY

            Id = odl.operator.IdentityOperator(grad.range)
            xiT = odl.PointwiseInner(grad.range, xi)
            xixiT = odl.BroadcastOperator(*[x * xiT for x in xi])

            grad = (Id - gamma * xixiT) * grad

            if show_sinfo:
                misc.save_image(ngrad_sinfo, prefix + '_sinfo_norm')
                misc.save_vfield(xi.asarray(), filename=prefix + '_sinfo_xi')
                misc.save_vfield_cmap(filename=prefix + '_sinfo_xi_cmap')

        elif mode == 'location':
            norm = odl.PointwiseNorm(grad.range)
            ngrad_sinfo = norm(grad(sinfo))
            ngrad_sinfo /= ngrad_sinfo.ufuncs.max()

            w = eta / np.sqrt(ngrad_sinfo**2 + eta**2)
            grad = odl.DiagonalOperator(odl.MultiplyOperator(w), 2) * grad

            if show_sinfo:
                misc.save_image(ngrad_sinfo, prefix + '_sinfo_norm')
                misc.save_image(w, prefix + '_w')

        else:
            grad = None

    return grad
Пример #3
0
                                               detector_partition,
                                               axis=[1, 0, 0])

# Ray transform (= forward projection). We use ASTRA CUDA backend.
ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')

# Create phantom
ellipses = odl.phantom.shepp_logan_ellipses(ndim, modified=True)[::4]

domain = odl.ProductSpace(space, len(ellipses))
phantom = domain.element(
    [odl.phantom.ellipse_phantom(space, [e]) for e in ellipses])
phantom = phantom.ufunc.absolute()
phantom.show('phantom', indices=np.s_[:])

diagop = odl.DiagonalOperator(ray_trafo, domain.size)
redop = odl.ReductionOperator(ray_trafo, domain.size)

# Assemble all operators
data = diagop(phantom)
data_sum = redop(phantom)

# Create functionals as needed
f = odl.solvers.IndicatorNonnegativity(domain)

alpha = 0.8
g_kl = [(1 - alpha) * odl.solvers.KullbackLeibler(ray_trafo.range, prior=d)
        for d in data]
g_l2 = alpha * odl.solvers.L2NormSquared(ray_trafo.range).translated(data_sum)
g = [odl.solvers.SeparableSum(*g_kl), g_l2]
Пример #4
0
# [-20, 20]^2 with 100 samples per dimension.
space = odl.uniform_discr(min_pt=[-20, -20],
                          max_pt=[20, 20],
                          shape=[100, 100],
                          dtype='float32')

# Make a parallel beam geometry with flat detector
# Angles: uniformly spaced, n = 300, min = 0, max = pi
angle_partition = odl.uniform_partition(0, np.pi, 300)
# Detector: uniformly sampled, n = 300, min = -30, max = 30
detector_partition = odl.uniform_partition(-30, 30, 300)
geometry = odl.tomo.Parallel2dGeometry(angle_partition, detector_partition)

# Create the forward operator, and also the vectorial forward operator.
ray_trafo = odl.tomo.RayTransform(space, geometry)
forward_op = odl.DiagonalOperator(ray_trafo, 2)

# Create phantom where the first component contains only part of the
# information in the  second component.
# We do this by using a sub-set of the ellipses in the well known Shepp-Logan
# phantom.
ellipses = odl.phantom.shepp_logan_ellipsoids(space.ndim, modified=True)
phantom = forward_op.domain.element([
    odl.phantom.ellipsoid_phantom(space, ellipses[:2]),
    odl.phantom.ellipsoid_phantom(space, ellipses)
])
phantom.show('phantom')

# Create data where second channel is highly noisy (SNR = 1)
data = forward_op(phantom)
data[1] += odl.phantom.white_noise(forward_op.range[1]) * np.mean(data[1])
Пример #5
0
            for i in range(self.domain.size):
                for j in range(self.domain[0].size):
                    result[i][j] += self.arr[k][i] * x[k][j]

        return result

    @property
    def adjoint(self):
        return LamOp(self.domain, self.arr.T)

data, geometry, crlb = load_fan_data(return_crlb=True)

space = odl.uniform_discr([-129, -129], [129, 129], [400, 400])

ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')
A = odl.DiagonalOperator(ray_trafo, 2)

grad = odl.Gradient(space)
grad_vec = odl.DiagonalOperator(grad, 2)

cross_terms = True
c = 0.5

if not cross_terms:
    crlb[1, 0, ...] = 0
    crlb[0, 1, ...] = 0

mat_sqrt_inv = inverse_sqrt_matrix(crlb)


re = ray_trafo.range.element
Пример #6
0
# Functionals
sol_space = space ** 2

l1norm_wave = odl.solvers.L1Norm(wave_op.range)
l1norm_shear = odl.solvers.L1Norm(shear_op.range)
data_matching = 1000 * odl.solvers.L2NormSquared(space)
data_matching = data_matching.translated(noisy_data)

f = odl.solvers.ZeroFunctional(sol_space)
penalizer = odl.solvers.SeparableSum(0.05 * l1norm_wave,
                                     l1norm_shear)

# Forward operators
sum_op = odl.ReductionOperator(
    odl.IdentityOperator(space), 2)
coeff_op = odl.DiagonalOperator(wave_op, shear_op)

# Solve using douglas_rachford_pd
g = [data_matching, penalizer]
L = [sum_op, coeff_op]

tau = 1
opnorms = [odl.power_method_opnorm(op) for op in L]
sigma = [1 / opnorm ** 2 for opnorm in opnorms]

callback = odl.solvers.CallbackShow(step=10)

images = sol_space.zero()
odl.solvers.douglas_rachford_pd(
    images, f, g, L, tau, sigma, niter=1000,
    callback=callback)
Пример #7
0
            v = disp_func[1]([x,y]) 
            
            plt.quiver(x,y,u,v,color='yellow')
            plt.axis('equal'),
            plt.axis([-1.3,1.3,-1.3,1.3]),
#                plt.axis('off'),
            plt.gca().set_aspect('equal', adjustable='box'),
            plt.savefig(folder_out + '/deformation_field.png',
                        bbox_inches='tight', 
                        pad_inches=0, 
                        transparent=True, dpi=600,format='png')

                            
            deform_op = defm.LinDeformFixedDisp(vf)
                    
            deformed_gt = odl.DiagonalOperator(deform_op, deform_op)(gt)
            
            # Forward operator    
            if unitary is True:
                F = ops.UnitaryRealFourierTransform(X)
            else:
                F = ops.RealFourierTransform(X)
            
            sampling_parts = sampling.split('-')
            if sampling_parts[0] == 'cartesian':
                r = int(sampling_parts[1])
                sampling_op, mask = ops.get_cartesian_sampling(F.range[0], r)
            elif sampling_parts[0] == 'random':
                p = float(sampling_parts[1])
                sampling_op, mask = ops.get_random_sampling(F.range[0], p)
            elif sampling_parts[0] == 'radial':
Пример #8
0
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.

from __future__ import division
import pytest

import odl
from odl.util.testutils import all_almost_equal, simple_fixture

base_op = simple_fixture('base_op', [
    odl.IdentityOperator(odl.rn(3)),
    odl.BroadcastOperator(odl.IdentityOperator(odl.rn(3)), 2),
    odl.ReductionOperator(odl.IdentityOperator(odl.rn(3)), 2),
    odl.DiagonalOperator(odl.IdentityOperator(odl.rn(3)), 2),
],
                         fmt=' {name}={value.__class__.__name__}')


def test_pspace_op_init(base_op):
    """Test initialization with different base operators."""
    A = base_op

    op = odl.ProductSpaceOperator([[A]])
    assert op.domain == A.domain**1
    assert op.range == A.range**1

    op = odl.ProductSpaceOperator([[A, A]])
    assert op.domain == A.domain**2
    assert op.range == A.range**1
Пример #9
0
noise_proj_data = proj_data + noise

# Compute the signal-to-noise ratio
snr = SNR(proj_data, noise, impl='dB')

# Output the signal-to-noise ratio
print('snr = {!r}'.format(snr))

# Do the backprojection reconstruction
backproj = xray_trafo_op.adjoint(noise_proj_data)

# FFT setting for regularization shape term, 1 means 100% padding
# FFT setting for data matching term, 1 means 100% padding
padded_size = 2 * cptsspace.shape[0]
padded_ft_shape_op = padded_ft_op(cptsspace, padded_size)
vectorial_ft_shape_op = odl.DiagonalOperator(*([padded_ft_shape_op] *
                                               cptsspace.ndim))

# FFT setting for data matching term, 1 means 100% padding
padded_ft_fit_op = padded_ft_op(discr_space, padded_size)
vectorial_ft_fit_op = odl.DiagonalOperator(*([padded_ft_fit_op] *
                                             discr_space.ndim))

# Initialize deformation vector field
momenta = vspace.zero()

# Fix the sigma parameter in the kernel
sigma = 4.0

# Compute Fourier trasform of the kernel function in data matching term
ft_kernel_fitting = fitting_kernel_ft(kernel)
Пример #10
0
where A is the ray transform, || . ||_W is the weighted l2 norm,
grad is the gradient and || . ||_* is the nuclear norm.
"""

import odl
import numpy as np
import scipy.linalg as spl
from util import cov_matrix, load_data, load_fan_data, inverse_sqrt_matrix

data, geometry, crlb = load_fan_data(return_crlb=True)

space = odl.uniform_discr([-129, -129], [129, 129], [400, 400])

ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')
A = odl.DiagonalOperator(ray_trafo, 2)

grad = odl.Gradient(space)
L = odl.DiagonalOperator(grad, 2)

# Compute covariance matrix and matrix power, this is slow.
mat_sqrt_inv = inverse_sqrt_matrix(crlb)

re = ray_trafo.range.element
W = odl.ProductSpaceOperator([[
    odl.MultiplyOperator(re(mat_sqrt_inv[0, 0])),
    odl.MultiplyOperator(re(mat_sqrt_inv[0, 1]))
],
                              [
                                  odl.MultiplyOperator(re(mat_sqrt_inv[1, 0])),
                                  odl.MultiplyOperator(re(mat_sqrt_inv[1, 1]))
Пример #11
0
The nuclear norm introduces a coupling between the channels, and hence we
expect that edges should coincide in the optimal solution.
"""

import odl

# Create space that the function should live in. Here, we want a vector valued
# function, so we create the tuple of two spaces.
space = odl.uniform_discr(0, 1, 100)
pspace = odl.ProductSpace(space, 2)

# Create the gradient operator on the set of vector-valued functions.
# We select pad_mode='order1' so that we have a Neumann-style boundary
# condition. Here we assume the gradient is continuous at the boundary.
gradient = odl.Gradient(space, pad_mode='order1')
pgradient = odl.DiagonalOperator(gradient, 2)

# Create the data. The first part is a linear function, the second is a step
# function at x=0.6
data = pspace.element([lambda x: x, lambda x: x > 0.6])
data.show('data')

# Create functionals for the data discrepancy (L2 squared) and for the
# regularizer (nuclear norm). The nuclear norm is defined on the range of
# the vectorial gradient, which is vector valued.
l2err = odl.solvers.L2NormSquared(pspace).translated(data)
nuc_norm = 0.02 * odl.solvers.NuclearNorm(pgradient.range)

# Assemble operators and functionals for the solver routine
lin_ops = [odl.IdentityOperator(pspace), pgradient]
g = [l2err, nuc_norm]
Пример #12
0
where A is the vectorial ray transform, W is the correlation matrix and grad
is the gradient.
"""

import odl
import numpy as np
import scipy.linalg as spl
from util import cov_matrix, load_data, load_fan_data

data, geometry = load_fan_data()

space = odl.uniform_discr([-129, -129], [129, 129], [200, 200])

ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')
A = odl.DiagonalOperator(ray_trafo, ray_trafo)

# Compute covariance matrix and matrix power
cov_mat = cov_matrix(data)
w_mat = spl.fractional_matrix_power(cov_mat, -0.5)

I = odl.IdentityOperator(ray_trafo.range)
W = odl.ProductSpaceOperator(np.multiply(w_mat, I))
A_corr = W * A

grad = odl.Gradient(space)
L = odl.DiagonalOperator(grad, grad)

op = A_corr.adjoint * A_corr + 10 * L.adjoint * L

fbp_op = odl.tomo.fbp_op(ray_trafo, filter_type='Hann', frequency_scaling=0.7)
Пример #13
0
 def inf_action(self, lie_alg_element):
     assert lie_alg_element in self.lie_group.associated_algebra
     subops = [ac.inf_action(lie_alg_element) for ac in self.actions]
     return odl.DiagonalOperator(*subops)
Пример #14
0
 def action(self, lie_grp_element):
     assert lie_grp_element in self.lie_group
     subops = [ac.action(lie_grp_element) for ac in self.actions]
     return odl.DiagonalOperator(*subops)
Пример #15
0
    phantom = domain.element([odl.phantom.ellipse_phantom(space, [e])
                              for e in ellipses])
    phantom = phantom.ufunc.absolute()
elif phantom_type == 'circles':
    ellipses = [[1, 0.8, 0.8, 0, 0, 0],
                [1, 0.4, 0.4, 0.2, 0.2, 0]]

    domain = odl.ProductSpace(space, len(ellipses))
    phantom = domain.element()
    phantom[0] = odl.phantom.ellipse_phantom(space, [ellipses[0]])
    phantom[1] = odl.phantom.ellipse_phantom(space, [ellipses[1]])
    phantom[0] -= phantom[1]

phantom.show('phantom', indices=np.s_[:])

diagop = odl.DiagonalOperator(ray_trafo, domain.size)
redop = odl.ReductionOperator(ray_trafo, domain.size)

# gradient
grad = odl.Gradient(ray_trafo.domain)
grad_n = odl.DiagonalOperator(grad, domain.size)

# Create data
data = diagop(phantom)
data_sum = redop(phantom)

# Add noise to data
scale_poisson = 1 / np.mean(data)  # 1 quanta per pixel, on avg
data += odl.phantom.poisson_noise(data * scale_poisson) / scale_poisson

scale_white_noise = 0.1 * np.mean(data_sum)  # 10% white noise
Пример #16
0
                                           detector_partition,
                                           axis=[1, 0, 0])

# Ray transform (= forward projection). We use ASTRA CUDA backend.
ray_trafo = odl.tomo.RayTransform(space, geometry, impl='astra_cuda')

# Create phantom
ellipses = odl.phantom.shepp_logan_ellipses(3, modified=True)[::4]

domain = odl.ProductSpace(space, len(ellipses))
phantom = domain.element(
    [odl.phantom.ellipse_phantom(space, [e]) for e in ellipses])
phantom.show('phantom', indices=np.s_[:])

alpha = 0.8
diagop = (1 - alpha) * odl.DiagonalOperator(ray_trafo, domain.size)
redop = alpha * odl.ReductionOperator(ray_trafo, domain.size)
op = odl.BroadcastOperator(diagop, redop)

data = op(phantom)
data.show('data')

callback = (odl.solvers.CallbackShow('iterates', display_step=5)
            & odl.solvers.CallbackPrintIteration())

x = op.domain.zero()
odl.solvers.conjugate_gradient_normal(op,
                                      x,
                                      data,
                                      niter=100,
                                      callback=callback)
Пример #17
0
# Forward operator (in the form of a broadcast operator)
ray_trafo = adutils.get_ray_trafo(reco_space, use_2D=True)

# Data
data = adutils.get_data(ray_trafo, use_2D=True)


# --- Set up the inverse problem --- #


# Initialize gradient operator
gradient = odl.Gradient(reco_space, method='forward')

gradient_back = odl.Gradient(reco_space, method='backward')
eps = odl.DiagonalOperator(gradient_back, reco_space.ndim)

# Create the domain of the problem, given by the reconstruction space and the
# range of the gradient on the reconstruction space.
domain = odl.ProductSpace(reco_space, gradient.range)

# Column vector of three operators defined as:
# 1. Computes ``A(x)``
# 2. Computes ``grad(x) - y``
# 3. Computes ``eps(y)``
op = odl.BroadcastOperator(
    ray_trafo * odl.ComponentProjection(domain, 0),
    odl.ReductionOperator(gradient, odl.ScalingOperator(gradient.range, -1)),
    eps * odl.ComponentProjection(domain, 1))

# Do not use the g functional, set it to zero.
         v = disp_func[1]([x,y]) 
         
         plt.quiver(x,y,u,v,color='yellow')
         plt.axis('equal'),
         plt.axis([-1.3,1.3,-1.3,1.3]),
 #                plt.axis('off'),
         plt.gca().set_aspect('equal', adjustable='box'),
         plt.savefig(folder_out + '/deformation_field.png',
                     bbox_inches='tight', 
                     pad_inches=0, 
                     transparent=True, dpi=600,format='png')
 
         
         deform_op = defm.LinDeformFixedDisp(vf)
                 
         deformed_gt = odl.DiagonalOperator(deform_op, deform_op)(gt)
         
             
         
         # Forward operator    
         if unitary is True:
             F = ops.UnitaryRealFourierTransform(X)
         else:
             F = ops.RealFourierTransform(X)
         
         sampling_parts = sampling.split('-')
         if sampling_parts[0] == 'cartesian':
             r = int(sampling_parts[1])
             sampling_op, mask = ops.get_cartesian_sampling(F.range[0], r)
         elif sampling_parts[0] == 'random':
             p = float(sampling_parts[1])