Commit 4fe96fe8 authored by Philipp Arras's avatar Philipp Arras
Browse files

Restructure operator tests

parent fb0a4dc3
Pipeline #76912 passed with stages
in 12 minutes and 1 second
Changes since NIFTy 6 Changes since NIFTy 6
===================== =====================
*None.* Naming of operator tests
------------------------
The implementation tests for nonlinear operators are now available in
`ift.extra.check_operator()` and for linear operators
`ift.extra.check_linear_operator()`.
Changes since NIFTy 5 Changes since NIFTy 5
......
...@@ -97,7 +97,7 @@ def main(): ...@@ -97,7 +97,7 @@ def main():
p_space = ift.UnstructuredDomain(N_params) p_space = ift.UnstructuredDomain(N_params)
params = ift.full(p_space, 0.) params = ift.full(p_space, 0.)
R = PolynomialResponse(p_space, x) R = PolynomialResponse(p_space, x)
ift.extra.consistency_check(R) ift.extra.check_linear_operator(R)
d_space = R.target d_space = R.target
d = ift.makeField(d_space, y) d = ift.makeField(d_space, y)
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
# #
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
from itertools import combinations
import numpy as np import numpy as np
from numpy.testing import assert_ from numpy.testing import assert_
...@@ -23,13 +25,103 @@ from .field import Field ...@@ -23,13 +25,103 @@ from .field import Field
from .linearization import Linearization from .linearization import Linearization
from .multi_domain import MultiDomain from .multi_domain import MultiDomain
from .multi_field import MultiField from .multi_field import MultiField
from .operators.energy_operators import EnergyOperator
from .operators.linear_operator import LinearOperator from .operators.linear_operator import LinearOperator
from .sugar import from_random from .operators.operator import Operator
from .sugar import from_random, full, makeDomain
__all__ = ["consistency_check", "check_jacobian_consistency", __all__ = ["check_linear_operator", "check_operator",
"assert_allclose"] "assert_allclose"]
def check_linear_operator(op, domain_dtype=np.float64, target_dtype=np.float64,
atol=0, rtol=1e-7, only_r_linear=False):
"""
Checks an operator for algebraic consistency of its capabilities.
Checks whether times(), adjoint_times(), inverse_times() and
adjoint_inverse_times() (if in capability list) is implemented
consistently. Additionally, it checks whether the operator is linear.
Parameters
----------
op : LinearOperator
Operator which shall be checked.
domain_dtype : dtype
The data type of the random vectors in the operator's domain. Default
is `np.float64`.
target_dtype : dtype
The data type of the random vectors in the operator's target. Default
is `np.float64`.
atol : float
Absolute tolerance for the check. If rtol is specified,
then satisfying any tolerance will let the check pass.
Default: 0.
rtol : float
Relative tolerance for the check. If atol is specified,
then satisfying any tolerance will let the check pass.
Default: 0.
only_r_linear: bool
set to True if the operator is only R-linear, not C-linear.
This will relax the adjointness test accordingly.
"""
if not isinstance(op, LinearOperator):
raise TypeError('This test tests only linear operators.')
_domain_check_linear(op, domain_dtype)
_domain_check_linear(op.adjoint, target_dtype)
_domain_check_linear(op.inverse, target_dtype)
_domain_check_linear(op.adjoint.inverse, domain_dtype)
_check_linearity(op, domain_dtype, atol, rtol)
_check_linearity(op.adjoint, target_dtype, atol, rtol)
_check_linearity(op.inverse, target_dtype, atol, rtol)
_check_linearity(op.adjoint.inverse, domain_dtype, atol, rtol)
_full_implementation(op, domain_dtype, target_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.adjoint, target_dtype, domain_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.inverse, target_dtype, domain_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.adjoint.inverse, domain_dtype, target_dtype, atol,
rtol, only_r_linear)
def check_operator(op, loc, tol=1e-8, ntries=100, perf_check=True,
only_r_differentiable=True, metric_sampling=True):
"""
Performs various checks of the implementation of linear and nonlinear
operators.
Computes the Jacobian with finite differences and compares it to the
implemented Jacobian.
Parameters
----------
op : Operator
Operator which shall be checked.
loc : Field or MultiField
An Field or MultiField instance which has the same domain
as op. The location at which the gradient is checked
tol : float
Tolerance for the check.
perf_check : Boolean
Do performance check. May be disabled for very unimportant operators.
only_r_differentiable : Boolean
Jacobians of C-differentiable operators need to be C-linear.
Default: True
metric_sampling: Boolean
If op is an EnergyOperator, metric_sampling determines whether the
test shall try to sample from the metric or not.
"""
if not isinstance(op, Operator):
raise TypeError('This test tests only linear operators.')
_domain_check_nonlinear(op, loc)
_performance_check(op, loc, bool(perf_check))
_linearization_value_consistency(op, loc)
_jac_vs_finite_differences(op, loc, tol, ntries, only_r_differentiable)
_check_nontrivial_constant(op, loc, tol, ntries, only_r_differentiable,
metric_sampling)
def assert_allclose(f1, f2, atol, rtol): def assert_allclose(f1, f2, atol, rtol):
if isinstance(f1, Field): if isinstance(f1, Field):
return np.testing.assert_allclose(f1.val, f2.val, atol=atol, rtol=rtol) return np.testing.assert_allclose(f1.val, f2.val, atol=atol, rtol=rtol)
...@@ -44,6 +136,20 @@ def assert_equal(f1, f2): ...@@ -44,6 +136,20 @@ def assert_equal(f1, f2):
assert_equal(val, f2[key]) assert_equal(val, f2[key])
def _nozero(fld):
if isinstance(fld, Field):
return np.testing.assert_((fld != 0).s_all())
for val in fld.values():
_nozero(val)
def _allzero(fld):
if isinstance(fld, Field):
return np.testing.assert_((fld == 0.).s_all())
for val in fld.values():
_allzero(val)
def _adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol, def _adjoint_implementation(op, domain_dtype, target_dtype, atol, rtol,
only_r_linear): only_r_linear):
needed_cap = op.TIMES | op.ADJOINT_TIMES needed_cap = op.TIMES | op.ADJOINT_TIMES
...@@ -90,7 +196,8 @@ def _check_linearity(op, domain_dtype, atol, rtol): ...@@ -90,7 +196,8 @@ def _check_linearity(op, domain_dtype, atol, rtol):
assert_allclose(val1, val2, atol=atol, rtol=rtol) assert_allclose(val1, val2, atol=atol, rtol=rtol)
def _actual_domain_check_linear(op, domain_dtype=None, inp=None): def _domain_check_linear(op, domain_dtype=None, inp=None):
_domain_check(op)
needed_cap = op.TIMES needed_cap = op.TIMES
if (op.capability & needed_cap) != needed_cap: if (op.capability & needed_cap) != needed_cap:
return return
...@@ -102,8 +209,9 @@ def _actual_domain_check_linear(op, domain_dtype=None, inp=None): ...@@ -102,8 +209,9 @@ def _actual_domain_check_linear(op, domain_dtype=None, inp=None):
assert_(op(inp).domain is op.target) assert_(op(inp).domain is op.target)
def _actual_domain_check_nonlinear(op, loc): def _domain_check_nonlinear(op, loc):
assert isinstance(loc, (Field, MultiField)) _domain_check(op)
assert_(isinstance(loc, (Field, MultiField)))
assert_(loc.domain is op.domain) assert_(loc.domain is op.domain)
for wm in [False, True]: for wm in [False, True]:
lin = Linearization.make_var(loc, wm) lin = Linearization.make_var(loc, wm)
...@@ -118,8 +226,8 @@ def _actual_domain_check_nonlinear(op, loc): ...@@ -118,8 +226,8 @@ def _actual_domain_check_nonlinear(op, loc):
assert_(reslin.jac.domain is reslin.domain) assert_(reslin.jac.domain is reslin.domain)
assert_(reslin.jac.target is reslin.target) assert_(reslin.jac.target is reslin.target)
assert_(lin.want_metric == reslin.want_metric) assert_(lin.want_metric == reslin.want_metric)
_actual_domain_check_linear(reslin.jac, inp=loc) _domain_check_linear(reslin.jac, inp=loc)
_actual_domain_check_linear(reslin.jac.adjoint, inp=reslin.jac(loc)) _domain_check_linear(reslin.jac.adjoint, inp=reslin.jac(loc))
if reslin.metric is not None: if reslin.metric is not None:
assert_(reslin.metric.domain is reslin.metric.target) assert_(reslin.metric.domain is reslin.metric.target)
assert_(reslin.metric.domain is op.domain) assert_(reslin.metric.domain is op.domain)
...@@ -171,58 +279,6 @@ def _performance_check(op, pos, raise_on_fail): ...@@ -171,58 +279,6 @@ def _performance_check(op, pos, raise_on_fail):
raise RuntimeError(s) raise RuntimeError(s)
def consistency_check(op, domain_dtype=np.float64, target_dtype=np.float64,
atol=0, rtol=1e-7, only_r_linear=False):
"""
Checks an operator for algebraic consistency of its capabilities.
Checks whether times(), adjoint_times(), inverse_times() and
adjoint_inverse_times() (if in capability list) is implemented
consistently. Additionally, it checks whether the operator is linear.
Parameters
----------
op : LinearOperator
Operator which shall be checked.
domain_dtype : dtype
The data type of the random vectors in the operator's domain. Default
is `np.float64`.
target_dtype : dtype
The data type of the random vectors in the operator's target. Default
is `np.float64`.
atol : float
Absolute tolerance for the check. If rtol is specified,
then satisfying any tolerance will let the check pass.
Default: 0.
rtol : float
Relative tolerance for the check. If atol is specified,
then satisfying any tolerance will let the check pass.
Default: 0.
only_r_linear: bool
set to True if the operator is only R-linear, not C-linear.
This will relax the adjointness test accordingly.
"""
if not isinstance(op, LinearOperator):
raise TypeError('This test tests only linear operators.')
_domain_check(op)
_actual_domain_check_linear(op, domain_dtype)
_actual_domain_check_linear(op.adjoint, target_dtype)
_actual_domain_check_linear(op.inverse, target_dtype)
_actual_domain_check_linear(op.adjoint.inverse, domain_dtype)
_check_linearity(op, domain_dtype, atol, rtol)
_check_linearity(op.adjoint, target_dtype, atol, rtol)
_check_linearity(op.inverse, target_dtype, atol, rtol)
_check_linearity(op.adjoint.inverse, domain_dtype, atol, rtol)
_full_implementation(op, domain_dtype, target_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.adjoint, target_dtype, domain_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.inverse, target_dtype, domain_dtype, atol, rtol,
only_r_linear)
_full_implementation(op.adjoint.inverse, domain_dtype, target_dtype, atol,
rtol, only_r_linear)
def _get_acceptable_location(op, loc, lin): def _get_acceptable_location(op, loc, lin):
if not np.isfinite(lin.val.s_sum()): if not np.isfinite(lin.val.s_sum()):
raise ValueError('Initial value must be finite') raise ValueError('Initial value must be finite')
...@@ -255,34 +311,46 @@ def _linearization_value_consistency(op, loc): ...@@ -255,34 +311,46 @@ def _linearization_value_consistency(op, loc):
assert_allclose(fld0, fld1, 0, 1e-7) assert_allclose(fld0, fld1, 0, 1e-7)
def check_jacobian_consistency(op, loc, tol=1e-8, ntries=100, perf_check=True, def _check_nontrivial_constant(op, loc, tol, ntries, only_r_differentiable,
only_r_differentiable=True): metric_sampling):
""" return # FIXME
Checks the Jacobian of an operator against its finite difference # Assumes that the operator is not constant
approximation. if isinstance(op.domain, DomainTuple):
return
Computes the Jacobian with finite differences and compares it to the keys = op.domain.keys()
implemented Jacobian. for ll in range(0, len(keys)):
for cstkeys in combinations(keys, ll):
Parameters cstdom, vardom = {}, {}
---------- for kk, dd in op.domain.items():
op : Operator if kk in cstkeys:
Operator which shall be checked. cstdom[kk] = dd
loc : Field or MultiField else:
An Field or MultiField instance which has the same domain vardom[kk] = dd
as op. The location at which the gradient is checked cstdom, vardom = makeDomain(cstdom), makeDomain(vardom)
tol : float cstloc = loc.extract(cstdom)
Tolerance for the check.
perf_check : Boolean val0 = op(loc)
Do performance check. May be disabled for very unimportant operators. _, op0 = op.simplify_for_constant_input(cstloc)
only_r_differentiable : Boolean val1 = op0(loc)
Jacobians of C-differentiable operators need to be C-linear. val2 = op0(loc.unite(cstloc))
Default: True assert_equal(val1, val2)
""" assert_equal(val0, val1)
_domain_check(op)
_actual_domain_check_nonlinear(op, loc) lin = Linearization.make_var(loc, want_metric=True)
_performance_check(op, loc, bool(perf_check)) oplin = op0(lin)
_linearization_value_consistency(op, loc) if isinstance(op, EnergyOperator):
_allzero(oplin.gradient.extract(cstdom))
_allzero(oplin.jac(from_random(cstdom).unite(full(vardom, 0))))
if isinstance(op, EnergyOperator) and metric_sampling:
samp0 = oplin.metric.draw_sample()
_allzero(samp0.extract(cstdom))
_nozero(samp0.extract(vardom))
_jac_vs_finite_differences(op0, loc, tol, ntries, only_r_differentiable)
def _jac_vs_finite_differences(op, loc, tol, ntries, only_r_differentiable):
for _ in range(ntries): for _ in range(ntries):
lin = op(Linearization.make_var(loc)) lin = op(Linearization.make_var(loc))
loc2, lin2 = _get_acceptable_location(op, loc, lin) loc2, lin2 = _get_acceptable_location(op, loc, lin)
...@@ -307,8 +375,6 @@ def check_jacobian_consistency(op, loc, tol=1e-8, ntries=100, perf_check=True, ...@@ -307,8 +375,6 @@ def check_jacobian_consistency(op, loc, tol=1e-8, ntries=100, perf_check=True,
print(hist) print(hist)
raise ValueError("gradient and value seem inconsistent") raise ValueError("gradient and value seem inconsistent")
loc = locnext loc = locnext
check_linear_operator(linmid.jac, domain_dtype=loc.dtype,
ddtype = loc.values()[0].dtype if isinstance(loc, MultiField) else loc.dtype target_dtype=dirder.dtype,
tdtype = dirder.values()[0].dtype if isinstance(dirder, MultiField) else dirder.dtype only_r_linear=only_r_differentiable)
consistency_check(linmid.jac, domain_dtype=ddtype, target_dtype=tdtype,
only_r_linear=only_r_differentiable)
...@@ -32,13 +32,13 @@ ntries = 10 ...@@ -32,13 +32,13 @@ ntries = 10
def test_gaussian(field): def test_gaussian(field):
energy = ift.GaussianEnergy(domain=field.domain) energy = ift.GaussianEnergy(domain=field.domain)
ift.extra.check_jacobian_consistency(energy, field) ift.extra.check_operator(energy, field)
def test_ScaledEnergy(field): def test_ScaledEnergy(field):
icov = ift.ScalingOperator(field.domain, 1.2) icov = ift.ScalingOperator(field.domain, 1.2)
energy = ift.GaussianEnergy(inverse_covariance=icov, sampling_dtype=np.float64) energy = ift.GaussianEnergy(inverse_covariance=icov, sampling_dtype=np.float64)
ift.extra.check_jacobian_consistency(energy.scale(0.3), field) ift.extra.check_operator(energy.scale(0.3), field)
lin = ift.Linearization.make_var(field, want_metric=True) lin = ift.Linearization.make_var(field, want_metric=True)
met1 = energy(lin).metric met1 = energy(lin).metric
...@@ -54,17 +54,17 @@ def test_QuadraticFormOperator(field): ...@@ -54,17 +54,17 @@ def test_QuadraticFormOperator(field):
op = ift.ScalingOperator(field.domain, 1.2) op = ift.ScalingOperator(field.domain, 1.2)
endo = ift.makeOp(op.draw_sample_with_dtype(dtype=np.float64)) endo = ift.makeOp(op.draw_sample_with_dtype(dtype=np.float64))
energy = ift.QuadraticFormOperator(endo) energy = ift.QuadraticFormOperator(endo)
ift.extra.check_jacobian_consistency(energy, field) ift.extra.check_operator(energy, field)
def test_studentt(field): def test_studentt(field):
if isinstance(field.domain, ift.MultiDomain): if isinstance(field.domain, ift.MultiDomain):
return return
energy = ift.StudentTEnergy(domain=field.domain, theta=.5) energy = ift.StudentTEnergy(domain=field.domain, theta=.5)
ift.extra.check_jacobian_consistency(energy, field, tol=1e-6) ift.extra.check_operator(energy, field, tol=1e-6)
theta = ift.from_random(field.domain, 'normal').exp() theta = ift.from_random(field.domain, 'normal').exp()
energy = ift.StudentTEnergy(domain=field.domain, theta=theta) energy = ift.StudentTEnergy(domain=field.domain, theta=theta)
ift.extra.check_jacobian_consistency(energy, field, tol=1e-6, ntries=ntries) ift.extra.check_operator(energy, field, tol=1e-6, ntries=ntries)
def test_hamiltonian_and_KL(field): def test_hamiltonian_and_KL(field):
...@@ -72,10 +72,10 @@ def test_hamiltonian_and_KL(field): ...@@ -72,10 +72,10 @@ def test_hamiltonian_and_KL(field):
space = field.domain space = field.domain
lh = ift.GaussianEnergy(domain=space) lh = ift.GaussianEnergy(domain=space)
hamiltonian = ift.StandardHamiltonian(lh) hamiltonian = ift.StandardHamiltonian(lh)
ift.extra.check_jacobian_consistency(hamiltonian, field, ntries=ntries) ift.extra.check_operator(hamiltonian, field, ntries=ntries)
samps = [ift.from_random(space, 'normal') for i in range(2)] samps = [ift.from_random(space, 'normal') for i in range(2)]
kl = ift.AveragedEnergy(hamiltonian, samps) kl = ift.AveragedEnergy(hamiltonian, samps)
ift.extra.check_jacobian_consistency(kl, field, ntries=ntries) ift.extra.check_operator(kl, field, ntries=ntries)
def test_variablecovariancegaussian(field): def test_variablecovariancegaussian(field):
...@@ -84,7 +84,7 @@ def test_variablecovariancegaussian(field): ...@@ -84,7 +84,7 @@ def test_variablecovariancegaussian(field):
dc = {'a': field, 'b': field.ptw("exp")} dc = {'a': field, 'b': field.ptw("exp")}
mf = ift.MultiField.from_dict(dc) mf = ift.MultiField.from_dict(dc)
energy = ift.VariableCovarianceGaussianEnergy(field.domain, 'a', 'b', np.float64) energy = ift.VariableCovarianceGaussianEnergy(field.domain, 'a', 'b', np.float64)
ift.extra.check_jacobian_consistency(energy, mf, tol=1e-6, ntries=ntries) ift.extra.check_operator(energy, mf, tol=1e-6, ntries=ntries)
energy(ift.Linearization.make_var(mf, want_metric=True)).metric.draw_sample() energy(ift.Linearization.make_var(mf, want_metric=True)).metric.draw_sample()
...@@ -93,7 +93,7 @@ def test_specialgamma(field): ...@@ -93,7 +93,7 @@ def test_specialgamma(field):
return return
energy = ift.operators.energy_operators._SpecialGammaEnergy(field) energy = ift.operators.energy_operators._SpecialGammaEnergy(field)
loc = ift.from_random(energy.domain).exp() loc = ift.from_random(energy.domain).exp()
ift.extra.check_jacobian_consistency(energy, loc, tol=1e-6, ntries=ntries) ift.extra.check_operator(energy, loc, tol=1e-6, ntries=ntries)
energy(ift.Linearization.make_var(loc, want_metric=True)).metric.draw_sample() energy(ift.Linearization.make_var(loc, want_metric=True)).metric.draw_sample()
...@@ -105,7 +105,7 @@ def test_inverse_gamma(field): ...@@ -105,7 +105,7 @@ def test_inverse_gamma(field):
d = ift.random.current_rng().normal(10, size=space.shape)**2 d = ift.random.current_rng().normal(10, size=space.shape)**2
d = ift.Field(space, d) d = ift.Field(space, d)
energy = ift.InverseGammaLikelihood(d) energy = ift.InverseGammaLikelihood(d)
ift.extra.check_jacobian_consistency(energy, field, tol=1e-5) ift.extra.check_operator(energy, field, tol=1e-5)
def testPoissonian(field): def testPoissonian(field):
...@@ -116,7 +116,7 @@ def testPoissonian(field): ...@@ -116,7 +116,7 @@ def testPoissonian(field):
d = ift.random.current_rng().poisson(120, size=space.shape) d = ift.random.current_rng().poisson(120, size=space.shape)
d = ift.Field(space, d) d = ift.Field(space, d)
energy = ift.PoissonianEnergy(d) energy = ift.PoissonianEnergy(d)
ift.extra.check_jacobian_consistency(energy, field, tol=1e-6) ift.extra.check_operator(energy, field, tol=1e-6)
def test_bernoulli(field): def test_bernoulli(field):
...@@ -127,4 +127,4 @@ def test_bernoulli(field): ...@@ -127,4 +127,4 @@ def test_bernoulli(field):
d = ift.random.current_rng().binomial(1, 0.1, size=space.shape) d = ift.random.current_rng().binomial(1, 0.1, size=space.shape)
d = ift.Field(space, d) d = ift.Field(space, d)
energy = ift.BernoulliEnergy(d) energy = ift.BernoulliEnergy(d)
ift.extra.check_jacobian_consistency(energy, field, tol=1e-5) ift.extra.check_operator(energy, field, tol=1e-5)
...@@ -70,7 +70,7 @@ def test_gaussian_energy(space, nonlinearity, noise, seed): ...@@ -70,7 +70,7 @@ def test_gaussian_energy(space, nonlinearity, noise, seed):
N = None N = None
energy = ift.GaussianEnergy(d, N) @ d_model() energy = ift.GaussianEnergy(d, N) @ d_model()
ift.extra.check_jacobian_consistency( ift.extra.check_operator(
energy, xi0, ntries=ntries, tol=1e-6) energy, xi0, ntries=ntries, tol=1e-6)
...@@ -99,9 +99,9 @@ def testgaussianenergy_compatibility(cplx): ...@@ -99,9 +99,9 @@ def testgaussianenergy_compatibility(cplx):
np.testing.assert_equal(val0, val1) np.testing.assert_equal(val0, val1)
np.testing.assert_equal(val1, val2) np.testing.assert_equal(val1, val2)
ift.extra.check_jacobian_consistency(e, loc, ntries=ntries) ift.extra.check_operator(e, loc, ntries=ntries)
ift.extra.check_jacobian_consistency(e0, loc, ntries=ntries) ift.extra.check_operator(e0, loc, ntries=ntries, tol=1e-7)
ift.extra.check_jacobian_consistency(e1, loc, ntries=ntries) ift.extra.check_operator(e1, loc, ntries=ntries)
# Test jacobian is zero # Test jacobian is zero
lin = ift.Linearization.make_var(loc, want_metric=True) lin = ift.Linearization.make_var(loc, want_metric=True)
......
...@@ -61,7 +61,7 @@ def test_blockdiagonal(): ...@@ -61,7 +61,7 @@ def test_blockdiagonal():
op = ift.BlockDiagonalOperator( op = ift.BlockDiagonalOperator(
dom, {"d1": ift.ScalingOperator(dom["d1"], 20.)}) dom, {"d1": ift.ScalingOperator(dom["d1"], 20.)})
op2 = op(op) op2 = op(op)
ift.extra.consistency_check(op2) ift.extra.check_linear_operator(op2)
assert_equal(type(op2), ift.BlockDiagonalOperator) assert_equal(type(op2), ift.BlockDiagonalOperator)
f1 = op2(ift.full(dom, 1)) f1 = op2(ift.full(dom, 1))
for val in f1.values(): for val in f1.values():
......
...@@ -42,7 +42,7 @@ def testLOSResponse(sp, dtype): ...@@ -42,7 +42,7 @@ def testLOSResponse(sp, dtype):
sigma_low = 1e-4*ift.random.current_rng().standard_normal(10) sigma_low = 1e-4*ift.random.current_rng().standard_normal(10)
sigma_ups = 1e-5*ift.random.current_rng().standard_normal(10) sigma_ups = 1e-5*ift.random.current_rng().standard_normal(10)
op = ift.LOSResponse(sp, starts, ends, sigma_low, sigma_ups) op = ift.LOSResponse(sp, starts, ends, sigma_low, sigma_ups)
ift.extra.consistency_check(op, dtype, dtype) ift.extra.check_linear_operator(op, dtype, dtype)
@pmp('sp', _h_spaces + _p_spaces + _pow_spaces) @pmp('sp', _h_spaces + _p_spaces + _pow_spaces)
...@@ -50,13 +50,13 @@ def testOperatorCombinations(sp, dtype): ...@@ -50,13 +50,13 @@ def testOperatorCombinations(sp, dtype):
a = ift.DiagonalOperator(ift.Field.from_random(sp, "normal", dtype=dtype)) a = ift.DiagonalOperator(ift.Field.from_random(sp, "normal", dtype=dtype))
b = ift.DiagonalOperator(ift.Field.from_random(sp, "normal", dtype=dtype)) b = ift.DiagonalOperator(ift.Field.from_random(sp, "normal", dtype=dtype))
op = ift.SandwichOperator.make(a, b) op = ift.SandwichOperator.make(a, b)
ift.extra.consistency_check(op, dtype, dtype) ift.extra.check_linear_operator(op, dtype, dtype)
op = a(b) op = a(b)
ift.extra.consistency_check(op, dtype, dtype) ift.extra.check_linear_operator(op, dtype, dtype)
op = a + b op = a + b
ift.extra.consistency_check(op, dtype, dtype) ift.extra.check_linear_operator(op, dtype, dtype)
op = a - b op = a - b
ift.extra.consistency_check(op, dtype, dtype) ift.extra.check_linear_operator(op, dtype, dtype)