summaryrefslogtreecommitdiffstats
path: root/Wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'Wrappers')
-rwxr-xr-xWrappers/Python/ccpi/framework/BlockDataContainer.py97
-rwxr-xr-xWrappers/Python/ccpi/framework/framework.py188
-rwxr-xr-xWrappers/Python/test/test_BlockDataContainer.py6
-rw-r--r--Wrappers/Python/test/test_functions.py10
-rwxr-xr-xWrappers/Python/wip/pdhg_TV_denoising.py57
5 files changed, 118 insertions, 240 deletions
diff --git a/Wrappers/Python/ccpi/framework/BlockDataContainer.py b/Wrappers/Python/ccpi/framework/BlockDataContainer.py
index 4655e1b..386cd87 100755
--- a/Wrappers/Python/ccpi/framework/BlockDataContainer.py
+++ b/Wrappers/Python/ccpi/framework/BlockDataContainer.py
@@ -45,6 +45,7 @@ class BlockDataContainer(object):
DIVIDE = 'divide'
POWER = 'power'
__array_priority__ = 1
+ __container_priority__ = 2
def __init__(self, *args, **kwargs):
''''''
self.containers = args
@@ -97,7 +98,6 @@ class BlockDataContainer(object):
a = el.is_compatible(other)
else:
a = el.shape == other.shape
-# print ("current element" , el.shape, "other ", other.shape, "same shape" , a)
ret = ret and a
return ret
#return self.get_item(0).shape == other.shape
@@ -111,92 +111,45 @@ class BlockDataContainer(object):
def __getitem__(self, row):
return self.get_item(row)
-# def add(self, other, *args, **kwargs):
-# if not self.is_compatible(other):
-# raise ValueError('Incompatible for add')
-# out = kwargs.get('out', None)
-# #print ("args" , *args)
-# if isinstance(other, Number):
-# return type(self)(*[ el.add(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# elif isinstance(other, list) or isinstance(other, numpy.ndarray):
-# return type(self)(*[ el.add(ot, *args, **kwargs) for el,ot in zip(self.containers,other)], shape=self.shape)
-# elif issubclass(other.__class__, DataContainer):
-# # try to do algebra with one DataContainer. Will raise error if not compatible
-# return type(self)(*[ el.add(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-#
-# return type(self)(
-# *[ el.add(ot, *args, **kwargs) for el,ot in zip(self.containers,other.containers)],
-# shape=self.shape)
-#
-# def subtract(self, other, *args, **kwargs):
-# if not self.is_compatible(other):
-# raise ValueError('Incompatible for subtract')
-# out = kwargs.get('out', None)
-# if isinstance(other, Number):
-# return type(self)(*[ el.subtract(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# elif isinstance(other, list) or isinstance(other, numpy.ndarray):
-# return type(self)(*[ el.subtract(ot, *args, **kwargs) for el,ot in zip(self.containers,other)], shape=self.shape)
-# elif issubclass(other.__class__, DataContainer):
-# # try to do algebra with one DataContainer. Will raise error if not compatible
-# return type(self)(*[ el.subtract(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# return type(self)(*[ el.subtract(ot, *args, **kwargs) for el,ot in zip(self.containers,other.containers)],
-# shape=self.shape)
-#
-# def multiply(self, other, *args, **kwargs):
-# if not self.is_compatible(other):
-# raise ValueError('{} Incompatible for multiply'.format(other))
-# out = kwargs.get('out', None)
-# if isinstance(other, Number):
-# return type(self)(*[ el.multiply(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# elif isinstance(other, list):
-# return type(self)(*[ el.multiply(ot, *args, **kwargs) for el,ot in zip(self.containers,other)], shape=self.shape)
-# elif isinstance(other, numpy.ndarray):
-# return type(self)(*[ el.multiply(ot, *args, **kwargs) for el,ot in zip(self.containers,other)], shape=self.shape)
-# elif issubclass(other.__class__, DataContainer):
-# # try to do algebra with one DataContainer. Will raise error if not compatible
-# return type(self)(*[ el.multiply(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# return type(self)(*[ el.multiply(ot, *args, **kwargs) for el,ot in zip(self.containers,other.containers)],
-# shape=self.shape)
-#
-# def divide_old(self, other, *args, **kwargs):
-# if not self.is_compatible(other):
-# raise ValueError('Incompatible for divide')
-# out = kwargs.get('out', None)
-# if isinstance(other, Number):
-# return type(self)(*[ el.divide(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# elif isinstance(other, list) or isinstance(other, numpy.ndarray):
-# return type(self)(*[ el.divide(ot, *args, **kwargs) for el,ot in zip(self.containers,other)], shape=self.shape)
-# elif issubclass(other.__class__, DataContainer):
-# # try to do algebra with one DataContainer. Will raise error if not compatible
-# if out is not None:
-# kw = kwargs.copy()
-# for i,el in enumerate(self.containers):
-# kw['out'] = out.get_item(i)
-# el.divide(other, *args, **kw)
-# return
-# else:
-# return type(self)(*[ el.divide(other, *args, **kwargs) for el in self.containers], shape=self.shape)
-# return type(self)(*[ el.divide(ot, *args, **kwargs) for el,ot in zip(self.containers,other.containers)],
-# shape=self.shape)
def add(self, other, *args, **kwargs):
+ '''Algebra: add method of BlockDataContainer with number/DataContainer or BlockDataContainer
+
+ :param: other (number, DataContainer or subclasses or BlockDataContainer
+ :param: out (optional): provides a placehold for the resul.
+ '''
out = kwargs.get('out', None)
if out is not None:
self.binary_operations(BlockDataContainer.ADD, other, *args, **kwargs)
else:
return self.binary_operations(BlockDataContainer.ADD, other, *args, **kwargs)
def subtract(self, other, *args, **kwargs):
+ '''Algebra: subtract method of BlockDataContainer with number/DataContainer or BlockDataContainer
+
+ :param: other (number, DataContainer or subclasses or BlockDataContainer
+ :param: out (optional): provides a placehold for the resul.
+ '''
out = kwargs.get('out', None)
if out is not None:
self.binary_operations(BlockDataContainer.SUBTRACT, other, *args, **kwargs)
else:
return self.binary_operations(BlockDataContainer.SUBTRACT, other, *args, **kwargs)
def multiply(self, other, *args, **kwargs):
+ '''Algebra: multiply method of BlockDataContainer with number/DataContainer or BlockDataContainer
+
+ :param: other (number, DataContainer or subclasses or BlockDataContainer
+ :param: out (optional): provides a placehold for the resul.
+ '''
out = kwargs.get('out', None)
if out is not None:
self.binary_operations(BlockDataContainer.MULTIPLY, other, *args, **kwargs)
else:
return self.binary_operations(BlockDataContainer.MULTIPLY, other, *args, **kwargs)
def divide(self, other, *args, **kwargs):
+ '''Algebra: divide method of BlockDataContainer with number/DataContainer or BlockDataContainer
+
+ :param: other (number, DataContainer or subclasses or BlockDataContainer
+ :param: out (optional): provides a placehold for the resul.
+ '''
out = kwargs.get('out', None)
if out is not None:
self.binary_operations(BlockDataContainer.DIVIDE, other, *args, **kwargs)
@@ -205,6 +158,14 @@ class BlockDataContainer(object):
def binary_operations(self, operation, other, *args, **kwargs):
+ '''Algebra: generic method of algebric operation with BlockDataContainer with number/DataContainer or BlockDataContainer
+
+ Provides commutativity with DataContainer and subclasses, i.e. this
+ class's reverse algebric methods take precedence w.r.t. direct algebric
+ methods of DataContainer and subclasses.
+
+ This method is not to be used directly
+ '''
if not self.is_compatible(other):
raise ValueError('Incompatible for divide')
out = kwargs.get('out', None)
diff --git a/Wrappers/Python/ccpi/framework/framework.py b/Wrappers/Python/ccpi/framework/framework.py
index e03a29c..af4139b 100755
--- a/Wrappers/Python/ccpi/framework/framework.py
+++ b/Wrappers/Python/ccpi/framework/framework.py
@@ -320,6 +320,7 @@ class DataContainer(object):
Data is currently held in a numpy arrays'''
+ __container_priority__ = 1
def __init__ (self, array, deep_copy=True, dimension_labels=None,
**kwargs):
'''Holds the data'''
@@ -495,119 +496,21 @@ class DataContainer(object):
return self.shape == other.shape
## algebra
- def __add__(self, other, *args, **kwargs):
- out = kwargs.get('out', None)
-
- if issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- out = self.as_array() + other.as_array()
- return type(self)(out,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise ValueError('Wrong shape: {0} and {1}'.format(self.shape,
- other.shape))
- elif isinstance(other, (int, float, complex)):
- return type(self)(
- self.as_array() + other,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise TypeError('Cannot {0} DataContainer with {1}'.format("add" ,
- type(other)))
- # __add__
+ def __add__(self, other):
+ return self.add(other)
+ def __mul__(self, other):
+ return self.multiply(other)
def __sub__(self, other):
- if issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- out = self.as_array() - other.as_array()
- return type(self)(out,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise ValueError('__sub__ Wrong shape: {0} and {1}'.format(self.shape,
- other.shape))
- elif isinstance(other, (int, float, complex)):
- return type(self)(self.as_array() - other,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise TypeError('Cannot {0} DataContainer with {1}'.format("subtract" ,
- type(other)))
- # __sub__
- def __truediv__(self,other):
- return self.__div__(other)
-
+ return self.subtract(other)
def __div__(self, other):
- if issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- out = self.as_array() / other.as_array()
- return type(self)(out,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise ValueError('__div__ Wrong shape: {0} and {1}'.format(self.shape,
- other.shape))
- elif isinstance(other, (int, float, complex)):
- return type(self)(self.as_array() / other,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise TypeError('Cannot {0} DataContainer with {1}'.format("divide" ,
- type(other)))
- # __div__
-
+ return self.divide(other)
+ def __truediv__(self, other):
+ return self.divide(other)
def __pow__(self, other):
- if issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- out = self.as_array() ** other.as_array()
- return type(self)(out,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise ValueError('__pow__ Wrong shape: {0} and {1}'.format(self.shape,
- other.shape))
- elif isinstance(other, (int, float, complex)):
- return type(self)(self.as_array() ** other,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise TypeError('pow: Cannot {0} DataContainer with {1}'.format("power" ,
- type(other)))
- # __pow__
+ return self.power(other)
+
- def __mul__(self, other):
- if issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- out = self.as_array() * other.as_array()
- return type(self)(out,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
- else:
- raise ValueError('*:Wrong shape: {0} and {1}'.format(self.shape,
- other.shape))
- elif isinstance(other, (int, float, complex,\
- numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.int64,\
- numpy.float, numpy.float16, numpy.float32, numpy.float64, \
- numpy.complex)):
- return type(self)(self.as_array() * other,
- deep_copy=True,
- dimension_labels=self.dimension_labels,
- geometry=self.geometry)
-
- else:
- raise TypeError('Cannot {0} DataContainer with {1}'.format("multiply" ,
- type(other)))
- # __mul__
# reverse operand
def __radd__(self, other):
@@ -648,54 +551,27 @@ class DataContainer(object):
# (+=, -=, *=, /= , //=,
# must return self
-
-
def __iadd__(self, other):
- if isinstance(other, (int, float)) :
- numpy.add(self.array, other, out=self.array)
- elif issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- numpy.add(self.array, other.array, out=self.array)
- else:
- raise ValueError('Dimensions do not match')
- return self
- # __iadd__
+ kw = {'out':self}
+ return self.add(other, **kw)
def __imul__(self, other):
- if isinstance(other, (int, float)) :
- arr = self.as_array()
- numpy.multiply(arr, other, out=arr)
- elif issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- numpy.multiply(self.array, other.array, out=self.array)
- else:
- raise ValueError('Dimensions do not match')
- return self
- # __imul__
+ kw = {'out':self}
+ return self.multiply(other, **kw)
def __isub__(self, other):
- if isinstance(other, (int, float)) :
- numpy.subtract(self.array, other, out=self.array)
- elif issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- numpy.subtract(self.array, other.array, out=self.array)
- else:
- raise ValueError('Dimensions do not match')
- return self
- # __isub__
+ kw = {'out':self}
+ return self.subtract(other, **kw)
def __idiv__(self, other):
- return self.__itruediv__(other)
+ kw = {'out':self}
+ return self.divide(other, **kw)
+
def __itruediv__(self, other):
- if isinstance(other, (int, float)) :
- numpy.divide(self.array, other, out=self.array)
- elif issubclass(type(other), DataContainer):
- if self.check_dimensions(other):
- numpy.divide(self.array, other.array, out=self.array)
- else:
- raise ValueError('Dimensions do not match')
- return self
- # __idiv__
+ kw = {'out':self}
+ return self.divide(other, **kw)
+
+
def __str__ (self, representation=False):
repres = ""
@@ -802,15 +678,27 @@ class DataContainer(object):
raise ValueError (message(type(self), "incompatible class:" , pwop.__name__, type(out)))
def add(self, other, *args, **kwargs):
+ if hasattr(other, '__container_priority__') and \
+ self.__class__.__container_priority__ < other.__class__.__container_priority__:
+ return other.add(self, *args, **kwargs)
return self.pixel_wise_binary(numpy.add, other, *args, **kwargs)
def subtract(self, other, *args, **kwargs):
+ if hasattr(other, '__container_priority__') and \
+ self.__class__.__container_priority__ < other.__class__.__container_priority__:
+ return other.subtract(self, *args, **kwargs)
return self.pixel_wise_binary(numpy.subtract, other, *args, **kwargs)
def multiply(self, other, *args, **kwargs):
+ if hasattr(other, '__container_priority__') and \
+ self.__class__.__container_priority__ < other.__class__.__container_priority__:
+ return other.multiply(self, *args, **kwargs)
return self.pixel_wise_binary(numpy.multiply, other, *args, **kwargs)
def divide(self, other, *args, **kwargs):
+ if hasattr(other, '__container_priority__') and \
+ self.__class__.__container_priority__ < other.__class__.__container_priority__:
+ return other.divide(self, *args, **kwargs)
return self.pixel_wise_binary(numpy.divide, other, *args, **kwargs)
def power(self, other, *args, **kwargs):
@@ -883,7 +771,7 @@ class DataContainer(object):
class ImageData(DataContainer):
'''DataContainer for holding 2D or 3D DataContainer'''
-
+ __container_priority__ = 1
def __init__(self,
array = None,
deep_copy=False,
@@ -1006,7 +894,7 @@ class ImageData(DataContainer):
class AcquisitionData(DataContainer):
'''DataContainer for holding 2D or 3D sinogram'''
-
+ __container_priority__ = 1
def __init__(self,
array = None,
deep_copy=True,
diff --git a/Wrappers/Python/test/test_BlockDataContainer.py b/Wrappers/Python/test/test_BlockDataContainer.py
index 0dd0657..a20f289 100755
--- a/Wrappers/Python/test/test_BlockDataContainer.py
+++ b/Wrappers/Python/test/test_BlockDataContainer.py
@@ -369,6 +369,12 @@ class TestBlockDataContainer(unittest.TestCase):
c5 = nbdc.get_item(0).power(2).sum()
c5a = nbdc.power(2).sum()
print ("sum", c5a, c5)
+
+ cp0 = BlockDataContainer(data0,data2)
+ a = cp0 * data2
+ b = data2 * cp0
+ self.assertBlockDataContainerEqual(a,b)
+
print ("test_Nested_BlockDataContainer OK")
def stest_NestedBlockDataContainer2(self):
diff --git a/Wrappers/Python/test/test_functions.py b/Wrappers/Python/test/test_functions.py
index bc1f034..22721fa 100644
--- a/Wrappers/Python/test/test_functions.py
+++ b/Wrappers/Python/test/test_functions.py
@@ -323,13 +323,15 @@ class TestFunction(unittest.TestCase):
# Define no scale and scaled
f_no_scaled = MixedL21Norm()
- #f_scaled = 0.5 * MixedL21Norm()
+ f_scaled = 1 * MixedL21Norm()
# call
- # a1 = f_no_scaled(U)
- # a2 = f_scaled(U)
- # self.assertBlockDataContainerEqual(a1,a2)
+ a1 = f_no_scaled(U)
+ a2 = f_scaled(U)
+ self.assertAlmostEqual(a1,a2)
+
+
tmp = [ el**2 for el in U.containers ]
self.assertBlockDataContainerEqual(BlockDataContainer(*tmp),
U.power(2))
diff --git a/Wrappers/Python/wip/pdhg_TV_denoising.py b/Wrappers/Python/wip/pdhg_TV_denoising.py
index 2072ea3..73fd57a 100755
--- a/Wrappers/Python/wip/pdhg_TV_denoising.py
+++ b/Wrappers/Python/wip/pdhg_TV_denoising.py
@@ -91,36 +91,57 @@ tau = 1/(sigma*normK**2)
opt = {'niter':2000}
opt1 = {'niter':2000, 'memopt': True}
-t1 = timer()
-res, time, primal, dual, pdgap = PDHG_old(f, g, operator, tau = tau, sigma = sigma, opt = opt)
-print(timer()-t1)
+#t1 = timer()
+#res, time, primal, dual, pdgap = PDHG_old(f, g, operator, tau = tau, sigma = sigma, opt = opt)
+#print(timer()-t1)
+#
+#print("with memopt \n")
+#
+#t2 = timer()
+#res1, time1, primal1, dual1, pdgap1 = PDHG_old(f, g, operator, tau = tau, sigma = sigma, opt = opt1)
+#print(timer()-t2)
+
+pdhg = PDHG(f=f,g=g,operator=operator, tau=tau, sigma=sigma)
+pdhg.max_iteration = 2000
+pdhg.update_objective_interval = 100
+
+
+pdhgo = PDHG(f=f,g=g,operator=operator, tau=tau, sigma=sigma, memopt=True)
+pdhgo.max_iteration = 2000
+pdhgo.update_objective_interval = 100
-print("with memopt \n")
+steps = [timer()]
+pdhgo.run(2000)
+steps.append(timer())
+t1 = dt(steps)
+
+pdhg.run(2000)
+steps.append(timer())
+t2 = dt(steps)
+
+print ("Time difference {}s {}s {}s Speedup {:.2f}".format(t1,t2,t2-t1, t2/t1))
+res = pdhg.get_output()
+res1 = pdhgo.get_output()
+
+diff = (res-res1)
+print ("diff norm {} max {}".format(diff.norm(), diff.abs().as_array().max()))
+print ("Sum ( abs(diff) ) {}".format(diff.abs().sum()))
-t2 = timer()
-res1, time1, primal1, dual1, pdgap1 = PDHG_old(f, g, operator, tau = tau, sigma = sigma, opt = opt1)
-print(timer()-t2)
plt.figure(figsize=(5,5))
+plt.subplot(1,3,1)
plt.imshow(res.as_array())
plt.colorbar()
-plt.show()
+#plt.show()
-plt.figure(figsize=(5,5))
+#plt.figure(figsize=(5,5))
+plt.subplot(1,3,2)
plt.imshow(res1.as_array())
plt.colorbar()
-plt.show()
+#plt.show()
-diff = np.abs(res1.as_array()-res.as_array())
-plt.figure(figsize=(5,5))
-plt.imshow(diff)
-plt.colorbar()
-plt.show()
-diff = (res-res1)
-print ("diff norm {} max {}".format(diff.norm(), diff.abs().as_array().max()))
-print ("Sum ( abs(diff) ) {}".format(diff.abs().sum()))
#=======
## opt = {'niter':2000, 'memopt': True}
#