scaling_operator.py 2.97 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
# 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 <http://www.gnu.org/licenses/>.
#
14
# Copyright(C) 2013-2019 Max-Planck-Society
Martin Reinecke's avatar
Martin Reinecke committed
15
#
16
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
17

Martin Reinecke's avatar
Martin Reinecke committed
18
import numpy as np
19

20
from ..sugar import full
21
from .endomorphic_operator import EndomorphicOperator
Martin Reinecke's avatar
Martin Reinecke committed
22
23
24


class ScalingOperator(EndomorphicOperator):
Martin Reinecke's avatar
Martin Reinecke committed
25
    """Operator which multiplies a Field with a scalar.
Martin Reinecke's avatar
Martin Reinecke committed
26
27
28
29
30

    Parameters
    ----------
    factor : scalar
        The multiplication factor
Martin Reinecke's avatar
docs    
Martin Reinecke committed
31
    domain : Domain or tuple of Domain or DomainTuple
Philipp Arras's avatar
Philipp Arras committed
32
        The domain on which the Operator's input Field is defined.
Martin Reinecke's avatar
Martin Reinecke committed
33
34
35

    Notes
    -----
Philipp Arras's avatar
Docs    
Philipp Arras committed
36
37
    :class:`Operator` supports the multiplication with a scalar. So one does
    not need instantiate :class:`ScalingOperator` explicitly in most cases.
Martin Reinecke's avatar
Martin Reinecke committed
38
39
40
    """

    def __init__(self, factor, domain):
Martin Reinecke's avatar
fix    
Martin Reinecke committed
41
        from ..sugar import makeDomain
Martin Reinecke's avatar
Martin Reinecke committed
42
43
44
45

        if not np.isscalar(factor):
            raise TypeError("Scalar required")
        self._factor = factor
Martin Reinecke's avatar
fix    
Martin Reinecke committed
46
        self._domain = makeDomain(domain)
Martin Reinecke's avatar
Martin Reinecke committed
47
48
49
50
        if self._factor == 0.:
            self._capability = self.TIMES | self.ADJOINT_TIMES
        else:
            self._capability = self._all_ops
Martin Reinecke's avatar
Martin Reinecke committed
51
52
53

    def apply(self, x, mode):
        self._check_input(x, mode)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
54
55
        fct = self._factor
        if fct == 1.:
56
            return x
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
57
        if fct == 0.:
58
            return full(self.domain, 0.)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
59
60
61
62
63
        if (mode & 10) != 0:
            fct = np.conj(fct)
        if (mode & 12) != 0:
            fct = 1./fct
        return x*fct
Martin Reinecke's avatar
Martin Reinecke committed
64

65
    def _flip_modes(self, trafo):
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
66
67
68
69
70
71
        fct = self._factor
        if trafo & self.ADJOINT_BIT:
            fct = np.conj(fct)
        if trafo & self.INVERSE_BIT:
            fct = 1./fct
        return ScalingOperator(fct, self._domain)
Martin Reinecke's avatar
Martin Reinecke committed
72

73
    def _get_fct(self, from_inverse):
74
        fct = self._factor
75
76
77
78
79
        if (fct.imag != 0. or fct.real < 0. or
                (fct.real == 0. and from_inverse)):
                    raise ValueError("operator not positive definite")
        return 1./np.sqrt(fct) if from_inverse else np.sqrt(fct)

Martin Reinecke's avatar
Martin Reinecke committed
80
81
#     def process_sample(self, samp, from_inverse):
#         return samp*self._get_fct(from_inverse)
82
83
84
85
86

    def draw_sample(self, from_inverse=False, dtype=np.float64):
        from ..sugar import from_random
        return from_random(random_type="normal", domain=self._domain,
                           std=self._get_fct(from_inverse), dtype=dtype)
Martin Reinecke's avatar
Martin Reinecke committed
87
88

    def __repr__(self):
Martin Reinecke's avatar
Martin Reinecke committed
89
        return "ScalingOperator ({})".format(self._factor)