def derivative(self, displacement): """Derivative of the operator at ``displacement``. Parameters ---------- displacement : `domain` `element-like` Point at which the derivative is computed. Returns ------- derivative : `PointwiseInner` The derivative evaluated at ``displacement``. """ # To implement the complex case we need to be able to embed the real # vector field space into the range of the gradient. Issue #59. if not self.range.is_rn: raise NotImplementedError('derivative not implemented for complex ' 'spaces.') displacement = self.domain.element(displacement) # TODO: allow users to select what method to use here. grad = Gradient(domain=self.range, method='central', pad_mode='symmetric') grad_templ = grad(self.template) def_grad = self.domain.element( [_linear_deform(gf, displacement) for gf in grad_templ]) return PointwiseInner(self.domain, def_grad)
def derivative(self, displacement): """Derivative of the operator at ``displacement``. Parameters ---------- displacement : `domain` `element-like` Point at which the derivative is computed. Returns ------- derivative : `PointwiseInner` The derivative evaluated at ``displacement``. Test derivative TBC >>> import odl >>> import operators >>> import deform >>> X = odl.uniform_discr([-1, -1], [1, 1], [10, 10]) >>> Y_aff = odl.rn(6) >>> parameters = Y_aff.element([.1, .1, .1, .1, .1, .1]) >>> embedding = operators.Embedding_Affine(Y_aff, X.tangent_bundle) >>> displacement = embedding(parameters) >>> T = deform.LinDeformFixedDispAffine(displacement, parameters) >>> x = odl.phantom.white_noise(T.domain) >>> y = odl.phantom.white_noise(T.range) >>> print(T(x).inner(y)/x.inner(T.adjoint(y))) >>> x = odl.phantom.shepp_logan(T.domain) >>> y = odl.phantom.shepp_logan(T.domain) >>> print(T(x).inner(y)/x.inner(T.adjoint(y))) """ # To implement the complex case we need to be able to embed the real # vector field space into the range of the gradient. Issue #59. if not self.range.is_real: raise NotImplementedError('derivative not implemented for complex ' 'spaces.') displacement = self.domain.element(displacement) image_pts = self.template.space.points() for i, vi in enumerate(displacement): image_pts[:, i] += vi.asarray().ravel() space = self.template.space if space.ndim == 1: x = np.unique(space.points()[:, 0]) itemplate = interpolate.CubicSpline(x, self.template) ptsx = image_pts[:, 0] dIx = itemplate(ptsx, nu=1) grad = space.tangent_bundle.element() grad[0] = dIx.reshape(space.shape) elif space.ndim == 2: x = np.unique(space.points()[:, 0]) y = np.unique(space.points()[:, 1]) itemplate = interpolate.RectBivariateSpline(x, y, self.template, kx=2, ky=2) ptsx = image_pts[:, 0] ptsy = image_pts[:, 1] dIx = itemplate(ptsx, ptsy, dx=1, dy=0, grid=False) dIy = itemplate(ptsx, ptsy, dx=0, dy=1, grid=False) def_grad = space.tangent_bundle.element() def_grad[0] = dIx.reshape(space.shape) def_grad[1] = dIy.reshape(space.shape) else: raise NotImplementedError('Interpolation not implemented ' 'for this dimension.') return PointwiseInner(self.domain, def_grad)