Example #1
0
def test_proximal_composition(pos_scalar, sigma):
    """Test for proximal of composition with semi-orthogonal linear operator.

    This test is for ``prox[f * L](x)``, where ``L`` is a linear operator such
    that ``L * L.adjoint = mu * IdentityOperator``. Specifically, ``L`` is
    taken to be ``scal * IdentityOperator``, since this is equivalent to
    scaling of the argument.
    """
    sigma = float(sigma)
    space = odl.uniform_discr(0, 1, 10)
    prox_factory = proximal_l2_squared(space)

    # The semi-orthogonal linear operator
    scal = pos_scalar
    L = odl.ScalingOperator(space, scal)
    mu = scal ** 2  # L = scal * I => L * L.adjoint = scal ** 2 * I
    prox_factory_composition = proximal_composition(prox_factory, L, mu)
    prox = prox_factory_composition(sigma)

    assert isinstance(prox, odl.Operator)

    x = space.element(np.arange(-5, 5))
    prox_x = prox(x)
    equiv_prox = proximal_arg_scaling(prox_factory, scal)(sigma)
    expected_result = equiv_prox(x)
    assert all_almost_equal(prox_x, expected_result, places=PLACES)
Example #2
0
def test_module_forward(shape, use_cuda):
    """Test forward evaluation with operators as modules."""
    ndim = len(shape)
    space = odl.uniform_discr([0] * ndim, shape, shape)
    odl_op = odl.ScalingOperator(space, 2)
    op_mod = odl_torch.OperatorAsModule(odl_op)

    x = torch.from_numpy(np.ones(shape))
    if use_cuda:
        x = x.cuda()

    # Test with 1 extra dim (minimum)
    x_var = autograd.Variable(x, requires_grad=True)[None, ...]
    y_var = op_mod(x_var)

    assert y_var.data.shape == (1, ) + odl_op.range.shape
    assert all_almost_equal(y_var.data.cpu().numpy(),
                            2 * np.ones((1, ) + shape))

    # Test with 2 extra dims
    x_var = autograd.Variable(x, requires_grad=True)[None, None, ...]
    y_var = op_mod(x_var)

    assert y_var.data.shape == (1, 1) + odl_op.range.shape
    assert all_almost_equal(y_var.data.cpu().numpy(),
                            2 * np.ones((1, 1) + shape))

    # Make sure data stays on the GPU
    if use_cuda:
        assert y_var.is_cuda
Example #3
0
def test_module_forward(shape, device):
    """Test forward evaluation with operators as modules."""
    # Define ODL operator and wrap as module
    ndim = len(shape)
    space = odl.uniform_discr([0] * ndim, shape, shape, dtype='float32')
    odl_op = odl.ScalingOperator(space, 2)
    op_mod = odl_torch.OperatorModule(odl_op)

    # Input data
    x_arr = np.ones(shape, dtype='float32')

    # Test with 1 extra dim (minimum)
    x = torch.from_numpy(x_arr).to(device)[None, ...]
    x.requires_grad_(True)
    res = op_mod(x)
    res_arr = res.detach().cpu().numpy()
    assert res_arr.shape == (1, ) + odl_op.range.shape
    assert all_almost_equal(res_arr, np.asarray(odl_op(x_arr))[None, ...])
    assert x.device.type == res.device.type == device

    # Test with 2 extra dims
    x = torch.from_numpy(x_arr).to(device)[None, None, ...]
    x.requires_grad_(True)
    res = op_mod(x)
    res_arr = res.detach().cpu().numpy()
    assert res_arr.shape == (1, 1) + odl_op.range.shape
    assert all_almost_equal(res_arr,
                            np.asarray(odl_op(x_arr))[None, None, ...])
    assert x.device.type == res.device.type == device
Example #4
0
    def reconstruction(proj_data, parameters):
        # Extract the separate parameters
        lam, sigma = parameters

        print('lam = {}, sigma = {}'.format(lam, sigma))

        # We do not allow negative parameters, so return a bogus result
        if lam <= 0 or sigma <= 0:
            return np.inf * space.one()

        # Create data term ||Ax - b||_2^2
        l2_norm = odl.solvers.L2NormSquared(ray_trafo.range)
        data_discrepancy = l2_norm * (ray_trafo - proj_data)

        # Create regularizing functional huber(|grad(x)|)
        gradient = odl.Gradient(space)
        l1_norm = odl.solvers.GroupL1Norm(gradient.range)
        smoothed_l1 = odl.solvers.MoreauEnvelope(l1_norm, sigma=sigma)
        regularizer = smoothed_l1 * gradient

        # Create full objective functional
        obj_fun = data_discrepancy + lam * regularizer

        # Pick parameters
        maxiter = 30
        num_store = 5

        # Run the algorithm
        x = ray_trafo.domain.zero()
        odl.solvers.bfgs_method(obj_fun,
                                x,
                                maxiter=maxiter,
                                num_store=num_store,
                                hessinv_estimate=odl.ScalingOperator(
                                    space,
                                    1 / odl.power_method_opnorm(ray_trafo)**2))

        return x
