Skip to content

Commit

Permalink
Implement tests
Browse files Browse the repository at this point in the history
  • Loading branch information
prisae committed Jun 29, 2024
1 parent a854e91 commit d72ae64
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 84 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
- python-version: "3.12"
name: full
os: ubuntu
conda: "numba scipy xarray tqdm h5py discretize matplotlib"
conda: "numba scipy xarray tqdm h5py discretize matplotlib pygimli"

env:
# Used for coveralls flag
Expand Down Expand Up @@ -105,7 +105,7 @@ jobs:
conda config --show-sources
conda config --show
conda info -a
conda install ${{ matrix.case.conda }} pytest pytest-cov pytest-console-scripts coveralls flake8 setuptools-scm
conda install -c conda-forge -c gimli ${{ matrix.case.conda }} pytest pytest-cov pytest-console-scripts coveralls flake8 setuptools-scm
- name: Conda list
shell: bash -l {0}
Expand Down
6 changes: 3 additions & 3 deletions emg3d/inversion/pygimli.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ def __init__(self, simulation, markers=None, pgthreads=2):

# Set markers.
if markers is not None:
mesh.setCellMarkers(markers.ravel('F'))
self.markers = markers
else:
self.markers = np.zeros(simulation.model.size, dtype=int)
self.markers = np.arange(simulation.model.size, dtype=int)
mesh.setCellMarkers(self.markers.ravel('F'))
# Store original props; required if a region is set to ``background``.
self._model = simulation.model.property_x.copy()
# Store volumes; required if a region is set to ``single``.
Expand All @@ -118,7 +118,7 @@ def __init__(self, simulation, markers=None, pgthreads=2):
self.setJacobian(self.J)

def response(self, model):
"""Create synthetic data for provided model."""
"""Create synthetic data for provided pyGIMLi model."""

# Clean emg3d-simulation, so things are recomputed
self.simulation.clean('computed')
Expand Down
243 changes: 165 additions & 78 deletions tests/test_pygimli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# import os
import pytest
import logging
import numpy as np
# from numpy.testing import assert_allclose
from numpy.testing import assert_allclose

import emg3d
from emg3d.inversion import pygimli as ipygimli
Expand All @@ -16,90 +16,177 @@
import discretize
except ImportError:
discretize = None
try:
import h5py
except ImportError:
h5py = False
try:
import pygimli
except ImportError:
pygimli = False
pygimli = None


LOGGER = logging.getLogger(__name__)


@pytest.mark.skipif(xarray is None, reason="xarray not installed.")
@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
class TestPygimli():

survey = emg3d.surveys.Survey(
sources=emg3d.TxElectricDipole((0, 0, -250, 0, 0)),
receivers=emg3d.RxElectricPoint((0, 0, -1250, 0, 0)),
frequencies=1.0,
noise_floor=1e-17,
relative_error=0.05,
)

hx = np.ones(3)*500.0
grid = emg3d.TensorMesh([hx, hx, hx], [-750, -750, -1500])

model_start = emg3d.Model(grid, 1.0, mapping='Conductivity')
model_true = emg3d.Model(grid, 1.0, mapping='Conductivity')
model_true.property_x[1, 1, 1] = 1/1000

# Create an emg3d Simulation instance
sim = emg3d.simulations.Simulation(
survey=survey.copy(),
model=model_true,
gridding='both',
max_workers=1,
gridding_opts={'center_on_edge': False},
receiver_interpolation='linear',
solver_opts={'tol_gradient': 1e-3},
tqdm_opts=False,
)
sim.compute(observed=True)
sim.clean('computed')

sim.model = model_start

sim.compute()
sim.survey.data['start'] = sim.survey.data.synthetic
sim.clean('computed')

sim.tol_gradient = 1e-2 # Reduce further
model_start = sim.model.copy()
grid = model_true.grid

markers = np.zeros(model_start.shape, dtype=int)
markers[1, 1, 1] = 1

# Without regions
fop = ipygimli.Kernel(simulation=sim, pgthreads=1)

INV = ipygimli.Inversion(fop=fop)
INV.inv.setCGLSTolerance(10)
INV.inv.setMaxCGLSIter(30)

errmodel = INV.run(maxIter=2, lam=0.10)

markers = np.zeros(model_start.shape, dtype=int)
markers[1, 1, 1] = 1
markers[0, :, :] = 2
markers[2, :, :] = 3

# With regions
fop = ipygimli.Kernel(simulation=sim, markers=markers, pgthreads=1)

INV = ipygimli.Inversion(fop=fop)
INV.inv.setCGLSTolerance(10)
INV.inv.setMaxCGLSIter(30)

INV.fop.setRegionProperties(1, limits=(0.0001, 2), startModel=1.0)
INV.fop.setRegionProperties(0, background=True)
INV.fop.setRegionProperties(2, fix=True, startModel=1)
INV.fop.setRegionProperties(
3, single=True, limits=(0.99999, 1.00001), startModel=1.0)

errmodel = INV.run(maxIter=2, lam=1)
if xarray is not None:
# Create data
survey = emg3d.surveys.Survey(
sources=emg3d.TxElectricDipole((0, 0, -250, 0, 0)),
receivers=emg3d.RxElectricPoint((0, 0, -1250, 0, 0)),
frequencies=1.0,
noise_floor=1e-17,
relative_error=0.05,
)

hx = np.ones(3)*500.0
grid = emg3d.TensorMesh([hx, hx, hx], [-750, -750, -1500])

