From b4f439677fa9a8d8235b2ddc0dcbda88cab7b76b Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 13:58:46 +0100 Subject: commutative algebra between BlockDataContainers and DataContainers simplified algebra in DataContainer --- .../Python/ccpi/framework/BlockDataContainer.py | 1 + Wrappers/Python/ccpi/framework/framework.py | 348 ++++++++++++--------- Wrappers/Python/test/test_BlockDataContainer.py | 6 + 3 files changed, 204 insertions(+), 151 deletions(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/ccpi/framework/BlockDataContainer.py b/Wrappers/Python/ccpi/framework/BlockDataContainer.py index 529a1ce..060b130 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 diff --git a/Wrappers/Python/ccpi/framework/framework.py b/Wrappers/Python/ccpi/framework/framework.py index 07c2ead..3982965 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,134 @@ 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, *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 __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) +# +# 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__ +# +# 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__ +# +# 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__ + + 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 +664,72 @@ 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 __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__ +# +# 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__ +# +# 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__ +# +# def __idiv__(self, other): +# return self.__itruediv__(other) +# 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__ def __str__ (self, representation=False): repres = "" @@ -802,15 +836,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 +929,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 +1052,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): -- cgit v1.2.3 From 849e40b45284bc879eaa2c6bc1fe1ba2a15de6c3 Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 14:03:17 +0100 Subject: removed comments --- Wrappers/Python/ccpi/framework/framework.py | 160 +--------------------------- 1 file changed, 1 insertion(+), 159 deletions(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/ccpi/framework/framework.py b/Wrappers/Python/ccpi/framework/framework.py index 3982965..2453986 100755 --- a/Wrappers/Python/ccpi/framework/framework.py +++ b/Wrappers/Python/ccpi/framework/framework.py @@ -496,119 +496,6 @@ 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 __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) -# -# 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__ -# -# 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__ -# -# 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__ def __add__(self, other): return self.add(other) @@ -684,52 +571,7 @@ class DataContainer(object): kw = {'out':self} return self.divide(other, **kw) -# 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__ -# -# 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__ -# -# 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__ -# -# def __idiv__(self, other): -# return self.__itruediv__(other) -# 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__ + def __str__ (self, representation=False): repres = "" -- cgit v1.2.3 From 9ede79fb417bdbbb21e94045af16d62c366e35ee Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 14:54:09 +0100 Subject: added docstrings --- .../Python/ccpi/framework/BlockDataContainer.py | 95 +++++++--------------- 1 file changed, 28 insertions(+), 67 deletions(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/ccpi/framework/BlockDataContainer.py b/Wrappers/Python/ccpi/framework/BlockDataContainer.py index 060b130..20efbc3 100755 --- a/Wrappers/Python/ccpi/framework/BlockDataContainer.py +++ b/Wrappers/Python/ccpi/framework/BlockDataContainer.py @@ -112,92 +112,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) @@ -206,6 +159,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) -- cgit v1.2.3 From 9c4776d7da4a599755badf018292d54317a2817b Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 15:16:06 +0100 Subject: scaled function proximal conjugate uses out --- Wrappers/Python/ccpi/optimisation/functions/ScaledFunction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/ccpi/optimisation/functions/ScaledFunction.py b/Wrappers/Python/ccpi/optimisation/functions/ScaledFunction.py index 464b944..3fbb858 100755 --- a/Wrappers/Python/ccpi/optimisation/functions/ScaledFunction.py +++ b/Wrappers/Python/ccpi/optimisation/functions/ScaledFunction.py @@ -61,7 +61,8 @@ class ScaledFunction(object): if out is None: return self.scalar * self.function.proximal_conjugate(x/self.scalar, tau/self.scalar) else: - out.fill(self.scalar*self.function.proximal_conjugate(x/self.scalar, tau/self.scalar)) + self.function.proximal_conjugate(x/self.scalar, tau/self.scalar, out=out) + out *= self.scalar def grad(self, x): '''Alias of gradient(x,None)''' -- cgit v1.2.3 From 168f8b09c56b06ab21f09e0ff2906e4ac18bf9d6 Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 15:23:28 +0100 Subject: removed print --- Wrappers/Python/ccpi/framework/BlockDataContainer.py | 1 - 1 file changed, 1 deletion(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/ccpi/framework/BlockDataContainer.py b/Wrappers/Python/ccpi/framework/BlockDataContainer.py index 20efbc3..afdf617 100755 --- a/Wrappers/Python/ccpi/framework/BlockDataContainer.py +++ b/Wrappers/Python/ccpi/framework/BlockDataContainer.py @@ -98,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 -- cgit v1.2.3 From 3a24350a3c3e617434885728c0afed8c1891d3c4 Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 15:57:58 +0100 Subject: use PDHG class --- Wrappers/Python/wip/pdhg_TV_denoising.py | 52 +++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) (limited to 'Wrappers/Python') diff --git a/Wrappers/Python/wip/pdhg_TV_denoising.py b/Wrappers/Python/wip/pdhg_TV_denoising.py index f276b46..9bd5221 100755 --- a/Wrappers/Python/wip/pdhg_TV_denoising.py +++ b/Wrappers/Python/wip/pdhg_TV_denoising.py @@ -93,28 +93,58 @@ tau = 1/(sigma*normK**2) opt = {'niter':1000} opt1 = {'niter':1000, '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 + +steps = [timer()] +pdhgo.run(2000) +steps.append(timer()) +t1 = dt(steps) + +pdhg.run(2000) +steps.append(timer()) +t2 = dt(steps) -print("with memopt \n") +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() -plt.figure(figsize=(5,5)) +#plt.figure(figsize=(5,5)) +plt.subplot(1,3,3) plt.imshow(np.abs(res1.as_array()-res.as_array())) plt.colorbar() plt.show() -- cgit v1.2.3 From 18ec4ecfe286d04868ddcd2febd94affd77e3a57 Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Fri, 12 Apr 2019 16:12:50 +0100 Subject: added test for mixedL21Norm closes #231 --- Wrappers/Python/test/test_functions.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Wrappers/Python') 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)) -- cgit v1.2.3