diff --git a/demos/Wiener_Filter.ipynb b/demos/Wiener_Filter.ipynb
index b6923a6fdabe730047db84171ab55c6fcb016021..08935427ed5f583b634392f4e4aa5d20dadad0ef 100644
--- a/demos/Wiener_Filter.ipynb
+++ b/demos/Wiener_Filter.ipynb
@@ -229,14 +229,13 @@
     "s_space = ift.RGSpace(N_pixels)\n",
     "h_space = s_space.get_default_codomain()\n",
     "HT = ift.HarmonicTransformOperator(h_space, target=s_space)\n",
-    "p_space = ift.PowerSpace(h_space)\n",
     "\n",
     "# Operators\n",
     "Sh = ift.create_power_operator(h_space, power_spectrum=pow_spec)\n",
     "R = HT #*ift.create_harmonic_smoothing_operator((h_space,), 0, 0.02)\n",
     "\n",
     "# Fields and data\n",
-    "sh = ift.power_synthesize(ift.PS_field(p_space, pow_spec),real_signal=True)\n",
+    "sh = Sh.draw_sample()\n",
     "noiseless_data=R(sh)\n",
     "noise_amplitude = np.sqrt(0.2)\n",
     "N = ift.ScalingOperator(noise_amplitude**2, s_space)\n",
@@ -394,7 +393,7 @@
     "# R is defined below\n",
     "\n",
     "# Fields\n",
-    "sh = ift.power_synthesize(ift.PS_field(p_space,pow_spec),real_signal=True)\n",
+    "sh = Sh.draw_sample()\n",
     "s = HT(sh)\n",
     "n = ift.Field.from_random(domain=s_space, random_type='normal',\n",
     "                      std=noise_amplitude, mean=0)"
