Exemplo n.º 1
0
    def __init__(self, domain_geometry, bnd_cond='Neumann', **kwargs):
        '''creator
        
        :param domain_geometry: domain of the operator
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: :code:`SpaceChannel` or :code:`Channel`
        :type correlation: str, optional, default :code:`Channel`
        '''

        self.bnd_cond = bnd_cond
        self.correlation = kwargs.get(
            'correlation', SymmetrisedGradientOperator.CORRELATION_SPACE)

        tmp_gm = len(domain_geometry.geometries) * domain_geometry.geometries

        # Define FD operator. We need one geometry from the BlockGeometry of the domain
        self.FD = FiniteDifferenceOperator(domain_geometry.get_item(0),
                                           direction=0,
                                           bnd_cond=self.bnd_cond)

        if domain_geometry.shape[0] == 2:
            self.order_ind = [0, 2, 1, 3]
        else:
            self.order_ind = [0, 3, 6, 1, 4, 7, 2, 5, 8]

        super(SymmetrisedGradientOperator,
              self).__init__(domain_geometry=domain_geometry,
                             range_geometry=BlockGeometry(*tmp_gm))
Exemplo n.º 2
0
    def __init__(self,
                 domain_geometry,
                 method='forward',
                 bnd_cond='Neumann',
                 **kwargs):
        '''creator
        
        :param gm_domain: domain of the operator
        :type gm_domain: :code:`AcquisitionGeometry` or :code:`ImageGeometry`
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: optional, :code:`SpaceChannel` or :code:`Space`
        :type correlation: str, optional, default :code:`Space`
        '''

        # Consider pseudo 2D geometries with one slice, e.g., (1,voxel_num_y,voxel_num_x)
        domain_shape = []
        self.ind = []
        for i, size in enumerate(list(domain_geometry.shape)):
            if size != 1:
                domain_shape.append(size)
                self.ind.append(i)

        # Dimension of domain geometry
        self.ndim = len(domain_shape)

        # Default correlation for the gradient coupling
        self.correlation = kwargs.get('correlation', CORRELATION_SPACE)
        self.bnd_cond = bnd_cond

        # Call FiniteDifference operator
        self.method = method
        self.FD = FiniteDifferenceOperator(domain_geometry,
                                           direction=0,
                                           method=self.method,
                                           bnd_cond=self.bnd_cond)

        if self.correlation == CORRELATION_SPACE and 'channel' in domain_geometry.dimension_labels:
            self.ndim -= 1
            self.ind.remove(domain_geometry.dimension_labels.index('channel'))

        range_geometry = BlockGeometry(
            *[domain_geometry for _ in range(self.ndim)])

        #get voxel spacing, if not use 1s
        try:
            self.voxel_size_order = list(domain_geometry.spacing)
        except:
            self.voxel_size_order = [1] * len(domain_geometry.shape)

        super(Gradient_numpy, self).__init__(domain_geometry=domain_geometry,
                                             range_geometry=range_geometry)

        print("Initialised GradientOperator with numpy backend")
Exemplo n.º 3
0
    def __init__(self,
                 domain_geometry,
                 method='forward',
                 bnd_cond='Neumann',
                 **kwargs):
        '''creator
        
        :param gm_domain: domain of the operator
        :type gm_domain: :code:`AcquisitionGeometry` or :code:`ImageGeometry`
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: optional, :code:`SpaceChannel` or :code:`Space`
        :type correlation: str, optional, default :code:`Space`
        '''

        self.size_dom_gm = len(domain_geometry.shape)
        self.correlation = kwargs.get('correlation', CORRELATION_SPACE)
        self.bnd_cond = bnd_cond

        # Call FiniteDiff operator
        self.method = method
        self.FD = FiniteDifferenceOperator(domain_geometry,
                                           direction=0,
                                           method=self.method,
                                           bnd_cond=self.bnd_cond)

        self.ndim = len(domain_geometry.shape)
        self.ind = list(range(self.ndim))

        if self.correlation == CORRELATION_SPACE and 'channel' in domain_geometry.dimension_labels:
            self.ndim -= 1
            self.ind.remove(domain_geometry.dimension_labels.index('channel'))

        range_geometry = BlockGeometry(
            *[domain_geometry for _ in range(self.ndim)])

        #get voxel spacing, if not use 1s
        try:
            self.voxel_size_order = list(domain_geometry.spacing)
        except:
            self.voxel_size_order = [1] * len(domain_geometry.shape)

        super(Gradient_numpy, self).__init__(domain_geometry=domain_geometry,
                                             range_geometry=range_geometry)

        print("Initialised GradientOperator with numpy backend")
