diff options
author | Edoardo Pasca <edo.paskino@gmail.com> | 2019-03-28 11:58:14 +0000 |
---|---|---|
committer | Edoardo Pasca <edo.paskino@gmail.com> | 2019-03-28 11:58:14 +0000 |
commit | a2c82a21f4cc498fd8f7cd8a8a1256f10524df14 (patch) | |
tree | adec69beb6974a98dcfc3c94ca949cb502f9d6c9 /Wrappers | |
parent | 1f68f4053c0b72f34168edc07e76c76aaa71ee96 (diff) | |
download | framework-a2c82a21f4cc498fd8f7cd8a8a1256f10524df14.tar.gz framework-a2c82a21f4cc498fd8f7cd8a8a1256f10524df14.tar.bz2 framework-a2c82a21f4cc498fd8f7cd8a8a1256f10524df14.tar.xz framework-a2c82a21f4cc498fd8f7cd8a8a1256f10524df14.zip |
BlockOperator checks compatibility of Operators
Diffstat (limited to 'Wrappers')
-rwxr-xr-x | Wrappers/Python/ccpi/optimisation/operators/BlockOperator.py | 37 | ||||
-rw-r--r-- | Wrappers/Python/test/test_BlockOperator.py | 4 |
2 files changed, 27 insertions, 14 deletions
diff --git a/Wrappers/Python/ccpi/optimisation/operators/BlockOperator.py b/Wrappers/Python/ccpi/optimisation/operators/BlockOperator.py index 3679136..323efcd 100755 --- a/Wrappers/Python/ccpi/optimisation/operators/BlockOperator.py +++ b/Wrappers/Python/ccpi/optimisation/operators/BlockOperator.py @@ -14,15 +14,22 @@ from ccpi.optimisation.operators.BlockScaledOperator import BlockScaledOperator from ccpi.framework import BlockGeometry class BlockOperator(Operator): - '''Class to hold a block operator + '''A Block matrix containing Operators + + The Block Framework is a generic strategy to treat variational problems in the + following form: + + .. math:: + + min Regulariser + Fidelity - Class to hold a number of Operators in a block. - User may specify the shape of the block, by default is a row vector BlockOperators have a generic shape M x N, and when applied on an Nx1 BlockDataContainer, will yield and Mx1 BlockDataContainer. Notice: BlockDatacontainer are only allowed to have the shape of N x 1, with N rows and 1 column. + + User may specify the shape of the block, by default is a row vector Operators in a Block are required to have the same domain column-wise and the same range row-wise. @@ -36,8 +43,8 @@ class BlockOperator(Operator): Do not include the `self` parameter in the ``Args`` section. Args: - vararg (Operator): Operators in the block. - shape (:obj:`tuple`, optional): If shape is passed the Operators in + :param: vararg (Operator): Operators in the block. + :param: shape (:obj:`tuple`, optional): If shape is passed the Operators in vararg are considered input in a row-by-row fashion. Shape and number of Operators must match. @@ -66,12 +73,12 @@ class BlockOperator(Operator): rows, cols = self.shape compatible = True for col in range(cols): - row_compatible = True + column_compatible = True for row in range(1,rows): dg0 = self.get_item(row-1,col).domain_geometry() dg1 = self.get_item(row,col).domain_geometry() - row_compatible = dg0.__dict__ == dg1.__dict__ and row_compatible - compatible = compatible and row_compatible + column_compatible = dg0.__dict__ == dg1.__dict__ and column_compatible + compatible = compatible and column_compatible return compatible def row_wise_compatible(self): @@ -79,16 +86,16 @@ class BlockOperator(Operator): rows, cols = self.shape compatible = True for row in range(rows): - column_compatible = True + row_compatible = True for col in range(1,cols): dg0 = self.get_item(row,col-1).range_geometry() dg1 = self.get_item(row,col).range_geometry() - column_compatible = dg0.__dict__ == dg1.__dict__ and column_compatible - print ("column_compatible" , column_compatible, dg0.shape, dg1.shape) - compatible = compatible and column_compatible + row_compatible = dg0.__dict__ == dg1.__dict__ and row_compatible + compatible = compatible and row_compatible return compatible def get_item(self, row, col): + '''returns the Operator at specified row and col''' if row > self.shape[0]: raise ValueError('Requested row {} > max {}'.format(row, self.shape[0])) if col > self.shape[1]: @@ -190,6 +197,11 @@ class BlockOperator(Operator): return type(self)(*self.operators, shape=shape) def domain_geometry(self): + '''returns the domain of the BlockOperator + + If the shape of the BlockOperator is (N,1) the domain is a ImageGeometry or AcquisitionGeometry. + Otherwise it is a BlockGeometry. + ''' if self.shape[1] == 1: # column BlockOperator return self[0].domain_geometry() @@ -199,6 +211,7 @@ class BlockOperator(Operator): shape=shape) def range_geometry(self): + '''returns the range of the BlockOperator''' shape = (self.shape[1], 1) return BlockGeometry(*[el.range_geometry() for el in self.operators], shape=shape) diff --git a/Wrappers/Python/test/test_BlockOperator.py b/Wrappers/Python/test/test_BlockOperator.py index c042d04..4eb84bb 100644 --- a/Wrappers/Python/test/test_BlockOperator.py +++ b/Wrappers/Python/test/test_BlockOperator.py @@ -67,8 +67,8 @@ class TestBlockOperator(unittest.TestCase): x = [ g.allocate() for g in ig ] ops = [ TestOperator(g, range=r) for g,r in zip(ig, rg0) ] ops += [ TestOperator(g, range=r) for g,r in zip(ig, rg1) ] - print (len(ops)) - K = BlockOperator(*ops) + + K = BlockOperator(*ops, shape=(2,3)) print ("K col comp? " , K.column_wise_compatible()) print ("K row comp? " , K.row_wise_compatible()) for op in ops: |