From 9b51b0961c43b74589d2bbc8a61838693da382bf Mon Sep 17 00:00:00 2001
From: Martin Reinecke <martin@mpa-garching.mpg.de>
Date: Thu, 2 Aug 2018 13:08:10 +0200
Subject: [PATCH] make third demo work

---
 demos/getting_started_3.py        |  6 +++---
 nifty5/library/amplitude_model.py |  9 +--------
 nifty5/linearization.py           |  3 +--
 nifty5/operators/field_adapter.py | 19 +++++++------------
 nifty5/operators/operator.py      | 10 +++++++++-
 5 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/demos/getting_started_3.py b/demos/getting_started_3.py
index 1dcab3a36..34398d2f2 100644
--- a/demos/getting_started_3.py
+++ b/demos/getting_started_3.py
@@ -40,13 +40,14 @@ if __name__ == '__main__':
     power_space = A.target[0]
     power_distributor = ift.PowerDistributor(harmonic_space, power_space)
     dummy = ift.Field.from_random('normal', harmonic_space)
+    domain = ift.MultiDomain.union((A.domain, ift.MultiDomain.make({'xi': harmonic_space})))
 
-    correlated_field = lambda inp: ht(power_distributor(A(inp))*inp["xi"])
+    correlated_field = ht.chain(power_distributor.chain(A)*ift.FieldAdapter(domain, "xi"))
     # alternatively to the block above one can do:
     #correlated_field = ift.CorrelatedField(position_space, A)
 
     # apply some nonlinearity
-    signal = lambda inp: correlated_field(inp).positive_tanh()
+    signal = correlated_field.positive_tanh()
 
     # Building the Line of Sight response
     LOS_starts, LOS_ends = get_random_LOS(100)
@@ -60,7 +61,6 @@ if __name__ == '__main__':
     N = ift.ScalingOperator(noise, data_space)
 
     # generate mock data
-    domain = ift.MultiDomain.union((A.domain, ift.MultiDomain.make({'xi': harmonic_space})))
     MOCK_POSITION = ift.from_random('normal', domain)
     data = signal_response(MOCK_POSITION) + N.draw_sample()
 
diff --git a/nifty5/library/amplitude_model.py b/nifty5/library/amplitude_model.py
index 846b3f721..3464bdce2 100644
--- a/nifty5/library/amplitude_model.py
+++ b/nifty5/library/amplitude_model.py
@@ -124,6 +124,7 @@ class AmplitudeModel(Operator):
 
         self._domain = MultiDomain.make({keys[0]: dof_space,
                                          keys[1]: param_space})
+        self._target = self._exp_transform.target
 
         kern = lambda k: _ceps_kernel(dof_space, k, ceps_a, ceps_k)
         cepstrum = create_cepstrum_amplitude_field(dof_space, kern)
@@ -138,11 +139,3 @@ class AmplitudeModel(Operator):
         linear_spec = self._slope(phi)
         loglog_spec = smooth_spec + linear_spec
         return self._exp_transform((0.5*loglog_spec).exp())
-
-    @property
-    def domain(self):
-        return self._domain
-
-    @property
-    def target(self):
-        return self._exp_transform.target
diff --git a/nifty5/linearization.py b/nifty5/linearization.py
index f1584aed8..f6b4d55f0 100644
--- a/nifty5/linearization.py
+++ b/nifty5/linearization.py
@@ -43,8 +43,7 @@ class Linearization(object):
 
     def __getitem__(self, name):
         from .operators.field_adapter import FieldAdapter
-        dom = self._val[name].domain
-        return Linearization(self._val[name], FieldAdapter(dom, name))
+        return Linearization(self._val[name], FieldAdapter(self.domain, name))
 
     def __neg__(self):
         return Linearization(
diff --git a/nifty5/operators/field_adapter.py b/nifty5/operators/field_adapter.py
index 54a026b8f..24abb0a0b 100644
--- a/nifty5/operators/field_adapter.py
+++ b/nifty5/operators/field_adapter.py
@@ -8,16 +8,10 @@ from ..multi.multi_field import MultiField
 
 class FieldAdapter(LinearOperator):
     def __init__(self, dom, name_dom):
-        self._domain = MultiDomain.make({name_dom: dom})
-        self._target = dom
-
-    @property
-    def domain(self):
-        return self._domain
-
-    @property
-    def target(self):
-        return self._target
+        self._domain = MultiDomain.make(dom)
+        self._smalldom = MultiDomain.make({name_dom: self._domain[name_dom]})
+        self._name = name_dom
+        self._target = dom[name_dom]
 
     @property
     def capability(self):
@@ -27,5 +21,6 @@ class FieldAdapter(LinearOperator):
         self._check_input(x, mode)
 
         if mode == self.TIMES:
-            return x.values()[0]
-        return MultiField(self._domain, (x,))
+            return x[self._name]
+        tmp = MultiField(self._smalldom, (x,))
+        return tmp.unite(MultiField.full(self._domain, 0.))
diff --git a/nifty5/operators/operator.py b/nifty5/operators/operator.py
index 3135a7f7d..aaac3d704 100644
--- a/nifty5/operators/operator.py
+++ b/nifty5/operators/operator.py
@@ -10,12 +10,14 @@ class Operator(NiftyMetaBase()):
     domain, and can also provide the Jacobian.
     """
 
+    @property
     def domain(self):
         """DomainTuple or MultiDomain : the operator's input domain
 
             The domain on which the Operator's input Field lives."""
         return self._domain
 
+    @property
     def target(self):
         """DomainTuple or MultiDomain : the operator's output domain
 
@@ -27,6 +29,11 @@ class Operator(NiftyMetaBase()):
             return NotImplemented
         return _OpChain.make((self, x))
 
+    def __mul__(self, x):
+        if not isinstance(x, Operator):
+            return NotImplemented
+        return _OpProd.make((self, x))
+
     def chain(self, x):
         res = self.__matmul__(x)
         if res == NotImplemented:
@@ -110,7 +117,8 @@ class _OpProd(_CombinedOperator):
         self._target = self._ops[0].target
 
     def __call__(self, x):
-        return my_prod(map(lambda op: op(x) for op in self._ops))
+        from ..utilities import my_product
+        return my_product(map(lambda op: op(x), self._ops))
 
 
 class _OpSum(_CombinedOperator):
-- 
GitLab