Commit bf947d1b authored by Martin Reinecke's avatar Martin Reinecke

Merge branch 'cf_wo_asperity' into 'NIFTy_7'

Allow for opting out of asperity and flexibility

See merge request !556
parents 2e872c5d 9dc11964
Pipeline #77882 passed with stages
in 26 minutes and 6 seconds
Changes since NIFTy 6 Changes since NIFTy 6
===================== =====================
CorrelatedFieldMaker interface change
-------------------------------------
The interface of `ift.CorrelatedFieldMaker.make` and
`ift.CorrelatedFieldMaker.add_fluctuations` changed; it now expects the mean
and the standard deviation of their various parameters not as separate
arguments but as a tuple.
Furthermore, it is now possible to disable the asperity and the flexibility
together with the asperity in the correlated field model. Note that disabling
only the flexibility is not possible.
SimpleCorrelatedField
---------------------
A simplified version of the correlated field model was introduced which does not
allow for multiple power spectra, the presence of a degree of freedom parameter
`dofdex`, or `total_N` larger than zero. Except for the above mentioned
limitations, it is equivalent to `ift.CorrelatedFieldMaker`. Hence, if one
wants to understand the implementation idea behind the model, it is easier to
grasp from reading `ift.SimpleCorrelatedField` than from going through
`ift.CorrelatedFieldMaker`.
Change in external dependencies Change in external dependencies
------------------------------- -------------------------------
...@@ -20,7 +43,7 @@ The implementation tests for nonlinear operators are now available in ...@@ -20,7 +43,7 @@ The implementation tests for nonlinear operators are now available in
MetricGaussianKL interface MetricGaussianKL interface
-------------------------- --------------------------
Users do not instanciate `MetricGaussianKL` by its constructor anymore. Rather Users do not instantiate `MetricGaussianKL` by its constructor anymore. Rather
`MetricGaussianKL.make()` shall be used. `MetricGaussianKL.make()` shall be used.
...@@ -91,10 +114,10 @@ New approach for sampling complex numbers ...@@ -91,10 +114,10 @@ New approach for sampling complex numbers
When calling draw_sample_with_dtype with a complex dtype, When calling draw_sample_with_dtype with a complex dtype,
the variance is now used for the imaginary part and real part separately. the variance is now used for the imaginary part and real part separately.
This is done in order to be consistent with the Hamiltonian. This is done in order to be consistent with the Hamiltonian.
Note that by this, Note that by this,
``` ```
np.std(ift.from_random(domain, 'normal', dtype=np.complex128).val) np.std(ift.from_random(domain, 'normal', dtype=np.complex128).val)
```` ````
does not give 1, but sqrt(2) as a result. does not give 1, but sqrt(2) as a result.
......
...@@ -73,10 +73,10 @@ def main(): ...@@ -73,10 +73,10 @@ def main():
sp2 = ift.RGSpace(npix2) sp2 = ift.RGSpace(npix2)
# Set up signal model # Set up signal model
cfmaker = ift.CorrelatedFieldMaker.make(0., 1e-2, 1e-6, '') cfmaker = ift.CorrelatedFieldMaker.make(0., (1e-2, 1e-6), '')
cfmaker.add_fluctuations(sp1, 0.1, 1e-2, 1, .1, .01, .5, -2, 1., 'amp1') cfmaker.add_fluctuations(sp1, (0.1, 1e-2), (1, .1), (.01, .5), (-2, 1.), 'amp1')
cfmaker.add_fluctuations(sp2, 0.1, 1e-2, 1, .1, .01, .5, cfmaker.add_fluctuations(sp2, (0.1, 1e-2), (1, .1), (.01, .5),
-1.5, .5, 'amp2') (-1.5, .5), 'amp2')
correlated_field = cfmaker.finalize() correlated_field = cfmaker.finalize()
A1 = cfmaker.normalized_amplitudes[0] A1 = cfmaker.normalized_amplitudes[0]
......
...@@ -92,7 +92,7 @@ from .library.correlated_fields_simple import SimpleCorrelatedField ...@@ -92,7 +92,7 @@ from .library.correlated_fields_simple import SimpleCorrelatedField
from . import extra from . import extra
from .utilities import memo, frozendict from .utilities import memo, frozendict, myassert
from .logger import logger from .logger import logger
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
from itertools import combinations from itertools import combinations
import numpy as np import numpy as np
from numpy.testing import assert_
from .domain_tuple import DomainTuple from .domain_tuple import DomainTuple
from .field import Field from .field import Field
...@@ -29,6 +28,7 @@ from .operators.energy_operators import EnergyOperator ...@@ -29,6 +28,7 @@ from .operators.energy_operators import EnergyOperator
from .operators.linear_operator import LinearOperator from .operators.linear_operator import LinearOperator
from .operators.operator import Operator from .operators.operator import Operator
from .sugar import from_random from .sugar import from_random
from .utilities import myassert
__all__ = ["check_linear_operator", "check_operator", __all__ = ["check_linear_operator", "check_operator",
"assert_allclose"] "assert_allclose"]
...@@ -137,20 +137,6 @@ def assert_equal(f1, f2): ...@@ -137,20 +137,6 @@ 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
...@@ -206,32 +192,32 @@ def _domain_check_linear(op, domain_dtype=None, inp=None): ...@@ -206,32 +192,32 @@ def _domain_check_linear(op, domain_dtype=None, inp=None):
inp = from_random(op.domain, "normal", dtype=domain_dtype) inp = from_random(op.domain, "normal", dtype=domain_dtype)
elif inp is None: elif inp is None:
raise ValueError('Need to specify either dtype or inp') raise ValueError('Need to specify either dtype or inp')
assert_(inp.domain is op.domain) myassert(inp.domain is op.domain)
assert_(op(inp).domain is op.target) myassert(op(inp).domain is op.target)
def _domain_check_nonlinear(op, loc): def _domain_check_nonlinear(op, loc):
_domain_check(op) _domain_check(op)
assert_(isinstance(loc, (Field, MultiField))) myassert(isinstance(loc, (Field, MultiField)))
assert_(loc.domain is op.domain) myassert(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)
reslin = op(lin) reslin = op(lin)
assert_(lin.domain is op.domain) myassert(lin.domain is op.domain)
assert_(lin.target is op.domain) myassert(lin.target is op.domain)
assert_(lin.val.domain is lin.domain) myassert(lin.val.domain is lin.domain)
assert_(reslin.domain is op.domain) myassert(reslin.domain is op.domain)
assert_(reslin.target is op.target) myassert(reslin.target is op.target)
assert_(reslin.val.domain is reslin.target) myassert(reslin.val.domain is reslin.target)
assert_(reslin.target is op.target) myassert(reslin.target is op.target)
assert_(reslin.jac.domain is reslin.domain) myassert(reslin.jac.domain is reslin.domain)
assert_(reslin.jac.target is reslin.target) myassert(reslin.jac.target is reslin.target)
assert_(lin.want_metric == reslin.want_metric) myassert(lin.want_metric == reslin.want_metric)
_domain_check_linear(reslin.jac, inp=loc) _domain_check_linear(reslin.jac, inp=loc)
_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) myassert(reslin.metric.domain is reslin.metric.target)
assert_(reslin.metric.domain is op.domain) myassert(reslin.metric.domain is op.domain)
def _domain_check(op): def _domain_check(op):
......
This diff is collapsed.
...@@ -78,7 +78,7 @@ class SimpleCorrelatedField(Operator): ...@@ -78,7 +78,7 @@ class SimpleCorrelatedField(Operator):
xi = ducktape(dom, None, prefix + 'spectrum') xi = ducktape(dom, None, prefix + 'spectrum')
shift = np.ones(dom.shape) shift = np.ones(dom.shape)
shift[0] = _log_vol(pspace)**2/12. shift[0] = _log_vol(pspace)**2 / 12.
shift = makeField(dom, shift) shift = makeField(dom, shift)
if asperity is None: if asperity is None:
asp = makeOp(shift.ptw("sqrt")) @ (xi*sig_flex) asp = makeOp(shift.ptw("sqrt")) @ (xi*sig_flex)
......
...@@ -405,3 +405,10 @@ def lognormal_moments(mean, sigma, N=0): ...@@ -405,3 +405,10 @@ def lognormal_moments(mean, sigma, N=0):
logsigma = np.sqrt(np.log1p((sigma / mean)**2)) logsigma = np.sqrt(np.log1p((sigma / mean)**2))
logmean = np.log(mean) - logsigma**2 / 2 logmean = np.log(mean) - logsigma**2 / 2
return logmean, logsigma return logmean, logsigma
def myassert(val):
"""Safe alternative to python's assert statement which is active even if
`__debug__` is False."""
if not val:
raise AssertionError
...@@ -17,9 +17,10 @@ ...@@ -17,9 +17,10 @@
import numpy as np import numpy as np
import pytest import pytest
from numpy.testing import assert_, assert_allclose, assert_raises from numpy.testing import assert_allclose, assert_raises
import nifty7 as ift import nifty7 as ift
from nifty7 import myassert
from .common import setup_function, teardown_function from .common import setup_function, teardown_function
...@@ -55,13 +56,13 @@ def test_kl(constants, point_estimates, mirror_samples, mf): ...@@ -55,13 +56,13 @@ def test_kl(constants, point_estimates, mirror_samples, mf):
ift.MetricGaussianKL.make(**args) ift.MetricGaussianKL.make(**args)
return return
kl = ift.MetricGaussianKL.make(**args) kl = ift.MetricGaussianKL.make(**args)
assert_(len(ic.history) > 0) myassert(len(ic.history) > 0)
assert_(len(ic.history) == len(ic.history.time_stamps)) myassert(len(ic.history) == len(ic.history.time_stamps))
assert_(len(ic.history) == len(ic.history.energy_values)) myassert(len(ic.history) == len(ic.history.energy_values))
ic.history.reset() ic.history.reset()
assert_(len(ic.history) == 0) myassert(len(ic.history) == 0)
assert_(len(ic.history) == len(ic.history.time_stamps)) myassert(len(ic.history) == len(ic.history.time_stamps))
assert_(len(ic.history) == len(ic.history.energy_values)) myassert(len(ic.history) == len(ic.history.energy_values))
locsamp = kl._local_samples locsamp = kl._local_samples
if isinstance(mean0, ift.MultiField): if isinstance(mean0, ift.MultiField):
...@@ -74,7 +75,7 @@ def test_kl(constants, point_estimates, mirror_samples, mf): ...@@ -74,7 +75,7 @@ def test_kl(constants, point_estimates, mirror_samples, mf):
# Test number of samples # Test number of samples
expected_nsamps = 2*nsamps if mirror_samples else nsamps expected_nsamps = 2*nsamps if mirror_samples else nsamps
assert_(len(tuple(kl.samples)) == expected_nsamps) myassert(len(tuple(kl.samples)) == expected_nsamps)
# Test value # Test value
assert_allclose(kl.value, klpure.value) assert_allclose(kl.value, klpure.value)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import numpy as np import numpy as np
import pytest import pytest
from numpy.testing import assert_, assert_allclose from numpy.testing import assert_allclose
import nifty7 as ift import nifty7 as ift
from .common import setup_function, teardown_function from .common import setup_function, teardown_function
...@@ -44,7 +44,7 @@ def test_special_gradients(): ...@@ -44,7 +44,7 @@ def test_special_gradients():
assert_allclose( assert_allclose(
_lin2grad(ift.Linearization.make_var(0*f).ptw("sinc")), np.zeros(s.shape)) _lin2grad(ift.Linearization.make_var(0*f).ptw("sinc")), np.zeros(s.shape))
assert_(np.isnan(_lin2grad(ift.Linearization.make_var(0*f).ptw("abs")))) ift.myassert(np.isnan(_lin2grad(ift.Linearization.make_var(0*f).ptw("abs"))))
assert_allclose( assert_allclose(
_lin2grad(ift.Linearization.make_var(0*f + 10).ptw("abs")), _lin2grad(ift.Linearization.make_var(0*f + 10).ptw("abs")),
np.ones(s.shape)) np.ones(s.shape))
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
import numpy as np import numpy as np
import pytest import pytest
from mpi4py import MPI from mpi4py import MPI
from numpy.testing import assert_, assert_equal, assert_raises from numpy.testing import assert_equal, assert_raises
import nifty7 as ift import nifty7 as ift
...@@ -84,8 +84,8 @@ def test_kl(constants, point_estimates, mirror_samples, mode, mf): ...@@ -84,8 +84,8 @@ def test_kl(constants, point_estimates, mirror_samples, mode, mf):
# Test number of samples # Test number of samples
expected_nsamps = 2*nsamps if mirror_samples else nsamps expected_nsamps = 2*nsamps if mirror_samples else nsamps
assert_(len(tuple(kl0.samples)) == expected_nsamps) ift.myassert(len(tuple(kl0.samples)) == expected_nsamps)
assert_(len(tuple(kl1.samples)) == expected_nsamps) ift.myassert(len(tuple(kl1.samples)) == expected_nsamps)
# Test value # Test value
assert_equal(kl0.value, kl1.value) assert_equal(kl0.value, kl1.value)
......
...@@ -16,14 +16,16 @@ ...@@ -16,14 +16,16 @@
# #
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
from numpy.testing import assert_, assert_allclose
import numpy as np
from copy import deepcopy from copy import deepcopy
import numpy as np
from numpy.testing import assert_allclose
import nifty7 as ift import nifty7 as ift
class CountingOp(ift.Operator): class CountingOp(ift.Operator):
#FIXME: Not a LinearOperator since ChainOps not supported yet # FIXME: Not a LinearOperator since ChainOps not supported yet
def __init__(self, domain): def __init__(self, domain):
self._domain = self._target = ift.sugar.makeDomain(domain) self._domain = self._target = ift.sugar.makeDomain(domain)
self._count = 0 self._count = 0
...@@ -56,6 +58,6 @@ def test_operator_tree_optimiser(): ...@@ -56,6 +58,6 @@ def test_operator_tree_optimiser():
op_orig = deepcopy(op) op_orig = deepcopy(op)
op = ift.operator_tree_optimiser._optimise_operator(op) op = ift.operator_tree_optimiser._optimise_operator(op)
assert_allclose(op(fld).val, op_orig(fld).val, rtol=np.finfo(np.float64).eps) assert_allclose(op(fld).val, op_orig(fld).val, rtol=np.finfo(np.float64).eps)
assert_(1 == ( (cop4.count-1) * cop3.count * cop2.count * cop1.count)) ift.myassert(1 == ((cop4.count-1) * cop3.count * cop2.count * cop1.count))
# test testing # test testing
ift.optimise_operator(op_orig) ift.optimise_operator(op_orig)
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import numpy as np import numpy as np
import pytest import pytest
from numpy.testing import assert_, assert_allclose from numpy.testing import assert_allclose
import nifty7 as ift import nifty7 as ift
...@@ -71,11 +71,11 @@ def testAmplitudesInvariants(sspace, N): ...@@ -71,11 +71,11 @@ def testAmplitudesInvariants(sspace, N):
astds = 0.2, 1.2 astds = 0.2, 1.2
offset_std_mean = 1.3 offset_std_mean = 1.3
fa = ift.CorrelatedFieldMaker.make(1.2, offset_std_mean, 1e-2, '', N, fa = ift.CorrelatedFieldMaker.make(1.2, (offset_std_mean, 1e-2), '', N,
dofdex1) dofdex1)
fa.add_fluctuations(sspace, astds[0], 1e-2, 1.1, 2., 2.1, .5, -2, 1., fa.add_fluctuations(sspace, (astds[0], 1e-2), (1.1, 2.), (2.1, .5), (-2, 1.),
'spatial', dofdex=dofdex2) 'spatial', dofdex=dofdex2)
fa.add_fluctuations(fsspace, astds[1], 1e-2, 3.1, 1., .5, .1, -4, 1., fa.add_fluctuations(fsspace, (astds[1], 1e-2), (3.1, 1.), (.5, .1), (-4, 1.),
'freq', dofdex=dofdex3) 'freq', dofdex=dofdex3)
op = fa.finalize() op = fa.finalize()
...@@ -103,19 +103,19 @@ def testAmplitudesInvariants(sspace, N): ...@@ -103,19 +103,19 @@ def testAmplitudesInvariants(sspace, N):
assert_allclose(slice_fluct_std0, sl_fluct_space, rtol=0.5) assert_allclose(slice_fluct_std0, sl_fluct_space, rtol=0.5)
assert_allclose(slice_fluct_std1, sl_fluct_freq, rtol=0.5) assert_allclose(slice_fluct_std1, sl_fluct_freq, rtol=0.5)
fa = ift.CorrelatedFieldMaker.make(0., offset_std_mean, .1, '', N, dofdex1) fa = ift.CorrelatedFieldMaker.make(0., (offset_std_mean, .1), '', N, dofdex1)
fa.add_fluctuations(fsspace, astds[1], 1., 3.1, 1., .5, .1, -4, 1., 'freq', fa.add_fluctuations(fsspace, (astds[1], 1.), (3.1, 1.), (.5, .1), (-4, 1.), 'freq',
dofdex=dofdex3) dofdex=dofdex3)
m = 3. m = 3.
x = fa.moment_slice_to_average(m) x = fa.moment_slice_to_average(m)
fa.add_fluctuations(sspace, x, 1.5, 1.1, 2., 2.1, .5, -2, 1., 'spatial', 0, fa.add_fluctuations(sspace, (x, 1.5), (1.1, 2.), (2.1, .5), (-2, 1.), 'spatial', 0,
dofdex=dofdex2) dofdex=dofdex2)
op = fa.finalize() op = fa.finalize()
em, estd = _stats(fa.slice_fluctuation(0), samples) em, estd = _stats(fa.slice_fluctuation(0), samples)
assert_allclose(m, em, rtol=0.5) assert_allclose(m, em, rtol=0.5)
assert_(op.target[-2] == sspace) assert op.target[-2] == sspace
assert_(op.target[-1] == fsspace) assert op.target[-1] == fsspace
for ampl in fa.normalized_amplitudes: for ampl in fa.normalized_amplitudes:
ift.extra.check_operator(ampl, 0.1*ift.from_random(ampl.domain), ntries=10) ift.extra.check_operator(ampl, 0.1*ift.from_random(ampl.domain), ntries=10)
...@@ -124,71 +124,59 @@ def testAmplitudesInvariants(sspace, N): ...@@ -124,71 +124,59 @@ def testAmplitudesInvariants(sspace, N):
@pmp('seed', [42, 31]) @pmp('seed', [42, 31])
@pmp('domain', spaces) @pmp('domain', spaces)
def test_complicated_vs_simple(seed, domain): @pmp('without', (('asperity', ), ('flexibility', ), ('flexibility', 'asperity')))
def test_complicated_vs_simple(seed, domain, without):
with ift.random.Context(seed): with ift.random.Context(seed):
offset_mean = _rand() offset_mean = _rand()
offset_std_mean = _posrand() offset_std = _posrand(), _posrand()
offset_std_std = _posrand() fluctuations = _posrand(), _posrand()
fluctuations_mean = _posrand() if "flexibility" in without:
fluctuations_stddev = _posrand() flexibility = None
flexibility_mean = _posrand() else:
flexibility_stddev = _posrand() flexibility = _posrand(), _posrand()
asperity_mean = _posrand() if "asperity" in without:
asperity_stddev = _posrand() asperity = None
loglogavgslope_mean = _posrand() else:
loglogavgslope_stddev = _posrand() asperity = _posrand(), _posrand()
loglogavgslope = _posrand(), _posrand()
prefix = 'foobar' prefix = 'foobar'
hspace = domain.get_default_codomain() hspace = domain.get_default_codomain()
scf = ift.SimpleCorrelatedField( scf_args = (
domain, domain,
offset_mean, (offset_std_mean, offset_std_std), offset_mean,
(fluctuations_mean, fluctuations_stddev), offset_std,
(flexibility_mean, flexibility_stddev), fluctuations,
(asperity_mean, asperity_stddev), flexibility,
(loglogavgslope_mean, loglogavgslope_stddev), asperity,
prefix=prefix, loglogavgslope
harmonic_partner=hspace) )
cfm = ift.CorrelatedFieldMaker.make(offset_mean, offset_std_mean, add_fluct_args = (
offset_std_std, prefix) domain,
cfm.add_fluctuations(domain, fluctuations,
fluctuations_mean, flexibility,
fluctuations_stddev, asperity,
flexibility_mean, loglogavgslope
flexibility_stddev, )
asperity_mean, cfm = ift.CorrelatedFieldMaker.make(offset_mean, offset_std, prefix)
asperity_stddev, if asperity is not None and flexibility is None:
loglogavgslope_mean, with pytest.raises(ValueError):
loglogavgslope_stddev, scf = ift.SimpleCorrelatedField(*scf_args, prefix=prefix,
prefix='', harmonic_partner=hspace)
with pytest.raises(ValueError):
cfm.add_fluctuations(*add_fluct_args, prefix='',
harmonic_partner=hspace)
return
scf = ift.SimpleCorrelatedField(*scf_args, prefix=prefix,
harmonic_partner=hspace)
cfm.add_fluctuations(*add_fluct_args, prefix='',
harmonic_partner=hspace) harmonic_partner=hspace)
inp = ift.from_random(scf.domain) inp = ift.from_random(scf.domain)
op1 = cfm.finalize() op1 = cfm.finalize()
assert_(scf.domain is op1.domain) assert scf.domain is op1.domain
ift.extra.assert_allclose(scf(inp), op1(inp)) ift.extra.assert_allclose(scf(inp), op1(inp))
ift.extra.check_operator(scf, inp, ntries=10) ift.extra.check_operator(scf, inp, ntries=10)
op1 = cfm.amplitude op1 = cfm.amplitude
op0 = scf.amplitude op0 = scf.amplitude
assert_(op0.domain is op1.domain) assert op0.domain is op1.domain
ift.extra.assert_allclose(op0.force(inp), op1.force(inp)) ift.extra.assert_allclose(op0.force(inp), op1.force(inp))
@pmp('asperity', [None, (_posrand(), _posrand())])
@pmp('flexibility', [None, (_posrand(), _posrand())])
def test_simple_without_asp_fluct(asperity, flexibility):
domain = ift.RGSpace((4, 4), (0.123, 0.4))
offset_mean = _rand()
offset_std = _posrand(), _posrand()
fluctuations = _posrand(), _posrand()
loglogavgslope = _posrand(), _posrand()
prefix = 'foobar'
hspace = domain.get_default_codomain()
args = (domain, offset_mean, offset_std, fluctuations, flexibility,
asperity, loglogavgslope, prefix, hspace)
if asperity is not None and flexibility is None:
with pytest.raises(ValueError):
scf = ift.SimpleCorrelatedField(*args)
else:
scf = ift.SimpleCorrelatedField(*args)
inp = ift.from_random(scf.domain)
ift.extra.check_operator(scf, inp, ntries=10)
...@@ -17,10 +17,10 @@ ...@@ -17,10 +17,10 @@
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
import numpy as np import numpy as np
from numpy.testing import assert_, assert_allclose from numpy.testing import assert_allclose
import nifty7 as ift import nifty7 as ift
from nifty7.extra import check_operator, check_linear_operator from nifty7.extra import check_linear_operator, check_operator
from ..common import list2fixture, setup_function, teardown_function from ..common import list2fixture, setup_function, teardown_function
...@@ -42,7 +42,7 @@ def test_linear_einsum_outer(space1, space2, dtype, n_invocations=10): ...@@ -42,7 +42,7 @@ def test_linear_einsum_outer(space1, space2, dtype, n_invocations=10):
ss = "i,ij,j->ij" ss = "i,ij,j->ij"