linKK not working as intended[BUG]
See original GitHub issueI tried replicating results from the Schonleber et al. paper this module is based on, but found some key differences to their results. The focus, for now, will be on Figure 3 from the paper.
To Reproduce First, I simulated a circuit for their IS1 data using parameters listed in Table 1 of the paper.
import numpy as np
import matplotlib.pyplot as plt
from impedance.circuits import CustomCircuit
from impedance.plotting import plot_nyquist
from impedance.validation import linKK
circ = 'R1-p(R2,C3)-p(R4,E5)'
vals = [100, 200, 0.8e-6, 500, 0.4e-3, 0.5]
f = np.logspace(7,-6, num=131)
IS1 = CustomCircuit(circ, initial_guess=vals)
Z_IS1 = IS1.predict(f)
fig, ax = plt.subplots()
plot_nyquist(ax, f, Z_IS1)
ax.set_ylim(0, 400)
ax.set_xlim(0, 900)
plt.show()
Compare this result: To Figure 2 in the paper:
It looks pretty close, though a quantitative comparison is difficult without their data.
Now, add noise to IS1 to get IS1a:
sigma_a = 1000
Z_IS1a = (Z_IS1.real + np.abs(Z_IS1)/sigma_a) + 1j *(Z_IS1.imag + np.abs(Z_IS1)/sigma_a)
And use manual mode of linKK to fit with M=6 (“Underfitting”) and M=104 (“Overfitting”)
IS1a_uf = linKK(f, Z_IS1a, c=None, max_M=6)
IS1a_of = linKK(f, Z_IS1a, c=None, max_M=104)
fig, ax =plt.subplots()
plot_nyquist(ax, f, Z_IS1a, fmt='.')
plot_nyquist(ax, f, IS1a_uf[2], fmt='-')
plot_nyquist(ax, f, IS1a_of[2], fmt='--')
ax.set_ylim(0, 400)
ax.set_xlim(0, 900)
ax.legend(labels=('IS1a', 'Underfitting', 'Overfitting'))
plt.show()
fig, (ax0, ax1) =plt.subplots(nrows=2, figsize=(6,6))
ax0.plot(np.log10(f), IS1a_uf[3], '-', label=r'$\Delta_{Re}$')
ax0.plot(np.log10(f), IS1a_uf[4], '--', label=r'$\Delta_{Im}$')
ax1.plot(np.log10(f), IS1a_of[3], '-', label=r'$\Delta_{Re}$')
ax1.plot(np.log10(f), IS1a_of[4], '--', label=r'$\Delta_{Im}$')
ax0.set_ylim(-.12, .12)
ax1.set_ylim(-.12, .12)
ax0.set_xlim(-6, 6)
ax1.set_xlim(-6, 6)
ax1.set_xlabel('log(f) / Hz')
ax0.locator_params(axis='y', nbins=3, tight=True)
ax1.locator_params(axis='y', nbins=3, tight=True)
ax0.locator_params(axis='x', nbins=3, tight=True)
ax1.locator_params(axis='x', nbins=3, tight=True)
ax0.legend()
ax1.legend()
ax0.grid(True)
ax1.grid(True)
plt.show()
Compared to their result:
Notably, the first visible arc in the “underfitting” case from impedance.py linKK is much larger than their figure. Further, the residuals lines have the same general shape but don’t quantitatively agree – most easily seen by comparing the residuals lines at log(f) = 0.
I believe this behavior arises from the way impedanc.py linKK calculates the distribution of time constants using linear frequencies (vs radial frequencies as used in the paper).
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
Wow @BGerwe this is a fantastic write up of your exploration 🚀 thanks for working on getting this implemented correctly!!!
sounds good! 😎