model_start = emg3d.Model(grid, 1.0, mapping='Conductivity')
model_true = emg3d.Model(grid, 1.0, mapping='Conductivity')
model_true.property_x[1, 1, 1] = 1/1000

# Create an emg3d Simulation instance
sim = emg3d.simulations.Simulation(
survey=survey.copy(),
model=model_true,
gridding='both',
max_workers=1,
gridding_opts={'center_on_edge': False},
receiver_interpolation='linear',
solver_opts={'tol_gradient': 1e-2},
tqdm_opts=False,
)
sim.compute(observed=True)
synthetic = sim.survey.data.synthetic.copy()
sim.clean('computed')

sim.model = model_start

sim.compute()
sim.survey.data['start'] = sim.survey.data.synthetic
sim.clean('computed')

markers = np.zeros(sim.model.shape, dtype=int)
markers[1, 1, 1] = 1
markers[0, :, :] = 2
markers[2, :, :] = 3

def set_regions(self, fop):
fop.setRegionProperties(1, limits=(0.0001, 2), startModel=1.0)
fop.setRegionProperties(0, background=True)
fop.setRegionProperties(2, fix=True, startModel=1)
fop.setRegionProperties(
3, single=True, limits=(0.99999, 1.00001), startModel=1.0)

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
def test_Kernel_errors(self):

sim = self.sim.copy()
sim.model = emg3d.Model(sim.model.grid, mapping='Resistivity')
with pytest.raises(NotImplementedError, match='for Resistivity'):
_ = ipygimli.Kernel(simulation=sim)

sim.model = emg3d.Model(sim.model.grid, 1, 2)
with pytest.raises(NotImplementedError, match='for HTI'):
_ = ipygimli.Kernel(simulation=sim)

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
def test_Kernel_markers(self):

# No regions
sim = self.sim.copy()
fop = ipygimli.Kernel(simulation=sim)
assert_allclose(fop.markers, np.arange(sim.model.size, dtype=int))
assert fop.fullmodel is True

# Regions
fop = ipygimli.Kernel(simulation=sim, markers=self.markers)
self.set_regions(fop)
assert_allclose(fop.markers, self.markers)
assert fop.fullmodel is False

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
def test_Kernel_conversions(self):
sim = self.sim.copy()
fop1 = ipygimli.Kernel(simulation=sim)
fop2 = ipygimli.Kernel(simulation=sim, markers=self.markers)
self.set_regions(fop2)

for fop in [fop1, fop2]:

assert_allclose(
fop.model2emg3d(fop.createStartModel()),
sim.model.property_x
)

assert_allclose(
sim.data.observed,
fop.data2emg3d(fop.data2gimli(sim.data.observed.data))
)

assert_allclose(
sim.model.property_x,
fop.model2emg3d(fop.model2gimli(sim.model.property_x))
)
data = sim.survey.standard_deviation.data
assert fop.data2gimli(data).dtype == np.float64

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
def test_Kernel_response(self):
sim = self.sim.copy()
sim.model = self.model_true
fop = ipygimli.Kernel(simulation=sim)
assert_allclose(
fop.data2emg3d(fop.response(fop.createStartModel())),
self.synthetic.data
)

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
@pytest.mark.skipif(discretize is None, reason="discretize not installed.")
def test_Inversion_noregions(self, caplog):
# Mainly "runtest"
sim = self.sim.copy()

fop = ipygimli.Kernel(simulation=sim, pgthreads=1)

INV = ipygimli.Inversion(fop=fop)
INV.inv.setCGLSTolerance(10)
INV.inv.setMaxCGLSIter(30)

_ = INV.run(maxIter=2, lam=0.1)

assert 'pyGIMLi(emg3d)' in caplog.text
assert 'Created startmodel from forward operator: 27' in caplog.text
assert 'λ = 0.1' in caplog.text

assert INV.inv.chi2() < 1

@pytest.mark.skipif(pygimli is None, reason="pygimli not installed.")
@pytest.mark.skipif(discretize is None, reason="discretize not installed.")
def test_Inversion_regions(self, caplog):
# Mainly "runtest"
sim = self.sim.copy()

fop = ipygimli.Kernel(
simulation=sim, markers=self.markers, pgthreads=1)

INV = ipygimli.Inversion(fop=fop)
INV.inv.setCGLSTolerance(10)
INV.inv.setMaxCGLSIter(30)

INV.fop.setRegionProperties(1, limits=(0.0001, 2), startModel=1.0)
INV.fop.setRegionProperties(0, background=True)
INV.fop.setRegionProperties(2, fix=True, startModel=1)
INV.fop.setRegionProperties(
3, single=True, limits=(0.99999, 1.00001), startModel=1.0)

_ = INV.run(maxIter=2, lam=1)

assert 'pyGIMLi(emg3d)' in caplog.text
assert 'Created startmodel from region infos: 2' in caplog.text
assert 'λ = 1.0' in caplog.text

assert INV.inv.chi2() < 1


def test_all_dir():
Expand Down
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_Report(capsys):
# We just ensure the shown packages do not change (core and optional).
out1 = utils.Report()
out2 = scooby.Report(
core=['numpy', 'scipy', 'numba', 'emg3d'],
core=['numpy', 'scipy', 'numba', 'emg3d', 'empymod'],
optional=['empymod', 'xarray', 'discretize', 'h5py',
'matplotlib', 'tqdm', 'IPython'],
ncol=4)
Expand Down

0 comments on commit d72ae64

Please sign in to comment.