# This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Copyright(C) 2013-2018 Max-Planck-Society # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik # and financially supported by the Studienstiftung des deutschen Volkes. from __future__ import absolute_import, division, print_function from .. import dobj from ..compat import * from ..domain_tuple import DomainTuple from ..field import Field from ..utilities import hartley, infer_space from .linear_operator import LinearOperator class QHTOperator(LinearOperator): """ Does a Hartley transform on LogRGSpace This operator takes a field on a LogRGSpace and transforms it according to the Hartley transform. The zero modes are not transformed because they are infinitely far away. Parameters ---------- domain : domain, tuple of domains or DomainTuple The full input domain space : int The index of the domain on which the operator acts. domain[space] must be a harmonic LogRGSpace. target : LogRGSpace The target codomain of domain[space] Must be a nonharmonic LogRGSpace. """ def __init__(self, domain, target, space=0): self._domain = DomainTuple.make(domain) self._space = infer_space(self._domain, space) from ..domains.log_rg_space import LogRGSpace if not isinstance(self._domain[self._space], LogRGSpace): raise ValueError("Domain[space] has to be a LogRGSpace!") if not isinstance(target, LogRGSpace): raise ValueError("Target has to be a LogRGSpace!") if not self._domain[self._space].harmonic: raise TypeError( "QHTOperator only works on a harmonic space") if target.harmonic: raise TypeError("Target is not a codomain of domain") self._target = [dom for dom in self._domain] self._target[self._space] = target self._target = DomainTuple.make(self._target) @property def domain(self): return self._domain @property def target(self): return self._target def apply(self, x, mode): self._check_input(x, mode) dom = self._domain[self._space] x = x.val * dom.scalar_dvol() n = self._domain.axes[self._space] rng = n if mode == self.TIMES else reversed(n) ax = dobj.distaxis(x) globshape = x.shape for i in rng: sl = (slice(None),)*i + (slice(1, None),) if i == ax: x = dobj.redistribute(x, nodist=(ax,)) tmp = dobj.local_data(x) tmp[sl] = hartley(tmp[sl], axes=(i,)) if i == ax: x = dobj.redistribute(x, dist=ax) return Field(self._tgt(mode), val=x) @property def capability(self): return self.TIMES | self.ADJOINT_TIMES