Example #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)
Example #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)
Example #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)
Example #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))
Example #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), )
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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)
Example #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))
Example #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)
Example #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)
Example #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)
Example #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
Example #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)
Example #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)
Example #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)
Example #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)