Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement: proportional weighting option #267

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion impedance/models/circuits/fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def set_default_bounds(circuit, constants={}):


def circuit_fit(frequencies, impedances, circuit, initial_guess, constants={},
bounds=None, weight_by_modulus=False, global_opt=False,
bounds=None, weight_by_modulus=False,
weight_proportionally=False, global_opt=False,
**kwargs):

""" Main function for fitting an equivalent circuit to data.
Expand Down Expand Up @@ -109,6 +110,10 @@ def circuit_fit(frequencies, impedances, circuit, initial_guess, constants={},
Standard weighting scheme when experimental variances are unavailable.
Only applicable when global_opt = False

weight_proportionally : bool, optional
Uses the Re(Z), Im(Z) components as the weighting factor.
Only applicable when global_opt = False and weight_by_modulus = False

global_opt : bool, optional
If global optimization should be used (uses the basinhopping
algorithm). Defaults to False
Expand Down Expand Up @@ -148,6 +153,8 @@ def circuit_fit(frequencies, impedances, circuit, initial_guess, constants={},
if weight_by_modulus:
abs_Z = np.abs(Z)
kwargs['sigma'] = np.hstack([abs_Z, abs_Z])
elif weight_proportionally and not weight_by_modulus:
kwargs['sigma'] = np.hstack([Z.real, Z.imag])

popt, pcov = curve_fit(wrapCircuit(circuit, constants), f,
np.hstack([Z.real, Z.imag]),
Expand Down
27 changes: 23 additions & 4 deletions impedance/tests/test_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ def test_circuit_fit():
6.31e-2, 2.33e2, 2.20e-1])
results_local_bounds = results_local.copy()
results_local_bounds[5] = 2.38e2
results_local_weighted = np.array([1.64e-2, 9.06e-3, 3.06,
5.29e-3, 1.45e-1, 1.32e3, 2.02e-1])
results_local_weighted_m = np.array([1.64e-2, 9.06e-3, 3.06,
5.29e-3, 1.45e-1, 1.32e3, 2.02e-1])
results_local_weighted_p = np.array([1.687e-2, 8.763e-3, 3.613, 5.194e-3,
1.225e-1, 9.510e+2, 2.891e-1])

results_global = np.array([1.65e-2, 5.34e-3, 0.22, 9.15e-3,
1.31e-1, 1.10e3, 2.78])
Expand Down Expand Up @@ -103,14 +105,31 @@ def test_circuit_fit():
Z_correct_filtered, circuit,
initial_guess, sigma=sigma,
constants={})[0],
results_local_weighted, rtol=1e-2)
results_local_weighted_m, rtol=1e-2)

# Test if using weight_by_modulus=True produces the same results
assert np.allclose(circuit_fit(example_frequencies_filtered,
Z_correct_filtered, circuit,
initial_guess, weight_by_modulus=True,
constants={})[0],
results_local_weighted, rtol=1e-2)
results_local_weighted_m, rtol=1e-2)

# Test local fitting with predefined weights
# Use Z components as weights
sigma = np.hstack((np.real(Z_correct_filtered),
np.imag(Z_correct_filtered)))
assert np.allclose(circuit_fit(example_frequencies_filtered,
Z_correct_filtered, circuit,
initial_guess, sigma=sigma,
constants={})[0],
results_local_weighted_p, rtol=1e-2)

# Test if using weight_proportionally=True produces the same results
assert np.allclose(circuit_fit(example_frequencies_filtered,
Z_correct_filtered, circuit,
initial_guess, weight_proportionally=True,
constants={})[0],
results_local_weighted_p, rtol=1e-2)

# Test global fitting on multiple seeds
# All seeds should converge to the same parameter values
Expand Down