Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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))
Пример #5
0
    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), )
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
    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)
Пример #11
0
    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)
Пример #12
0
    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)
Пример #13
0
    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)
Пример #14
0
    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)
Пример #15
0
    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)
Пример #16
0
    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)
Пример #17
0
    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)
Пример #18
0
    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)
Пример #19
0
    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)
Пример #20
0
    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)
Пример #21
0
    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)
Пример #22
0
    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))
Пример #23
0
    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)
Пример #24
0
    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)
Пример #25
0
    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)
Пример #26
0
    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
Пример #27
0
    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)
Пример #28
0
    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)
Пример #29
0
    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)
Пример #30
0
    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)