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,))