Exemplo n.º 4
0
    def test_FiniteDiffOperator(self):
        N, M = 200, 300

        ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N)
        u = ig.allocate('random_int')
        G = FiniteDifferenceOperator(ig, direction=0, bnd_cond='Neumann')
        print(type(u), u.as_array())
        print(G.direct(u).as_array())

        # Gradient Operator norm, for one direction should be close to 2
        numpy.testing.assert_allclose(G.norm(), numpy.sqrt(4), atol=0.1)

        M1, N1, K1 = 200, 300, 2
        ig1 = ImageGeometry(voxel_num_x=M1, voxel_num_y=N1, channels=K1)
        u1 = ig1.allocate('random_int')
        G1 = FiniteDifferenceOperator(ig1, direction=2, bnd_cond='Periodic')
        print(ig1.shape == u1.shape)
        print(G1.norm())
        numpy.testing.assert_allclose(G1.norm(), numpy.sqrt(4), atol=0.1)
Exemplo n.º 5
0
class SymmetrisedGradientOperator(LinearOperator):
    r'''Symmetrized Gradient Operator:  E: V -> W
        
        V : range of the Gradient Operator
        W : range of the Symmetrized Gradient          

        Example (2D): 
        
        .. math::
            v = (v1, v2) \\
        
            Ev = 0.5 * ( \nabla\cdot v + (\nabla\cdot c)^{T} ) \\
            
            \begin{matrix} 
                \partial_{y} v1 & 0.5 * (\partial_{x} v1 + \partial_{y} v2) \\
                0.5 * (\partial_{x} v1 + \partial_{y} v2) & \partial_{x} v2 
            \end{matrix}
                                                                  
    '''

    CORRELATION_SPACE = "Space"
    CORRELATION_SPACECHANNEL = "SpaceChannels"

    def __init__(self, domain_geometry, bnd_cond='Neumann', **kwargs):
        '''creator
        
        :param domain_geometry: domain of the operator
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: :code:`SpaceChannel` or :code:`Channel`
        :type correlation: str, optional, default :code:`Channel`
        '''

        self.bnd_cond = bnd_cond
        self.correlation = kwargs.get(
            'correlation', SymmetrisedGradientOperator.CORRELATION_SPACE)

        tmp_gm = len(domain_geometry.geometries) * domain_geometry.geometries

        # Define FD operator. We need one geometry from the BlockGeometry of the domain
        self.FD = FiniteDifferenceOperator(domain_geometry.get_item(0),
                                           direction=0,
                                           bnd_cond=self.bnd_cond)

        if domain_geometry.shape[0] == 2:
            self.order_ind = [0, 2, 1, 3]
        else:
            self.order_ind = [0, 3, 6, 1, 4, 7, 2, 5, 8]

        super(SymmetrisedGradientOperator,
              self).__init__(domain_geometry=domain_geometry,
                             range_geometry=BlockGeometry(*tmp_gm))

    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):

        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_FiniteDifference(self):
        print("test FiniteDifference")
        ##
        N, M = 2, 3
        numpy.random.seed(1)
        ig = ImageGeometry(N, M)
        Id = IdentityOperator(ig)

        FD = FiniteDifferenceOperator(ig, direction=0, bnd_cond='Neumann')
        u = FD.domain_geometry().allocate('random')

        res = FD.domain_geometry().allocate(ImageGeometry.RANDOM)
        FD.adjoint(u, out=res)
        w = FD.adjoint(u)

        self.assertNumpyArrayEqual(res.as_array(), w.as_array())

        res = Id.domain_geometry().allocate(ImageGeometry.RANDOM)
        Id.adjoint(u, out=res)
        w = Id.adjoint(u)

        self.assertNumpyArrayEqual(res.as_array(), w.as_array())
        self.assertNumpyArrayEqual(u.as_array(), w.as_array())

        G = GradientOperator(ig)

        u = G.range_geometry().allocate(ImageGeometry.RANDOM)
        res = G.domain_geometry().allocate()
        G.adjoint(u, out=res)
        w = G.adjoint(u)

        self.assertNumpyArrayEqual(res.as_array(), w.as_array())

        u = G.domain_geometry().allocate(ImageGeometry.RANDOM)
        res = G.range_geometry().allocate()
        G.direct(u, out=res)
        w = G.direct(u)
        self.assertBlockDataContainerEqual(res, w)

        # 2D
        M, N = 2, 3
        ig = ImageGeometry(voxel_num_x=M,
                           voxel_num_y=N,
                           voxel_size_x=0.1,
                           voxel_size_y=0.4)
        x = ig.allocate('random')

        labels = ["horizontal_y", "horizontal_x"]

        for i, dir in enumerate(labels):
            FD1 = FiniteDifferenceOperator(ig, direction=i)
            res1 = FD1.direct(x)
            res1b = FD1.adjoint(x)

            FD2 = FiniteDifferenceOperator(ig, direction=labels[i])
            res2 = FD2.direct(x)
            res2b = FD2.adjoint(x)

            numpy.testing.assert_almost_equal(res1.as_array(), res2.as_array())
            numpy.testing.assert_almost_equal(res1b.as_array(),
                                              res2b.as_array())
            print("Check 2D FiniteDiff for label {}".format(labels[i]))

        # 2D  + chan
        M, N, K = 2, 3, 4
        ig1 = ImageGeometry(voxel_num_x=M,
                            voxel_num_y=N,
                            channels=K,
                            voxel_size_x=0.1,
                            voxel_size_y=0.4)
        print(ig1.dimension_labels)
        x = ig1.allocate('random')

        labels = ["channel", "horizontal_y", "horizontal_x"]

        for i, dir in enumerate(labels):
            FD1 = FiniteDifferenceOperator(ig1, direction=i)
            res1 = FD1.direct(x)
            res1b = FD1.adjoint(x)

            FD2 = FiniteDifferenceOperator(ig1, direction=labels[i])
            res2 = FD2.direct(x)
            res2b = FD2.adjoint(x)

            numpy.testing.assert_almost_equal(res1.as_array(), res2.as_array())
            numpy.testing.assert_almost_equal(res1b.as_array(),
                                              res2b.as_array())
            print("Check for 2D chan for FiniteDiff label {}".format(
                labels[i]))