@@ -565,14 +564,13 @@
    "source": [
     "h_space = s_space.get_default_codomain()\n",
     "HT = ift.HarmonicTransformOperator(h_space,s_space)\n",
-    "p_space = ift.PowerSpace(h_space)\n",
     "\n",
     "# Operators\n",
     "Sh = ift.create_power_operator(h_space, power_spectrum=pow_spec)\n",
     "N = ift.ScalingOperator(sigma2,s_space)\n",
     "\n",
     "# Fields and data\n",
-    "sh = ift.power_synthesize(ift.PS_field(p_space,pow_spec),real_signal=True)\n",
+    "sh = Sh.draw_sample()\n",
     "n = ift.Field.from_random(domain=s_space, random_type='normal',\n",
     "                      std=np.sqrt(sigma2), mean=0)\n",
     "\n",
diff --git a/demos/critical_filtering.py b/demos/critical_filtering.py
index 9f892d3a50657ab1e336302db42797063b534584..0011e23f00a3757192ce78f1c86ff66f15bfbba9 100644
--- a/demos/critical_filtering.py
+++ b/demos/critical_filtering.py
@@ -31,21 +31,21 @@ if __name__ == "__main__":
     p_space = ift.PowerSpace(h_space,
                              binbounds=ift.PowerSpace.useful_binbounds(
                                  h_space, logarithmic=True))
-    s_spec = ift.Field.full(p_space, 1e-5)
+
     # Choosing the prior correlation structure and defining
     # correlation operator
     p = ift.PS_field(p_space, p_spec)
     log_p = ift.log(p)
-    S = ift.create_power_operator(h_space, power_spectrum=s_spec)
+    S = ift.create_power_operator(h_space, power_spectrum=lambda k: 1e-5)
 
     # Drawing a sample sh from the prior distribution in harmonic space
-    sh = ift.power_synthesize(s_spec)
+    sh = S.draw_sample()
 
     # Choosing the measurement instrument
     # Instrument = SmoothingOperator(s_space, sigma=0.01)
     mask = np.ones(s_space.shape)
-    #mask[6000:8000] = 0.
-    mask[30:70,30:70] = 0.
+    # mask[6000:8000] = 0.
+    mask[30:70, 30:70] = 0.
     mask = ift.Field.from_global_data(s_space, mask)
 
     MaskOperator = ift.DiagonalOperator(mask)
@@ -69,7 +69,7 @@ if __name__ == "__main__":
     # Creating the mock data
     d = noiseless_data + n
 
-    m0 = ift.power_synthesize(ift.Field.full(p_space, 1e-7))
+    m0 = ift.Field.full(h_space, 1e-7)
     t0 = ift.Field.full(p_space, -4.)
     power0 = Distributor.times(ift.exp(0.5 * t0))
 
@@ -120,5 +120,5 @@ if __name__ == "__main__":
     ift.plot(nonlinearity(HT(power0*m0)), title="Reconstructed sky",
              name="reconstructed_sky.png", zmin=zmin, zmax=zmax, **plotdict)
     ymin = np.min(p.to_global_data())
-    ift.plot([ift.exp(t0),p], title="Power spectra",
+    ift.plot([ift.exp(t0), p], title="Power spectra",
              name="ps.png", ymin=ymin, **plotdict)
diff --git a/demos/nonlinear_critical_filter.py b/demos/nonlinear_critical_filter.py
index 3f9eabca8e12c9e2153261f3dbd8556073280eed..f1b84ab5cca49e2ef03baaf66accf1475c0070e8 100644
--- a/demos/nonlinear_critical_filter.py
+++ b/demos/nonlinear_critical_filter.py
@@ -33,15 +33,14 @@ if __name__ == "__main__":
     p_space = ift.PowerSpace(h_space,
                              binbounds=ift.PowerSpace.useful_binbounds(
                                  h_space, logarithmic=True))
-    s_spec = ift.Field.full(p_space, 1.)
     # Choosing the prior correlation structure and defining
     # correlation operator
     p = ift.PS_field(p_space, p_spec)
     log_p = ift.log(p)
-    S = ift.create_power_operator(h_space, power_spectrum=s_spec)
+    S = ift.create_power_operator(h_space, lambda k: 1.)
 
     # Drawing a sample sh from the prior distribution in harmonic space
-    sh = ift.power_synthesize(s_spec)
+    sh = S.draw_sample()
 
     # Choosing the measurement instrument
     # Instrument = SmoothingOperator(s_space, sigma=0.01)
@@ -70,7 +69,7 @@ if __name__ == "__main__":
     # Creating the mock data
     d = noiseless_data + n
 
-    m0 = ift.power_synthesize(ift.Field.full(p_space, 1e-7))
+    m0 = ift.Field.full(h_space, 1e-7)
     t0 = ift.Field.full(p_space, -4.)
     power0 = Distributor.times(ift.exp(0.5 * t0))
 
@@ -116,4 +115,4 @@ if __name__ == "__main__":
     ift.plot(nonlinearity(HT(power0*m0)),
              name="reconstructed_sky.png", **plotdict)
     ift.plot(MeasurementOperator.adjoint_times(d), name="data.png", **plotdict)
-    ift.plot([ift.exp(t0),p], name="ps.png")
+    ift.plot([ift.exp(t0), p], name="ps.png")
diff --git a/demos/paper_demos/cartesian_wiener_filter.py b/demos/paper_demos/cartesian_wiener_filter.py
index 71b1a7086bee31724eb9bb6a57135bc82838e8b8..ce14a604daac4edd161e9a76e31adbceaac54862 100644
--- a/demos/paper_demos/cartesian_wiener_filter.py
+++ b/demos/paper_demos/cartesian_wiener_filter.py
@@ -20,43 +20,28 @@ if __name__ == "__main__":
         a = 4 * correlation_length_1 * field_variance_1**2
         return a / (1 + k * correlation_length_1) ** 4.
 
+    def power_spectrum_2(k):  # note: field_variance**2 = a*k_0/4.
+        a = 4 * correlation_length_2 * field_variance_2**2
+        return a / (1 + k * correlation_length_2) ** 2.5
+
     signal_space_1 = ift.RGSpace([N_pixels_1], distances=L_1/N_pixels_1)
     harmonic_space_1 = signal_space_1.get_default_codomain()
     signal_space_2 = ift.RGSpace([N_pixels_2], distances=L_2/N_pixels_2)
     harmonic_space_2 = signal_space_2.get_default_codomain()
 
     signal_domain = ift.DomainTuple.make((signal_space_1, signal_space_2))
-    mid_domain = ift.DomainTuple.make((signal_space_1, harmonic_space_2))
     harmonic_domain = ift.DomainTuple.make((harmonic_space_1,
                                             harmonic_space_2))
 
     ht_1 = ift.HarmonicTransformOperator(harmonic_domain, space=0)
-    power_space_1 = ift.PowerSpace(harmonic_space_1)
-
-    mock_power_1 = ift.PS_field(power_space_1, power_spectrum_1)
-
-    def power_spectrum_2(k):  # note: field_variance**2 = a*k_0/4.
-        a = 4 * correlation_length_2 * field_variance_2**2
-        return a / (1 + k * correlation_length_2) ** 2.5
-
-    ht_2 = ift.HarmonicTransformOperator(mid_domain, space=1)
-    power_space_2 = ift.PowerSpace(harmonic_space_2)
-
-    mock_power_2 = ift.PS_field(power_space_2, power_spectrum_2)
-
+    ht_2 = ift.HarmonicTransformOperator(ht_1.target, space=1)
     ht = ht_2*ht_1
 
-    mock_power = ift.Field.from_global_data(
-        (power_space_1, power_space_2),
-        np.outer(mock_power_1.to_global_data(),
-                 mock_power_2.to_global_data()))
-
-    diagonal = ift.power_synthesize_nonrandom(mock_power, spaces=(0, 1))**2
-
-    S = ift.DiagonalOperator(diagonal)
+    S = (ift.create_power_operator(harmonic_domain, power_spectrum_1, 0) *
+         ift.create_power_operator(harmonic_domain, power_spectrum_2, 1))
 
     np.random.seed(10)
-    mock_signal = ift.power_synthesize(mock_power, real_signal=True)
+    mock_signal = S.draw_sample()
 
     # Setting up a exemplary response
     N1_10 = int(N_pixels_1/10)
diff --git a/demos/paper_demos/wiener_filter.py b/demos/paper_demos/wiener_filter.py
index a53aebe7b3f4c3e1c25ce554a7c5eca7e3836a44..8fa668992e5d9570f87b3396596a89069c61c983 100644
--- a/demos/paper_demos/wiener_filter.py
+++ b/demos/paper_demos/wiener_filter.py
@@ -20,15 +20,11 @@ if __name__ == "__main__":
     signal_space = ift.RGSpace([N_pixels, N_pixels], distances=L/N_pixels)
     harmonic_space = signal_space.get_default_codomain()
     ht = ift.HarmonicTransformOperator(harmonic_space, target=signal_space)
-    power_space = ift.PowerSpace(
-        harmonic_space, binbounds=ift.PowerSpace.useful_binbounds(
-            harmonic_space, logarithmic=True))
 
     # Creating the mock signal
     S = ift.create_power_operator(harmonic_space,
                                   power_spectrum=power_spectrum)
-    mock_power = ift.PS_field(power_space, power_spectrum)
-    mock_signal = ift.power_synthesize(mock_power, real_signal=True)
+    mock_signal = S.draw_sample()
 
     # Setting up an exemplary response
     mask = np.ones(signal_space.shape)
diff --git a/demos/wiener_filter_easy.py b/demos/wiener_filter_easy.py
index 5fb40c9873f529e417a737dd59c0be55a465c73c..8412ac722b4e74289a9d2deacd3545fd94bc0358 100644
--- a/demos/wiener_filter_easy.py
+++ b/demos/wiener_filter_easy.py
@@ -9,7 +9,7 @@ if __name__ == "__main__":
     L = 2.
     # Typical distance over which the field is correlated (in same unit as L)
     correlation_length = 0.1
-    # Variance of field in position space sqrt(<|s_x|^2>) (in unit of s)
+    # Variance of field in position space sqrt(<|s_x|^2>) (in same unit as s)
     field_variance = 2.
     # Smoothing length of response (in same unit as L)
     response_sigma = 0.01
@@ -29,14 +29,11 @@ if __name__ == "__main__":
     s_space = ift.RGSpace([N_pixels, N_pixels], distances=pixel_width)
     h_space = s_space.get_default_codomain()
     HT = ift.HarmonicTransformOperator(h_space, s_space)
-    p_space = ift.PowerSpace(h_space)
 
     # Create mock data
 
     Sh = ift.create_power_operator(h_space, power_spectrum=pow_spec)
-
-    sp = ift.PS_field(p_space, pow_spec)
-    sh = ift.power_synthesize(sp, real_signal=True)
+    sh = Sh.draw_sample()
 
     R = HT*ift.create_harmonic_smoothing_operator((h_space,), 0,
                                                   response_sigma)
diff --git a/demos/wiener_filter_via_curvature.py b/demos/wiener_filter_via_curvature.py
index fbcb9a58d19382a09735b32325a8d017304bc158..a295f1161a423b2e0f8dc0366c3698ad220129b1 100644
--- a/demos/wiener_filter_via_curvature.py
+++ b/demos/wiener_filter_via_curvature.py
@@ -52,15 +52,13 @@ if __name__ == "__main__":
     signal_space = ift.RGSpace(shape, distances=L/N_pixels)
     harmonic_space = signal_space.get_default_codomain()
     HT = ift.HarmonicTransformOperator(harmonic_space, target=signal_space)
-    power_space = ift.PowerSpace(harmonic_space)
 
     # Creating the mock data
     S = ift.create_power_operator(harmonic_space,
                                   power_spectrum=power_spectrum)
     np.random.seed(43)
 
-    mock_power = ift.PS_field(power_space, power_spectrum)
-    mock_signal = ift.power_synthesize(mock_power, real_signal=True)
+    mock_signal = S.draw_sample()
 
     sensitivity = (1./nu.m)**dimensionality/nu.K
     R = ift.GeometryRemover(signal_space)
diff --git a/demos/wiener_filter_via_hamiltonian.py b/demos/wiener_filter_via_hamiltonian.py
index 37e9b6cbd282a85da747f1c15b492c56717bffb1..124a625a2504eee5b9770b17a28ce1926d451081 100644
--- a/demos/wiener_filter_via_hamiltonian.py
+++ b/demos/wiener_filter_via_hamiltonian.py
@@ -13,17 +13,13 @@ if __name__ == "__main__":
     h_space = s_space.get_default_codomain()
     ht = ift.HarmonicTransformOperator(h_space, s_space)
 
-    # Set up power space
-    p_space = ift.PowerSpace(h_space)
-
     # Choose prior correlation structure and define correlation operator
     p_spec = (lambda k: (42/(k+1)**3))
 
     S = ift.create_power_operator(h_space, power_spectrum=p_spec)
 
     # Draw sample sh from the prior distribution in harmonic space
-    sp = ift.PS_field(p_space, p_spec)
-    sh = ift.power_synthesize(sp, real_signal=True)
+    sh = S.draw_sample()
 
     # Choose measurement instrument
     diag = np.ones(s_space.shape)
diff --git a/nifty4/__init__.py b/nifty4/__init__.py
index 0b7821d03f6788a97743b48997312a2c92fc08e2..320f58d04b709985855d925635cd6c4802db7349 100644
--- a/nifty4/__init__.py
+++ b/nifty4/__init__.py
@@ -10,7 +10,8 @@ from .operators import *
 
 from .field import Field, sqrt, exp, log
 
-from .probing.utils import probe_with_posterior_samples, probe_diagonal
+from .probing.utils import probe_with_posterior_samples, probe_diagonal, \
+    StatCalculator
 
 from .minimization import *
 
diff --git a/nifty4/library/wiener_filter_curvature.py b/nifty4/library/wiener_filter_curvature.py
index ebe56b5cdf83905d94b947694ea4905ff5a5d1e3..6dc9ed2ffb58c2c98a5bb5852ceca55cf3080342 100644
--- a/nifty4/library/wiener_filter_curvature.py
+++ b/nifty4/library/wiener_filter_curvature.py
@@ -18,8 +18,6 @@
 
 from ..operators.endomorphic_operator import EndomorphicOperator
 from ..operators.inversion_enabler import InversionEnabler
-from ..field import Field, sqrt
-from ..sugar import power_analyze, power_synthesize
 import numpy as np
 
 
diff --git a/nifty4/operators/chain_operator.py b/nifty4/operators/chain_operator.py
index ff290a93159279cad27e9f9ffc452c97ab677acb..783f9c151a70dd2c7e82d8eb78c1b3316651e88a 100644
--- a/nifty4/operators/chain_operator.py
+++ b/nifty4/operators/chain_operator.py
@@ -17,6 +17,7 @@
 # and financially supported by the Studienstiftung des deutschen Volkes.
 
 from .linear_operator import LinearOperator
+import numpy as np
 
 
 class ChainOperator(LinearOperator):
@@ -119,3 +120,9 @@ class ChainOperator(LinearOperator):
         for op in t_ops:
             x = op.apply(x, mode)
         return x
+
+    def draw_sample(self, dtype=np.float64):
+        sample = self._ops[-1].draw_sample(dtype)
+        for op in reversed(self._ops[:-1]):
+            sample = op.process_sample(sample)
+        return sample
diff --git a/nifty4/operators/diagonal_operator.py b/nifty4/operators/diagonal_operator.py
index a30fc283f5c4693f4c0d0f8d6815f6d7d12e19e4..f8ce4a6de32ea058b6565571606b53f8977f7c52 100644
--- a/nifty4/operators/diagonal_operator.py
+++ b/nifty4/operators/diagonal_operator.py
@@ -133,6 +133,14 @@ class DiagonalOperator(EndomorphicOperator):
         return DiagonalOperator(self._diagonal.conjugate(), self._domain,
                                 self._spaces)
 
+    def process_sample(self, sample):
+        if np.issubdtype(self._ldiag.dtype, np.complexfloating):
+            raise ValueError("cannot draw sample from complex-valued operator")
+
+        res = Field.empty_like(sample)
+        res.local_data[()] = sample.local_data * np.sqrt(self._ldiag)
+        return res
+
     def draw_sample(self, dtype=np.float64):
         if np.issubdtype(self._ldiag.dtype, np.complexfloating):
             raise ValueError("cannot draw sample from complex-valued operator")
diff --git a/nifty4/operators/scaling_operator.py b/nifty4/operators/scaling_operator.py
index a327ac75c224ea878bf498d610ca90f3cf91d68a..82f55104f7a81847927cb7cc9c14f324a98027e8 100644
--- a/nifty4/operators/scaling_operator.py
+++ b/nifty4/operators/scaling_operator.py
@@ -83,6 +83,11 @@ class ScalingOperator(EndomorphicOperator):
             return self.TIMES | self.ADJOINT_TIMES
         return self._all_ops
 
+    def process_sample(self, sample):
+        if self._factor.imag != 0. or self._factor.real <= 0.:
+            raise ValueError("Operator not positive definite")
+        return sample * np.sqrt(self._factor)
+
     def draw_sample(self, dtype=np.float64):
         if self._factor.imag != 0. or self._factor.real <= 0.:
             raise ValueError("Operator not positive definite")
diff --git a/nifty4/sugar.py b/nifty4/sugar.py
index d85a14462eddb7fde37c1938933f0be0555a4bfa..61aed8e152cb0fc15418d7e97ce6f3593bd1b7ce 100644
--- a/nifty4/sugar.py
+++ b/nifty4/sugar.py
@@ -28,18 +28,16 @@ from . import dobj, utilities
 
 __all__ = ['PS_field',
            'power_analyze',
-           'power_synthesize',
-           'power_synthesize_nonrandom',
            'create_power_field',
            'create_power_operator',
            'create_harmonic_smoothing_operator']
 
 
-def PS_field(pspace, func, dtype=None):
+def PS_field(pspace, func):
     if not isinstance(pspace, PowerSpace):
         raise TypeError
     data = dobj.from_global_data(func(pspace.k_lengths))
-    return Field(pspace, val=data, dtype=dtype)
+    return Field(pspace, val=data)
 
 
 def _single_power_analyze(field, idx, binbounds):
@@ -119,21 +117,21 @@ def power_analyze(field, spaces=None, binbounds=None,
     return parts[0] + 1j*parts[1] if keep_phase_information else parts[0]
 
 
-def power_synthesize_nonrandom(field, spaces=None):
+def _power_synthesize_nonrandom(field, spaces=None):
     spaces = utilities.parse_spaces(spaces, len(field.domain))
 
     result_domain = list(field.domain)
-    spec = sqrt(field)
+    amplitude = sqrt(field)
     for i in spaces:
         result_domain[i] = field.domain[i].harmonic_partner
         pd = PowerDistributor(result_domain, field.domain[i], i)
-        spec = pd(spec)
+        amplitude = pd(amplitude)
 
-    return spec
+    return amplitude
 
 
-def power_synthesize(field, spaces=None, real_power=True, real_signal=True):
-    """Returns a sampled field with `field`\**2 as its power spectrum.
+def _power_synthesize(field, spaces=None, real_power=True, real_signal=True):
+    """Returns a sampled field with `field` as its power spectrum.
 
     This method draws a Gaussian random field in the harmonic partner
     domain of this field's domains, using this field as power spectrum.
@@ -141,7 +139,7 @@ def power_synthesize(field, spaces=None, real_power=True, real_signal=True):
     Parameters
     ----------
     field : Field
-        The input field containing the square root of the power spectrum
+        The input field containing the power spectrum
     spaces : None, int, or tuple of int, optional
         Specifies the subdomains containing all the PowerSpaces which
         should be converted (default : None).
@@ -161,16 +159,16 @@ def power_synthesize(field, spaces=None, real_power=True, real_signal=True):
 
     Notes
     -----
-    For this the spaces specified by `spaces` must be a PowerSpace.
-    This expects this field to be the square root of a power spectrum, i.e.
-    to have the unit of the field to be sampled.
+    For this the spaces specified by `spaces` must be of type PowerSpace.
+    This expects this field to be a power spectrum, i.e.
+    to have the unit of "field to be sampled"**2.
 
     Raises
     ------
     ValueError : If a domain specified by `spaces` is not a PowerSpace.
     """
 
-    spec = power_synthesize_nonrandom(field, spaces)
+    spec = _power_synthesize_nonrandom(field, spaces)
     self_real = not np.issubdtype(spec.dtype, np.complexfloating)
     if (not real_power) and self_real:
         raise ValueError("can't draw complex realizations from real spectrum")
@@ -190,7 +188,7 @@ def power_synthesize(field, spaces=None, real_power=True, real_signal=True):
     return result[0] if real_power else result[0] + 1j*result[1]
 
 
-def create_power_field(domain, power_spectrum, dtype=None):
+def create_power_field(domain, power_spectrum):
     if not callable(power_spectrum):  # we have a Field living on a PowerSpace
         if not isinstance(power_spectrum, Field):
             raise TypeError("Field object expected")
@@ -199,15 +197,15 @@ def create_power_field(domain, power_spectrum, dtype=None):
         if not isinstance(power_spectrum.domain[0], PowerSpace):
             raise TypeError("PowerSpace required")
         power_domain = power_spectrum.domain[0]
-        fp = Field(power_domain, val=power_spectrum.val, dtype=dtype)
+        fp = Field(power_domain, val=power_spectrum.val)
     else:
         power_domain = PowerSpace(domain)
-        fp = PS_field(power_domain, power_spectrum, dtype)
+        fp = PS_field(power_domain, power_spectrum)
 
     return PowerDistributor(domain, power_domain)(fp)
 
 
-def create_power_operator(domain, power_spectrum, space=None, dtype=None):
+def create_power_operator(domain, power_spectrum, space=None):
     """ Creates a diagonal operator with the given power spectrum.
 
     Constructs a diagonal operator that lives over the specified domain.
@@ -220,10 +218,6 @@ def create_power_operator(domain, power_spectrum, space=None, dtype=None):
         An object that contains the power spectrum as a function of k.
     space : int
         the domain index on which the power operator will work
-    dtype : None or type, optional
-        dtype that the field holding the power spectrum shall use
-        (default : None).
-        if dtype is None: the dtype of `power_spectrum` will be used.
 
     Returns
     -------
@@ -233,7 +227,7 @@ def create_power_operator(domain, power_spectrum, space=None, dtype=None):
     domain = DomainTuple.make(domain)
     space = utilities.infer_space(domain, space)
     return DiagonalOperator(
-        create_power_field(domain[space], power_spectrum, dtype),
+        create_power_field(domain[space], power_spectrum),
         domain=domain, spaces=space)
 
 
diff --git a/nifty4/utilities.py b/nifty4/utilities.py
index f19a968a5aa4aeb5118ec551dffab424610a86a7..6aa2f241f8be7a4c91a0a0db2cb0bc2a6fa1a324 100644
--- a/nifty4/utilities.py
+++ b/nifty4/utilities.py
@@ -22,10 +22,10 @@ from itertools import product
 import abc
 from future.utils import with_metaclass
 
-
 __all__ = ["get_slice_list", "safe_cast", "parse_spaces", "infer_space",
            "memo", "NiftyMetaBase", "hartley", "my_fftn_r2c"]
 
+
 def get_slice_list(shape, axes):
     """
     Helper function which generates slice list(s) to traverse over all
diff --git a/test/test_field.py b/test/test_field.py
index 110c51dbdbf3f50bb20e848d378fe05a31441bfc..c6079771962cd7efd68bdfe2e345447d1ce7130d 100644
--- a/test/test_field.py
+++ b/test/test_field.py
@@ -58,66 +58,57 @@ class Test_Functionality(unittest.TestCase):
         np.random.seed(11)
 
         p1 = ift.PowerSpace(space1)
-        p1val = _spec1(p1.k_lengths)
-        fp1 = ift.Field.from_global_data(p1, p1val)
-
+        fp1 = ift.PS_field(p1, _spec1)
         p2 = ift.PowerSpace(space2)
-        p2val = _spec2(p2.k_lengths)
-        fp2 = ift.Field.from_global_data(p2, p2val)
-
-        outer = np.outer(p1val, p2val)
+        fp2 = ift.PS_field(p2, _spec2)
+        outer = np.outer(fp1.to_global_data(), fp2.to_global_data())
         fp = ift.Field.from_global_data((p1, p2), outer)
 
+        op1 = ift.create_power_operator((space1, space2), _spec1, 0)
+        op2 = ift.create_power_operator((space1, space2), _spec2, 1)
+        opfull = op2*op1
+
         samples = 500
-        ps1 = 0.
-        ps2 = 0.
+        sc1 = ift.StatCalculator()
+        sc2 = ift.StatCalculator()
         for ii in range(samples):
-            sk = ift.power_synthesize(fp, spaces=(0, 1), real_signal=True)
+            sk = opfull.draw_sample()
 
             sp = ift.power_analyze(sk, spaces=(0, 1),
                                    keep_phase_information=False)
-            ps1 += sp.sum(spaces=1)/fp2.sum()
-            ps2 += sp.sum(spaces=0)/fp1.sum()
+            sc1.add(sp.sum(spaces=1)/fp2.sum())
+            sc2.add(sp.sum(spaces=0)/fp1.sum())
 
-        assert_allclose((ps1/samples).local_data, fp1.local_data, rtol=0.2)
-        assert_allclose((ps2/samples).local_data, fp2.local_data, rtol=0.2)
+        assert_allclose(sc1.mean.local_data, fp1.local_data, rtol=0.2)
+        assert_allclose(sc2.mean.local_data, fp2.local_data, rtol=0.2)
 
     @expand(product([ift.RGSpace((8,), harmonic=True),
                      ift.RGSpace((8, 8), harmonic=True, distances=0.123)],
                     [ift.RGSpace((8,), harmonic=True),
                      ift.LMSpace(12)]))
-    def test_DiagonalOperator_power_analyze(self, space1, space2):
+    def test_DiagonalOperator_power_analyze2(self, space1, space2):
         np.random.seed(11)
 
-        fulldomain = ift.DomainTuple.make((space1, space2))
-
-        p1 = ift.PowerSpace(space1)
-        p1val = _spec1(p1.k_lengths)
-        fp1 = ift.Field.from_global_data(p1, p1val)
-
-        p2 = ift.PowerSpace(space2)
-        p2val = _spec2(p2.k_lengths)
-        fp2 = ift.Field.from_global_data(p2, p2val)
+        fp1 = ift.PS_field(ift.PowerSpace(space1), _spec1)
+        fp2 = ift.PS_field(ift.PowerSpace(space2), _spec2)
 
-        S_1 = ift.create_power_field(space1, lambda x: np.sqrt(_spec1(x)))
-        S_1 = ift.DiagonalOperator(S_1, domain=fulldomain, spaces=0)
-        S_2 = ift.create_power_field(space2, lambda x: np.sqrt(_spec2(x)))
-        S_2 = ift.DiagonalOperator(S_2, domain=fulldomain, spaces=1)
+        S_1 = ift.create_power_operator((space1, space2), _spec1, 0)
+        S_2 = ift.create_power_operator((space1, space2), _spec2, 1)
+        S_full = S_2*S_1
 
         samples = 500
-        ps1 = 0.
-        ps2 = 0.
+        sc1 = ift.StatCalculator()
+        sc2 = ift.StatCalculator()
 
         for ii in range(samples):
-            rand_k = ift.Field.from_random('normal', domain=fulldomain)
-            sk = S_1.times(S_2.times(rand_k))
+            sk = S_full.draw_sample()
             sp = ift.power_analyze(sk, spaces=(0, 1),
                                    keep_phase_information=False)
-            ps1 += sp.sum(spaces=1)/fp2.sum()
-            ps2 += sp.sum(spaces=0)/fp1.sum()
+            sc1.add(sp.sum(spaces=1)/fp2.sum())
+            sc2.add(sp.sum(spaces=0)/fp1.sum())
 
-        assert_allclose((ps1/samples).local_data, fp1.local_data, rtol=0.2)
-        assert_allclose((ps2/samples).local_data, fp2.local_data, rtol=0.2)
+        assert_allclose(sc1.mean.local_data, fp1.local_data, rtol=0.2)
+        assert_allclose(sc2.mean.local_data, fp2.local_data, rtol=0.2)
 
     def test_vdot(self):
         s = ift.RGSpace((10,))