Example #5
0
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.
g = odl.solvers.ZeroFunctional(op.domain)

# Create functionals for the dual variable

# l2-squared data matching
l2_norm = odl.solvers.L2NormSquared(ray_trafo.range).translated(data)

# The l1-norms scaled by regularization paramters
l1_norm_1 = 0.001 * odl.solvers.L1Norm(gradient.range)
l1_norm_2 = 1e-4 * odl.solvers.L1Norm(eps.range)

# Combine functionals, order must correspond to the operator K
Example #6
0
#    [[Dx, 0], [0, Dy], [0.5*Dy, 0.5*Dx]], range=W)
E = odl.operator.ProductSpaceOperator(
    [[Dx, 0], [0, Dy], [0.5*Dy, 0.5*Dx], [0.5*Dy, 0.5*Dx]])
W = E.range

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

# Column vector of three operators defined as:
# 1. Computes ``Ax``
# 2. Computes ``Gx - y``
# 3. Computes ``Ey``
op = odl.BroadcastOperator(
    A * odl.ComponentProjection(domain, 0),
    odl.ReductionOperator(G, odl.ScalingOperator(V, -1)),
    E * odl.ComponentProjection(domain, 1))

# Do not use the g functional, set it to zero.
g = odl.solvers.ZeroFunctional(domain)

# l2-squared data matching
l2_norm = odl.solvers.L2NormSquared(A.range).translated(data)

# parameters
alpha = 1e-1
beta = 1

# The l1-norms scaled by regularization paramters
l1_norm_1 = alpha * odl.solvers.L1Norm(V)
l1_norm_2 = alpha * beta * odl.solvers.L1Norm(W)
Example #7
0
data = ray_trafo(discr_phantom)
data += odl.phantom.white_noise(ray_trafo.range) * np.mean(data) * 0.1

# --- Set up optimization problem and solve --- #

# Create objective functional ||Ax - b||_2^2 as composition of l2 norm squared
# and the residual operator.
obj_fun = odl.solvers.L2NormSquared(ray_trafo.range) * (ray_trafo - data)

# Create line search
line_search = 1.0
# line_search = odl.solvers.BacktrackingLineSearch(obj_fun)

# Create initial estimate of the inverse Hessian by a diagonal estimate
opnorm = odl.power_method_opnorm(ray_trafo)
hessinv_estimate = odl.ScalingOperator(reco_space, 1 / opnorm**2)

# Optionally pass callback to the solver to display intermediate results
callback = (odl.solvers.CallbackPrintIteration() & odl.solvers.CallbackShow())

# Pick parameters
maxiter = 20
num_store = 5  # only save some vectors (Limited memory)

# Choose a starting point
x = ray_trafo.domain.zero()