Exemplo n.º 7
0
    def __init__(self,
                 domain_geometry,
                 method='forward',
                 bnd_cond='Neumann',
                 **kwargs):
        '''creator
        
        :param gm_domain: domain of the operator
        :type gm_domain: :code:`AcquisitionGeometry` or :code:`ImageGeometry`
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: optional, :code:`SpaceChannel` or :code:`Space`
        :type correlation: str, optional, default :code:`Space`
        '''

        self.size_dom_gm = len(domain_geometry.shape)
        self.correlation = kwargs.get('correlation', CORRELATION_SPACE)
        self.bnd_cond = bnd_cond

        # Call FiniteDiff operator
        self.method = method
        self.FD = FiniteDifferenceOperator(domain_geometry,
                                           direction=0,
                                           method=self.method,
                                           bnd_cond=self.bnd_cond)

        if self.correlation == CORRELATION_SPACE:

            if domain_geometry.channels > 1:

                range_geometry = BlockGeometry(*[
                    domain_geometry for _ in range(domain_geometry.length - 1)
                ])

                if self.size_dom_gm == 4:
                    # 3D + Channel
                    expected_order = [
                        ImageGeometry.CHANNEL, ImageGeometry.VERTICAL,
                        ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X
                    ]

                else:
                    # 2D + Channel
                    expected_order = [
                        ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y,
                        ImageGeometry.HORIZONTAL_X
                    ]

                order = domain_geometry.get_order_by_label(
                    domain_geometry.dimension_labels, expected_order)

                self.ind = order[1:]

            else:
                # no channel info
                range_geometry = BlockGeometry(
                    *[domain_geometry for _ in range(domain_geometry.length)])
                if self.size_dom_gm == 3:
                    # 3D
                    expected_order = [
                        ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y,
                        ImageGeometry.HORIZONTAL_X
                    ]


