Skip to content

Commit

Permalink
Add modulus-weighted fit option (#185)
Browse files Browse the repository at this point in the history
* Add modulus-weighted fit option

* add test on modulus-weighted option
  • Loading branch information
stephendkang authored Oct 19, 2021
1 parent 06fd26d commit 34715ff
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 3 deletions.
12 changes: 10 additions & 2 deletions impedance/models/circuits/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ def __eq__(self, other):
else:
raise TypeError('Comparing object is not of the same type.')

def fit(self, frequencies, impedance, bounds=None, **kwargs):
def fit(self, frequencies, impedance, bounds=None,
weight_by_modulus=False, **kwargs):
""" Fit the circuit model
Parameters
Expand All @@ -73,6 +74,11 @@ def fit(self, frequencies, impedance, bounds=None, **kwargs):
parameters of 0 and np.inf, except the CPE alpha
which has an upper bound of 1
weight_by_modulus : bool, optional
Uses the modulus of each data (|Z|) as the weighting factor.
Standard weighting scheme when experimental variances are
unavailable. Only applicable when global_opt = False
kwargs :
Keyword arguments passed to
impedance.models.circuits.fitting.circuit_fit,
Expand Down Expand Up @@ -108,7 +114,9 @@ def fit(self, frequencies, impedance, bounds=None, **kwargs):
parameters, conf = circuit_fit(frequencies, impedance,
self.circuit, self.initial_guess,
constants=self.constants,
bounds=bounds, **kwargs)
bounds=bounds,
weight_by_modulus=weight_by_modulus,
**kwargs)
self.parameters_ = parameters
if conf is not None:
self.conf_ = conf
Expand Down
13 changes: 12 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, global_opt=False, **kwargs):
bounds=None, weight_by_modulus=False, global_opt=False,
**kwargs):

""" Main function for fitting an equivalent circuit to data.
Expand Down Expand Up @@ -103,6 +104,11 @@ def circuit_fit(frequencies, impedances, circuit, initial_guess, constants={},
parameters of 0 and np.inf, except the CPE alpha
which has an upper bound of 1
weight_by_modulus : bool, optional
Uses the modulus of each data (|Z|) as the weighting factor.
Standard weighting scheme when experimental variances are unavailable.
Only applicable when global_opt = False
global_opt : bool, optional
If global optimization should be used (uses the basinhopping
algorithm). Defaults to False
Expand Down Expand Up @@ -137,6 +143,11 @@ def circuit_fit(frequencies, impedances, circuit, initial_guess, constants={},
if 'ftol' not in kwargs:
kwargs['ftol'] = 1e-13

# weighting scheme for fitting
if weight_by_modulus:
abs_Z = np.abs(Z)
kwargs['sigma'] = np.hstack([abs_Z, abs_Z])

popt, pcov = curve_fit(wrapCircuit(circuit, constants), frequencies,
np.hstack([Z.real, Z.imag]),
p0=initial_guess, bounds=bounds, **kwargs)
Expand Down
7 changes: 7 additions & 0 deletions impedance/tests/test_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ def test_circuit_fit():
constants={})[0],
results_local_weighted, 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)

# Test global fitting on multiple seeds
# All seeds should converge to the same parameter values
# seed = 0 (default)
Expand Down

0 comments on commit 34715ff

Please sign in to comment.