# Run the algorithm
odl.solvers.bfgs_method(obj_fun,
                        x,
                        line_search=line_search,
Example #8
0
data_discrepancy = odl.solvers.L2NormSquared(A.range).translated(rhs)

l1_norm = odl.solvers.L1Norm(space)
huber = 2.5 * odl.solvers.MoreauEnvelope(l1_norm, sigma=0.01)

my_op = MyOperatorTrace(domain=grad_vec.range, range=space, linear=False)

spc_cov_matrix = [[1, -c],
                  [-c, 1]]
spc_cov_matrix_inv_sqrt = inverse_sqrt_matrix(spc_cov_matrix)
Lam = LamOp(grad_vec.range, arr=spc_cov_matrix_inv_sqrt)

func = data_discrepancy * op + huber * my_op * Lam * grad_vec

fbp_op = odl.tomo.fbp_op(ray_trafo,
                         filter_type='Hann', frequency_scaling=0.7)
x = A.domain.element([fbp_op(data[0]), fbp_op(data[1])])
x.show(clim=[0.9, 1.1])

callback = (odl.solvers.CallbackShow(step=5) &
            odl.solvers.CallbackShow(step=5, clim=[-0.1, 0.1]) &
            odl.solvers.CallbackShow(step=5, clim=[0.9, 1.1]) &
            odl.solvers.CallbackPrintIteration())

opnorm = odl.power_method_opnorm(op)
hessinv_estimate = odl.ScalingOperator(func.domain, 1 / opnorm ** 2)

odl.solvers.bfgs_method(func, x, line_search=1.0, maxiter=1000, num_store=10,
                        callback=callback, hessinv_estimate=hessinv_estimate)
Example #9
0
phantom = odl.phantom.shepp_logan(space, modified=True)

# Create sinogram of forward projected phantom with noise
data = operator(phantom)
data += odl.phantom.white_noise(operator.range) * np.mean(np.abs(data)) * 0.05

# --- Set up optimization problem and solve --- #

# Create data term ||Ax - b||_2^2 as composition of the squared L2 norm and the
# ray trafo translated by the data.
l2_norm = odl.solvers.L2NormSquared(operator.range)
data_discrepancy = l2_norm * (operator - data)

# Create initial estimate of the inverse Hessian by a diagonal estimate
opnorm = odl.power_method_opnorm(operator)
hessinv_estimate = odl.ScalingOperator(space, 0.5 / opnorm**2)

sigma = 0.03
lam = 0.3

# Create regularizing functional || |grad(x)| ||_1 and smooth the functional
# using the Moreau envelope.
# The parameter sigma controls the strength of the regularization.
gradient = odl.Gradient(space)
l1_norm = odl.solvers.GroupL1Norm(gradient.range)
smoothed_l1 = odl.solvers.MoreauEnvelope(l1_norm, sigma=sigma)
regularizer = smoothed_l1 * gradient

# Create full objective functional
obj_fun = data_discrepancy + lam * regularizer
Example #10
0
mu = [
    np.less(y, (c[0] + c[1]) / 2),
    np.logical_and(np.greater_equal(y, (c[0] + c[1]) / 2),
                   np.less(y, (c[1] + c[2]) / 2)),
    np.greater_equal(y, (c[1] + c[2]) / 2)
]
x = y.copy()

callback = (odl.solvers.CallbackShow('bias', display_step=1)
            & odl.solvers.CallbackPrintIteration())

# Store some values
I = len(c)
spatial_domain = y.space
ones = spatial_domain.one()  # ones.inner(x)  gives integral of x
scaling = odl.ScalingOperator(spatial_domain, lam1)
conv_adj_mu_pow_m = [None] * I
cd
# Iteratively solve the coordinate descent equations
for _ in range(niter):
    # Update mu
    for i in range(I):
        summand = spatial_domain.zero()
        convi = conv((x - c[i])**2)
        for j in range(I):
            convj = conv((x - c[j])**2)
            summand += np.power(convi / convj, 1.0 / (m - 1.0))
        mu[i] = 1.0 / summand
        conv_adj_mu_pow_m[i] = conv.adjoint(np.power(mu[i], m))

    # Update c
Example #11
0
    # Create huber norm
    grad = odl.Gradient(space)
    l1_norm = odl.solvers.GroupL1Norm(grad.range)
    huber = odl.solvers.MoreauEnvelope(l1_norm, sigma=sigma)

    func = l2 + lam * huber * grad

    callback = odl.solvers.CallbackPrintIteration(
        'huber material {} lam {}'.format(material, lam))

    opnorm = odl.power_method_opnorm(ray_trafo)
    if lam > 0:
        reg_norm = odl.power_method_opnorm((lam * huber * grad).gradient)
    else:
        reg_norm = 0
    hessinv_estimate = odl.ScalingOperator(func.domain,
                                           1 / (opnorm + reg_norm)**2)

    x = func.domain.zero()
    odl.solvers.bfgs_method(func,
                            x,
                            line_search=1.0,
                            maxiter=1000,
                            num_store=10,
                            callback=callback,
                            hessinv_estimate=hessinv_estimate)

    import scipy.io as sio
    mdict = {'result': x.asarray(), 'lam': lam}
    sio.savemat(
        'data/results/parameters/result_huber_{}_lam_{}'.format(material, lam),
        mdict)
Example #12
0
 def inf_action(self, lie_alg_element):
     assert lie_alg_element in self.lie_group.associated_algebra
     return odl.ScalingOperator(self.domain, np.trace(lie_alg_element.arr))
Example #13
0
 def action(self, lie_grp_element):
     assert lie_grp_element in self.lie_group
     return odl.ScalingOperator(self.domain,
                                np.linalg.det(lie_grp_element.arr))