#                    self.voxel_size_order = [domain_geometry.voxel_size_z, domain_geometry.voxel_size_y, domain_geometry.voxel_size_x ]

                else:
                    # 2D
                    expected_order = [
                        ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X
                    ]

                self.ind = domain_geometry.get_order_by_label(
                    domain_geometry.dimension_labels, expected_order)

        elif self.correlation == CORRELATION_SPACECHANNEL:

            if domain_geometry.channels > 1:
                range_geometry = BlockGeometry(
                    *[domain_geometry for _ in range(domain_geometry.length)])
                self.ind = range(domain_geometry.length)
            else:
                raise ValueError('No channels to correlate')

        self.voxel_size_order = domain_geometry.spacing

        super(Gradient_numpy, self).__init__(domain_geometry=domain_geometry,
                                             range_geometry=range_geometry)

        print("Initialised GradientOperator with numpy backend")
Exemplo n.º 8
0
class Gradient_numpy(LinearOperator):
    def __init__(self,
                 domain_geometry,
                 method='forward',
                 bnd_cond='Neumann',
                 **kwargs):
        '''creator
        
        :param gm_domain: domain of the operator
        :type gm_domain: :code:`AcquisitionGeometry` or :code:`ImageGeometry`
        :param bnd_cond: boundary condition, either :code:`Neumann` or :code:`Periodic`.
        :type bnd_cond: str, optional, default :code:`Neumann`
        :param correlation: optional, :code:`SpaceChannel` or :code:`Space`
        :type correlation: str, optional, default :code:`Space`
        '''

        self.size_dom_gm = len(domain_geometry.shape)
        self.correlation = kwargs.get('correlation', CORRELATION_SPACE)
        self.bnd_cond = bnd_cond

        # Call FiniteDiff operator
        self.method = method
        self.FD = FiniteDifferenceOperator(domain_geometry,
                                           direction=0,
                                           method=self.method,
                                           bnd_cond=self.bnd_cond)

        self.ndim = len(domain_geometry.shape)
        self.ind = list(range(self.ndim))

        if self.correlation == CORRELATION_SPACE and 'channel' in domain_geometry.dimension_labels:
            self.ndim -= 1
            self.ind.remove(domain_geometry.dimension_labels.index('channel'))

        range_geometry = BlockGeometry(
            *[domain_geometry for _ in range(self.ndim)])

        #get voxel spacing, if not use 1s
        try:
            self.voxel_size_order = list(domain_geometry.spacing)
        except:
            self.voxel_size_order = [1] * len(domain_geometry.shape)

        super(Gradient_numpy, self).__init__(domain_geometry=domain_geometry,
                                             range_geometry=range_geometry)

        print("Initialised GradientOperator with numpy backend")

    def direct(self, x, out=None):
        if out is not None:
            for i, axis_index in enumerate(self.ind):
                self.FD.direction = axis_index
                self.FD.voxel_size = self.voxel_size_order[axis_index]
                self.FD.direct(x, out=out[i])
        else:
            tmp = self.range_geometry().allocate()
            for i, axis_index in enumerate(self.ind):
                self.FD.direction = axis_index
                self.FD.voxel_size = self.voxel_size_order[axis_index]
                tmp.get_item(i).fill(self.FD.direct(x))
            return tmp

    def adjoint(self, x, out=None):

        if out is not None:
            tmp = self.domain_geometry().allocate()
            for i, axis_index in enumerate(self.ind):
                self.FD.direction = axis_index
                self.FD.voxel_size = self.voxel_size_order[axis_index]
                self.FD.adjoint(x.get_item(i), out=tmp)
                if i == 0:
                    out.fill(tmp)
                else:
                    out += tmp
        else:
            tmp = self.domain_geometry().allocate()
            for i, axis_index in enumerate(self.ind):
                self.FD.direction = axis_index
                self.FD.voxel_size = self.voxel_size_order[axis_index]
                tmp += self.FD.adjoint(x.get_item(i))
            return tmp