Skip to content

Commit f7bd286

Browse files
authored
IP and Q clarifications (#239)
1 parent 140f31e commit f7bd286

File tree

3 files changed

+60
-33
lines changed

3 files changed

+60
-33
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ v2.5.x
1010
""""""
1111

1212

13-
*latest*
14-
--------
13+
v2.5.1 IP/Q clarifications
14+
--------------------------
15+
16+
**2025-03-12**
17+
18+
19+
- Modelling routines ``ip_and_q``:
1520

16-
- Modelling routines: Add warning to ``ip_and_q`` if ``src_z!=rec_z``; not
17-
thoroughly tested.
21+
- Use the corresponding co-planar loop configuration for the primary field.
22+
- Add warning to it that it is experimental.
1823

1924

2025
v2.5.0 In-phase and quadrature

empymod/model.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,8 @@ def ip_and_q(**kwargs):
17751775
- 1st: with `xdirect=None` for the secondary field Hs.
17761776
- 2nd: with `xdirect=True`, and only the first value of all model
17771777
parameters and an empty `depth`-parameter for the primary field Hp.
1778+
For the primary field, the co-planar field of the source configuration is
1779+
used.
17781780
17791781
It then returns the real (in-phase) and imaginary (quadrature) components
17801782
of the ratio Hs/Hp, scaled by `scale`.
@@ -1786,9 +1788,17 @@ def ip_and_q(**kwargs):
17861788
This function is only implemented for frequency-domain data of magnetic
17871789
sources and receivers.
17881790
1789-
Warning: Only the case where source and receiver are at the same height has
1790-
been tested; if you encounter any issues with other configurations, please
1791-
let us know!
1791+
.. note::
1792+
1793+
This function is experimental. Please let us know if you encounter any
1794+
issues when using this function!
1795+
1796+
Also note that for the primary field computation, the co-planar field
1797+
of the source direction is used. Hence:
1798+
1799+
- Hp for ab=44 is used for ab in [44, 54, 64],
1800+
- Hp for ab=55 is used for ab in [45, 55, 65],
1801+
- Hp for ab=66 is used for ab in [46, 56, 66].
17921802
17931803
17941804
Parameters
@@ -1826,8 +1836,8 @@ def ip_and_q(**kwargs):
18261836
# Warning that it has not been thoroughly tested.
18271837
verb = kwargs.get('verb', 2)
18281838
if verb > 0 and not np.allclose(kwargs['src'][2], kwargs['rec'][2]):
1829-
print("* WARNING :: `src_z != rec_z`: has not been tested; "
1830-
"please report back any issues you might encounter.")
1839+
print("* WARNING :: This function is experimental. Please let us know "
1840+
"if you encounter any issues when using this function!")
18311841

18321842
# Get or set scale
18331843
scale = kwargs.pop('scale', 1e3)
@@ -1838,9 +1848,13 @@ def ip_and_q(**kwargs):
18381848
# Primary magnetic field
18391849
new = copy.deepcopy(kwargs)
18401850

1841-
# For PERP, ab=[46;64], Hp is zero; instead use Hp of the HCP config.
1842-
# Frischknecht et al., 1991, p. 111; doi: 10.1190/1.9781560802686.ch3.
1843-
new['ab'] = new['ab'] if new['ab'] not in [46, 64] else 66
1851+
# For the primary field, use the co-planar field of source configuration.
1852+
if new['ab'] in [44, 54, 64]:
1853+
new['ab'] = 44
1854+
elif new['ab'] in [45, 55, 65]:
1855+
new['ab'] = 55
1856+
elif new['ab'] in [46, 56, 66]:
1857+
new['ab'] = 66
18441858

18451859
# Take only the first value of each parameter, and set depth to empty.
18461860
new['depth'] = []

tests/test_model.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,21 +1079,21 @@ def test_ip_and_q(capsys):
10791079

10801080
# Status Quo
10811081
system = {
1082-
'src': [0, 0, -1],
1083-
'rec': [2, 0, -1],
1084-
'freqtime': [1.0, 100.0, 10000.0],
1085-
'ab': 66,
1086-
'verb': 1,
1082+
"src": [0, 0, -1],
1083+
"rec": [2, 0, -1],
1084+
"freqtime": [1.0, 100.0, 10000.0],
1085+
"ab": 66,
1086+
"verb": 1,
10871087
}
10881088

10891089
model1 = {
1090-
'depth': [0, 2, 5],
1091-
'res': [2e14, 50, 0.1, 50],
1092-
'aniso': [1, 1.2, 1, 1],
1093-
'epermH': [0, 1, 1.1, 1],
1094-
'epermV': [0, 1, 1, 1.1],
1095-
'mpermH': [1, 1, 1.5, 1],
1096-
'mpermV': [1, 1.1, 1, 1],
1090+
"depth": [0, 2, 5],
1091+
"res": [2e14, 50, 0.1, 50],
1092+
"aniso": [1, 1.2, 1, 1],
1093+
"epermH": [0, 1, 1.1, 1],
1094+
"epermV": [0, 1, 1, 1.1],
1095+
"mpermH": [1, 1, 1.5, 1],
1096+
"mpermV": [1, 1.1, 1, 1],
10971097
}
10981098

10991099
IP1, Q1 = model.ip_and_q(**model1, **system)
@@ -1104,26 +1104,34 @@ def test_ip_and_q(capsys):
11041104
assert_allclose(IP1*1e3, IP2)
11051105
assert_allclose(Q1*1e3, Q2)
11061106

1107+
IP3, Q3 = model.ip_and_q(**model1, **{**system, 'ab': 44})
1108+
assert_allclose(IP3, [-1.3563986, -1.38122726, -7.4560389])
1109+
assert_allclose(Q3, [-0.00299279869, -0.293418700, -3.40236993])
1110+
1111+
IP4, Q4 = model.ip_and_q(**model1, **{**system, 'ab': 55})
1112+
assert_allclose(IP4, [-10.74321713, -10.69222953, 3.62780845])
1113+
assert_allclose(Q4, [0.00663009305, 0.651225190, 9.52444857])
1114+
11071115
# Test errors
11081116
with pytest.raises(ValueError, match="Only implemented for magnetic"):
1109-
model.ip_and_q(**model1, **{**system, 'ab': 13})
1117+
model.ip_and_q(**model1, **{**system, "ab": 13})
11101118

11111119
with pytest.raises(ValueError, match="Only implemented for frequency"):
1112-
model.ip_and_q(**model1, **{**system, 'signal': 0})
1120+
model.ip_and_q(**model1, **{**system, "signal": 0})
11131121

11141122
with pytest.raises(ValueError, match="Only implemented for frequency"):
1115-
model.ip_and_q(**model1, **{**system, 'signal': 1})
1123+
model.ip_and_q(**model1, **{**system, "signal": 1})
11161124

11171125
# Fullspace - no secondary field -> zeros
1118-
model2 = {'depth': [0], 'res': [50, 50]}
1119-
IP3, Q3 = model.ip_and_q(**model2, **system)
1120-
assert_allclose(IP3, 0.0)
1121-
assert_allclose(Q3, 0.0)
1126+
model2 = {"depth": [0], "res": [50, 50]}
1127+
IP5, Q5 = model.ip_and_q(**model2, **system)
1128+
assert_allclose(IP5, 0.0)
1129+
assert_allclose(Q5, 0.0)
11221130

11231131
_, _ = capsys.readouterr()
1124-
_, _ = model.ip_and_q(**model1, **{**system, 'src': [0, 0, 0]})
1132+
_, _ = model.ip_and_q(**model1, **{**system, "src": [0, 0, 0]})
11251133
out, _ = capsys.readouterr()
1126-
assert 'has not been tested' in out
1134+
assert "This function is experimental" in out
11271135

11281136

11291137
def test_fem():

0 commit comments

Comments
 (0)