def test_odl_operator_test(self):

        # Volume geometry parameters
        vol_shape = (20, 21, 22)
        vox_size = (1, 1, 1)
        ndim = len(vol_shape)
        volSize = [vol_shape[n] * vox_size[n] for n in range(ndim)]

        # Define continuous image space, typically a 2D or 3D volume
        volSpace = odl.L2(odl.Cuboid([0 for _ in range(ndim)], volSize))

        # Discretize the image space
        volDisc = odl.l2_uniform_discretization(volSpace, vol_shape)

        # Create data
        volVec = volDisc.element(1)

        # Create gradient operator
        grad = Gradient(volDisc, vox_size, edge_order=1, zero_padding=True)

        ot = OperatorTest(grad, operator_norm=1)
        ot.adjoint()
    def test_gradient_operator(self):
        # Volume geometry parameters
        # volGeom = Geometry(volume_shape=(2,3,4), voxel_size=(1,2,3))
        # vol_shape = (10, 11, 12)
        vol_shape = (20, 21, 22)
        v, v1, v2 = np.meshgrid(np.linspace(0, 1, vol_shape[1]),
                                np.linspace(0, 1, vol_shape[0]),
                                np.linspace(0, 1, vol_shape[2]))
        v = 1 + np.sin(np.pi*np.sqrt(v**2 + v1**2 + v2**2) + np.pi/2)
        v2 = 1 + np.sin(np.pi*np.sqrt(v**2 + v1**2 + v2**2) + np.pi/3)

        def set_surface_pixel_to_zero(vol, npixel):
            if npixel == 0:
                return
            nn = npixel
            vol[:nn, :, :] = 0
            vol[-nn:, :, :] = 0
            vol[:, :nn, :] = 0
            vol[:, -nn:, :] = 0
            vol[:, :, :nn] = 0
            vol[:, :, -nn:] = 0

        set_surface_pixel_to_zero(v, 0)
        set_surface_pixel_to_zero(v2, 0)

        vox_size = (1, 1, 1)
        ndim = len(vol_shape)
        volSize = [vol_shape[n] * vox_size[n] for n in range(ndim)]

        # Define continuous image space, typically a 2D or 3D volume
        volSpace = odl.L2(odl.Cuboid([0 for _ in range(ndim)], volSize))

        # Discretize the image space
        volDisc = odl.l2_uniform_discretization(volSpace, vol_shape)

        # Create data
        volVec = volDisc.element(v)

        # Target space: product space of image space
        volVec2 = volDisc.element(v2)
        gradDisc = odl.ProductSpace(volDisc, ndim)
        gradVec = gradDisc.element([volVec2, volVec2, volVec2])

        print('volDisc.norm:', volVec.norm()**2)
        print('gradDisc.norm:', gradVec.norm()**2)

        # Create gradient operator
        print('INITIALIZE GRADIENT OPERATOR:')
        grad = Gradient(volDisc, vox_size, edge_order=2, zero_padding=True)
        print(' op domain: ', grad.domain)
        print(' op range: ', grad.range)
        print(' op adjoint domain: ', grad.adjoint.domain)
        print(' op adjoint range: ', grad.adjoint.range)

        q = grad(volVec)
        p = grad.adjoint(gradVec)
        print('INNER PRODUCT:')
        print(' <Af,   g>', gradVec.inner(q))
        print(' < f, A*g>', volVec.inner(p))
        print(' Diff', gradVec.inner(q) -volVec.inner(p))
        s = 0
        v = volVec.asarray()
        for axis in range(ndim):
            slice1 = [slice(None)] * ndim
            slice2 = [slice(None)] * ndim
            slice1[axis] = 0
            slice2[axis] = -1

            vv = gradVec[axis].asarray()
            s1 = np.sum(v[slice1] * vv[slice1])
            s2 = np.sum(v[slice2] * vv[slice2])
            s += s1 - s2
            print(s1, s2, s1-s2, s)


        print( 'Surface contribution:', s)

        # print(type(gradDisc), type(gradDisc[0]))
        print('\nProduct space')
        print('gradDisc:', type(gradDisc))
        print('gradVec:', type(gradVec))
        print('q       :', type(q))
        print('gradDisc[0]:', type(gradDisc[0]))
        print('q[0]       :', type(q[0]))
        q2 = q.copy()

        # Create divergence operator
        div = Divergence(volDisc, vox_size, zero_padding=True)
        v = div(q)