# -*- coding: utf-8 -*-
"""LINEAR OPERATORS
This module contains linear operator classes.
:Author: Samuel Farrens <samuel.farrens@gmail.com>
:Version: 1.3
:Date: 19/07/2017
"""
from builtins import range, zip
import numpy as np
from sf_tools.signal.wavelet import *
from sf_tools.math.matrix import rotate
[docs]class Identity(object):
"""Identity operator class
This is a dummy class that can be used in the optimisation classes
"""
def __init__(self):
self.l1norm = 1.0
[docs] def op(self, data, **kwargs):
"""Operator
Returns the input data unchanged
Parameters
----------
data : np.ndarray
Input data array
**kwargs
Arbitrary keyword arguments
Returns
-------
np.ndarray input data
"""
return data
[docs] def adj_op(self, data):
"""Adjoint operator
Returns the input data unchanged
Parameters
----------
data : np.ndarray
Input data array
Returns
-------
np.ndarray input data
"""
return data
[docs]class Wavelet(object):
"""Wavelet class
This class defines the wavelet transform operators
Parameters
----------
data : np.ndarray
Input data array, normally an array of 2D images
wavelet_opt: str, optional
Additional options for `mr_transform`
"""
def __init__(self, data, wavelet_opt=None):
self.y = data
self.data_shape = data.shape[-2:]
n = data.shape[0]
self.filters = get_mr_filters(self.data_shape, opt=wavelet_opt)
self.l1norm = n * np.sqrt(sum((np.sum(np.abs(filter)) ** 2 for
filter in self.filters)))
[docs] def op(self, data):
"""Operator
This method returns the input data convolved with the wavelet filters
Parameters
----------
data : np.ndarray
Input data array, a 2D image
Returns
-------
np.ndarray wavelet convolved data
"""
return filter_convolve_stack(data, self.filters)
[docs] def adj_op(self, data):
"""Adjoint operator
This method returns the input data convolved with the wavelet filters
rotated by 180 degrees
Parameters
----------
data : np.ndarray
Input data array, a 3D of wavelet coefficients
Returns
-------
np.ndarray wavelet convolved data
"""
return filter_convolve_stack(data, self.filters, filter_rot=True)
[docs]class LinearCombo(object):
"""Linear combination class
This class defines a combination of linear transform operators
Parameters
----------
operators : list
List of linear operator class instances
weights : list, optional
List of weights for combining the linear adjoint operator results
"""
def __init__(self, operators, weights=None):
self.operators = operators
self.weights = weights
self.l1norm = np.array([operator.l1norm for operator in
self.operators])
[docs] def op(self, data):
"""Operator
This method returns the input data operated on by all of the operators
Parameters
----------
data : np.ndarray
Input data array, a 2D image
Returns
-------
np.ndarray linear operation results
"""
res = np.empty(len(self.operators), dtype=np.ndarray)
for i in range(len(self.operators)):
res[i] = self.operators[i].op(data)
return res
[docs] def adj_op(self, data):
"""Adjoint operator
This method returns the combination of the result of all of the
adjoint operators. If weights are provided the comibination is the sum
of the weighted results, otherwise the combination is the mean.
Parameters
----------
data : np.ndarray
Input data array, an array of coefficients
Returns
-------
np.ndarray adjoint operation results
"""
if isinstance(self.weights, type(None)):
return np.mean([operator.adj_op(x) for x, operator in
zip(data, self.operators)], axis=0)
else:
return np.sum([weight * operator.adj_op(x) for x, operator,
weight in zip(data, self.operators, weights)],
axis=0)