def test_axpby2(self): # test axpby with BlockDataContainer and DataContainer ig0 = ImageGeometry(2, 3, 4) # ig1 = ImageGeometry(2,3,5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) data1 = ig0.allocate(2) # data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0, data2) # cp1 = BlockDataContainer(data1,data3) out = cp0 * 0. - 10 cp0.axpby(3, -2, data1, out) # operation should be [ 3 * -1 + (-2) * 2 , 3 * 1 + (-2) * 2 ] # output should be [ -7 , -1 ] res0 = ig0.allocate(-7) res2 = ig0.allocate(-1) res = BlockDataContainer(res0, res2) self.assertBlockDataContainerEqual(out, res)
def test_axpby4(self): # test axpby with nested BlockDataContainer ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) # data1 = ig0.allocate(2) data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0, data2) cp1 = BlockDataContainer(cp0 * 0. + [2, -2], data3) out = cp1 * 0. cp2 = out + [1, 3] cp2.axpby(3, -2, cp1, out, num_threads=4) # output should be [ [ -1 , 7 ] , 3] res0 = ig0.allocate(-1) res2 = ig0.allocate(7) res3 = ig1.allocate(3) res = BlockDataContainer(BlockDataContainer(res0, res2), res3) self.assertBlockDataContainerEqual(out, res)
def test_mixedL12Norm(self): numpy.random.seed(1) M, N, K = 2, 3, 5 ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N) u1 = ig.allocate('random') u2 = ig.allocate('random') U = BlockDataContainer(u1, u2, shape=(2, 1)) # Define no scale and scaled f_no_scaled = MixedL21Norm() f_scaled = 1 * MixedL21Norm() # call a1 = f_no_scaled(U) a2 = f_scaled(U) self.assertNumpyArrayAlmostEqual(a1, a2) tmp = [el**2 for el in U.containers] self.assertBlockDataContainerEqual(BlockDataContainer(*tmp), U.power(2)) z1 = f_no_scaled.proximal_conjugate(U, 1) u3 = ig.allocate('random') u4 = ig.allocate('random') z3 = BlockDataContainer(u3, u4, shape=(2, 1)) f_no_scaled.proximal_conjugate(U, 1, out=z3) self.assertBlockDataContainerAlmostEqual(z3, z1, decimal=5)
def direct(self, x, out=None): '''Returns E(v)''' if out is None: tmp = [] for i in range(self.domain_geometry().shape[0]): for j in range(x.shape[0]): self.FD.direction = i tmp.append(self.FD.adjoint(x.get_item(j))) tmp1 = [tmp[i] for i in self.order_ind] res = [0.5 * sum(x) for x in zip(tmp, tmp1)] return BlockDataContainer(*res) else: ind = 0 for i in range(self.domain_geometry().shape[0]): for j in range(x.shape[0]): self.FD.direction = i self.FD.adjoint(x.get_item(j), out=out[ind]) ind += 1 out1 = BlockDataContainer(*[out[i] for i in self.order_ind]) out.fill(0.5 * (out + out1))
def adjoint(self, x, out=None): '''Adjoint operation for the BlockOperator BlockOperator may contain both LinearOperator and Operator This method exists in BlockOperator as it is not known what type of Operator it will contain. BlockOperator work on BlockDataContainer, but they will work on DataContainers and inherited classes by simple wrapping the input in a BlockDataContainer of shape (1,1) Raises: ValueError if the contained Operators are not linear ''' if not self.is_linear(): raise ValueError('Not all operators in Block are linear.') if not isinstance(x, BlockDataContainer): x_b = BlockDataContainer(x) else: x_b = x shape = self.get_output_shape(x_b.shape, adjoint=True) if out is None: res = [] for col in range(self.shape[1]): for row in range(self.shape[0]): if row == 0: prod = self.get_item(row, col).adjoint(x_b.get_item(row)) else: prod += self.get_item(row, col).adjoint(x_b.get_item(row)) res.append(prod) if self.shape[1] == 1: # the output is a single DataContainer, so we can take it out return res[0] else: return BlockDataContainer(*res, shape=shape) else: for col in range(self.shape[1]): for row in range(self.shape[0]): if row == 0: if issubclass(out.__class__, DataContainer) or \ ( has_sirf and issubclass(out.__class__, SIRFDataContainer) ): self.get_item(row, col).adjoint(x_b.get_item(row), out=out) else: op = self.get_item(row, col) self.get_item(row, col).adjoint(x_b.get_item(row), out=out.get_item(col)) else: if issubclass(out.__class__, DataContainer) or \ ( has_sirf and issubclass(out.__class__, SIRFDataContainer) ): out += self.get_item(row, col).adjoint( x_b.get_item(row)) else: a = out.get_item(col) a += self.get_item(row, col).adjoint( x_b.get_item(row), )
def test_unary_conjugate2(self): # test axpby with nested BlockDataContainer data0 = self.ig0.allocate(4+3j, dtype=numpy.complex64) data2 = self.ig1.allocate(1-1j, dtype=numpy.complex64) # data1 = ig0.allocate(2) # data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0,data2) cp0.conjugate(out=cp0) res = BlockDataContainer(self.ig0.allocate(4-3j, dtype=numpy.complex64), self.ig1.allocate(1+1j, dtype=numpy.complex64)) self.assertBlockDataContainerAlmostEqual(res, cp0)
def test_unary_sqrt2(self): # test axpby with nested BlockDataContainer data0 = self.ig0.allocate(4) data2 = self.ig1.allocate(8) # data1 = ig0.allocate(2) # data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0,data2) cp0.sqrt(out=cp0) res = BlockDataContainer(self.ig0.allocate(numpy.sqrt(4)), self.ig1.allocate(numpy.sqrt(8))) self.assertBlockDataContainerAlmostEqual(res, cp0)
def skiptest_BlockDataContainerShape(self): ig0 = ImageGeometry(12, 42, 55, 32) ig1 = ImageGeometry(12, 42, 55, 32) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0, data1) cp1 = BlockDataContainer(data2, data3) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp0.T.shape == transpose_shape)
def test_axpby_ab_blockdc(self): # test axpby between BlockDataContainers, with a and b as a blockdatacontainer ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) data1 = ig0.allocate(2) data3 = ig0.allocate(3) a1 = ig0.allocate(3) a2 = ig0.allocate(2) b1 = ig0.allocate(-2) b2 = ig0.allocate(-3) cp0 = BlockDataContainer(data0, data2) cp1 = BlockDataContainer(data1, data3) a = BlockDataContainer(a1, a2) b = BlockDataContainer(b1, b2) out = cp0 * 0. - 10 cp0.axpby(a, b, cp1, out, num_threads=4) # operation should be [ 3 * -1 + (-2) * 2 , 2 * 1 + (-3) * 3 ] # output should be [ -7 , -7 ] res0 = ig0.allocate(-7) res2 = ig0.allocate(-7) res = BlockDataContainer(res0, res2) self.assertBlockDataContainerEqual(out, res)
def proximal_conjugate(self, x, tau, out = None): r"""Proximal operator of the convex conjugate of BlockFunction at x: .. math:: \mathrm{prox}_{\tau F^{*}}(x) = (\mathrm{prox}_{\tau f^{*}_{i}}(x^{*}_{i}))_{i=1}^{m} Parameter: x : BlockDataContainer and must have as many rows as self.length """ if self.length != x.shape[0]: raise ValueError('BlockFunction and BlockDataContainer have incompatible size') if out is not None: if isinstance(tau, Number): for i in range(self.length): self.functions[i].proximal_conjugate(x.get_item(i), tau, out=out.get_item(i)) else: for i in range(self.length): self.functions[i].proximal_conjugate(x.get_item(i), tau.get_item(i),out=out.get_item(i)) else: out = [None]*self.length if isinstance(tau, Number): for i in range(self.length): out[i] = self.functions[i].proximal_conjugate(x.get_item(i), tau) else: for i in range(self.length): out[i] = self.functions[i].proximal_conjugate(x.get_item(i), tau.get_item(i)) return BlockDataContainer(*out)
def adjoint(self, x, out=None): if out is None: tmp = [None] * self.domain_geometry().shape[0] i = 0 for k in range(self.domain_geometry().shape[0]): tmp1 = 0 for j in range(self.domain_geometry().shape[0]): self.FD.direction = j tmp1 += self.FD.direct(x[i]) i += 1 tmp[k] = tmp1 return BlockDataContainer(*tmp) else: tmp = self.domain_geometry().allocate() i = 0 for k in range(self.domain_geometry().shape[0]): tmp1 = 0 for j in range(self.domain_geometry().shape[0]): self.FD.direction = j self.FD.direct(x[i], out=tmp[j]) i += 1 tmp1 += tmp[j] out[k].fill(tmp1)
def test_binary_add(self): # test axpby with nested BlockDataContainer cp0 = self.cp0 cp1 = cp0 * 0 cp0.add(1, out=cp1) res = BlockDataContainer(self.ig0.allocate(0), self.ig1.allocate(2)) self.assertBlockDataContainerEqual(cp1, res)
def test_binary_power(self): # test axpby with nested BlockDataContainer cp0 = self.cp0 cp1 = cp0 * 0 cp0.power(2 , out = cp1) res = BlockDataContainer(self.ig0.allocate((-1)**2), self.ig1.allocate((1)**2)) self.assertBlockDataContainerAlmostEqual(cp1, res)
def test_binary_divide(self): # test axpby with nested BlockDataContainer cp0 = self.cp0 cp1 = cp0 * 0 cp0.divide(2 , out = cp1) res = BlockDataContainer(self.ig0.allocate(-1/2), self.ig1.allocate(1/2)) self.assertBlockDataContainerAlmostEqual(cp1, res)
def test_binary_subtract(self): # test axpby with nested BlockDataContainer cp0 = self.cp0 cp1 = cp0 * 0 cp0.subtract(1 , out = cp1) res = BlockDataContainer(self.ig0.allocate(-1-1), self.ig1.allocate(1-1)) self.assertBlockDataContainerEqual(cp1, res)
def test_binary_minimum(self): # test axpby with nested BlockDataContainer cp0 = self.cp0 cp1 = cp0 * 10 cp0.minimum(0, out=cp1) res = BlockDataContainer(self.ig0.allocate(-1), self.ig1.allocate(0)) self.assertBlockDataContainerAlmostEqual(cp1, res)
def test_BlockDataContainer_with_SIRF_DataContainer_subtract(self): os.chdir(self.cwd) image1 = pet.ImageData('emission.hv') image2 = pet.ImageData('emission.hv') image1.fill(2) image2.fill(1) print(image1.shape, image2.shape) bdc = BlockDataContainer(image1, image2) bdc1 = bdc.subtract(1.) image1.fill(1) image2.fill(0) bdc = BlockDataContainer(image1, image2) self.assertBlockDataContainerEqual(bdc, bdc1)
def test_BlockDataContainer_with_SIRF_DataContainer_multiply(self): os.chdir(self.cwd) image1 = pet.ImageData('emission.hv') image2 = pet.ImageData('emission.hv') image1.fill(1.) image2.fill(2.) print(image1.shape, image2.shape) tmp = image1.multiply(1.) numpy.testing.assert_array_equal(image1.as_array(), tmp.as_array()) tmp = image2.multiply(1.) numpy.testing.assert_array_equal(image2.as_array(), tmp.as_array()) # image.fill(1.) bdc = BlockDataContainer(image1, image2) bdc1 = bdc.multiply(1.) self.assertBlockDataContainerEqual(bdc, bdc1)
def skiptest_BlockDataContainerShapeArithmetic(self): print ("test block data container") ig0 = ImageGeometry(2,3,4) ig1 = ImageGeometry(2,3,4) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0,data1) #cp1 = BlockDataContainer(data2,data3) cp1 = cp0 + 1 self.assertTrue(cp1.shape == cp0.shape) cp1 = cp0.T + 1 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T - 1 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = (cp0.T + 1)*2 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = (cp0.T + 1)/2 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.power(2.2) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.maximum(3) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.abs() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.sign() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.sqrt() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.conjugate() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape)
def sum_abs_col(self): res = [] for row in range(self.shape[0]): for col in range(self.shape[1]): if col == 0: prod = self.get_item(row, col).sum_abs_col() else: prod += self.get_item(row, col).sum_abs_col() res.append(prod) return BlockDataContainer(*res)
def test_ScaledBlockOperatorScalarList(self): ig = [ ImageGeometry(2,3) , \ #ImageGeometry(10,20,30) , \ ImageGeometry(2,3 ) ] x = [g.allocate() for g in ig] ops = [IdentityOperator(g) for g in ig] # test limit as non Scaled scalar = numpy.asarray([1 for _ in x]) k = BlockOperator(*ops) K = scalar * k val = 1 X = BlockDataContainer(*x) + val Y = K.T.direct(X) self.assertTrue(Y.shape == (1, 1)) zero = numpy.zeros(X.get_item(0).shape) xx = numpy.asarray([val for _ in x]) numpy.testing.assert_array_equal( Y.get_item(0).as_array(), (scalar * xx).sum() + zero) scalar = numpy.asarray([i + 1 for i, el in enumerate(x)]) #scalar = numpy.asarray([6,0]) k = BlockOperator(*ops) K = scalar * k X = BlockDataContainer(*x) + val Y = K.T.direct(X) self.assertTrue(Y.shape == (1, 1)) zero = numpy.zeros(X.get_item(0).shape) xx = numpy.asarray([val for _ in x]) numpy.testing.assert_array_equal( Y.get_item(0).as_array(), (scalar * xx).sum() + zero)
def test_ScaledBlockOperatorSingleScalar(self): ig = [ ImageGeometry(10,20,30) , \ ImageGeometry(10,20,30) , \ ImageGeometry(10,20,30) ] x = [g.allocate() for g in ig] ops = [IdentityOperator(g) for g in ig] val = 1 # test limit as non Scaled scalar = 1 k = BlockOperator(*ops) K = scalar * k X = BlockDataContainer(*x) + val Y = K.T.direct(X) self.assertTrue(Y.shape == (1, 1)) zero = numpy.zeros(X.get_item(0).shape) xx = numpy.asarray([val for _ in x]) numpy.testing.assert_array_equal( Y.get_item(0).as_array(), ((scalar * xx).sum() + zero)) scalar = 0.5 k = BlockOperator(*ops) K = scalar * k X = BlockDataContainer(*x) + 1 Y = K.T.direct(X) self.assertTrue(Y.shape == (1, 1)) zero = numpy.zeros(X.get_item(0).shape) numpy.testing.assert_array_equal( Y.get_item(0).as_array(), scalar * (len(x) + zero))
def test_axpby(self): # test axpby between BlockDataContainers ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) data1 = ig0.allocate(2) data3 = ig0.allocate(3) cp0 = BlockDataContainer(data0, data2) cp1 = BlockDataContainer(data1, data3) out = cp0 * 0. - 10 cp0.axpby(3, -2, cp1, out, num_threads=4) # operation should be [ 3 * -1 + (-2) * 2 , 3 * 1 + (-2) * 3 ] # output should be [ -7 , -3 ] res0 = ig0.allocate(-7) res2 = ig0.allocate(-3) res = BlockDataContainer(res0, res2) self.assertBlockDataContainerEqual(out, res)
def test_BlockDataContainer_fill(self): ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0, data1) #cp1 = BlockDataContainer(data2,data3) cp2 = BlockDataContainer(data0 + 1, data1 + 1) data0.fill(data2) self.assertNumpyArrayEqual(data0.as_array(), data2.as_array()) data0 = ImageData(geometry=ig0) cp0.fill(cp2) self.assertBlockDataContainerEqual(cp0, cp2)
def test_BlockDataContainer_with_SIRF_DataContainer_add(self): os.chdir(self.cwd) image1 = pet.ImageData('emission.hv') image2 = pet.ImageData('emission.hv') image1.fill(0) image2.fill(1) print(image1.shape, image2.shape) tmp = image1.add(1.) numpy.testing.assert_array_equal(image2.as_array(), tmp.as_array()) tmp = image2.subtract(1.) numpy.testing.assert_array_equal(image1.as_array(), tmp.as_array()) bdc = BlockDataContainer(image1, image2) bdc1 = bdc.add(1.) image1.fill(1) image2.fill(2) bdc = BlockDataContainer(image1, image2) self.assertBlockDataContainerEqual(bdc, bdc1)
def setUp(self): ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig1.allocate(1) # data1 = ig0.allocate(2) # data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0, data2) self.ig0 = ig0 self.ig1 = ig1 self.cp0 = cp0
def test_BlockDataContainer_fill(self): print ("test block data container") ig0 = ImageGeometry(2,3,4) ig1 = ImageGeometry(2,3,5) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0,data1) #cp1 = BlockDataContainer(data2,data3) cp2 = BlockDataContainer(data0+1, data1+1) data0.fill(data2) self.assertNumpyArrayEqual(data0.as_array(), data2.as_array()) data0 = ImageData(geometry=ig0) for el,ot in zip(cp0, cp2): print (el.shape, ot.shape) cp0.fill(cp2) self.assertBlockDataContainerEqual(cp0, cp2)
def test_NestedBlockDataContainer(self): ig0 = ImageGeometry(2,3,4) ig1 = ImageGeometry(2,3,5) data0 = ig0.allocate(0) data2 = ig0.allocate(1) cp0 = BlockDataContainer(data0,data2) #cp1 = BlockDataContainer(data2,data3) nested = BlockDataContainer(cp0, data2, data2) out = BlockDataContainer(BlockDataContainer(data0 , data0), data0, data0) nested.divide(data2,out=out) self.assertBlockDataContainerEqual(out, nested)
def sum_abs_row(self): res = [] for row in range(self.shape[0]): for col in range(self.shape[1]): if col == 0: prod = self.get_item(row, col).sum_abs_row() else: prod += self.get_item(row, col).sum_abs_row() res.append(prod) if self.shape[1] == 1: tmp = sum(res) return ImageData(tmp) else: return BlockDataContainer(*res)
def allocate(self, value=0, dimension_labels=None, **kwargs): max_value = kwargs.get('max_value', 100) symmetry = kwargs.get('symmetry', False) containers = [ geom.allocate(value, max_value=max_value) for geom in self.geometries ] if symmetry == True: # for 2x2 # [ ig11, ig12\ # ig21, ig22] # Row-wise Order if len(containers) == 4: containers[1] = containers[2] # for 3x3 # [ ig11, ig12, ig13\ # ig21, ig22, ig23\ # ig31, ig32, ig33] elif len(containers) == 9: containers[1] = containers[3] containers[2] = containers[6] containers[5] = containers[7] # for 4x4 # [ ig11, ig12, ig13, ig14\ # ig21, ig22, ig23, ig24\ # ig31, ig32, ig33, ig34 # ig41, ig42, ig43, ig44] elif len(containers) == 16: containers[1] = containers[4] containers[2] = containers[8] containers[3] = containers[12] containers[6] = containers[9] containers[7] = containers[10] containers[11] = containers[15] return BlockDataContainer(*containers)