impedance.py
impedance.py copied to clipboard
insert a boundary in the frequency of RC and RQ elements
Is there a way to constrain the peak frequency value of RQ and RC circuits?
I've used this package for the last couple of years and I am loving it! And I love that you can specify bounds for each circuit element. However, from what I can see I think it is only possible to introduce boundaries on R, Q and n when it comes to CPE elements, and not their peak frequency. Is this the case or did I not notice the functionality?
Possible solution: I imagine the easiest solution would be to write a second fitting function that expects R, f and n as initial guesses for CPE, and then insert boundaries on those. Or define another circuit element, RQfreq, that has those initial parameters which can be costrained as usual. I did not look too deep into it as I am not sure if the functionality already exists Edit: it'd probably be necessary to write a RQ element where we specify the peak frequency, but I guess it'd need to return R Q and n.
Why I would want this: Recently I have began to also look into DRT to treat my data, as there's a ton of overlapping features in it, but I have some doubts on how precise the quantification is. A workaround would be to estimate the peak frequencies of each component via DRT (or even just a Bode plot...) and then run a standard ECM fit with strong constraints on the peak frequencies of RC and CPE elements. So far I have provided a guess of each R, and then have the script calculate the corresponding C to get the frequency I'd want, and use it as starting guess, but I am not sure how much it actually helped when two features are overlapping.
Thanks!
Follow up, this might be the RQ
def RQ(p, f):
""" defines an RQ element using R and peak frequency as inputs
Notes
-----
.. math::
Z = \\frac{R}{1+ R \\times Q \\times (d \\times j 2 \\pi f )^\\alpha}
where :math:`Q` is obtained from :math:`R` = p[0], :math:`peak_freq` = p[1] and :math:`\\alpha` = p[2].
"""
omega = 2*np.pi*np.array(f)
R, peak_freq, alpha = p[0], p[1], p[2]
Q = float((1/R)*(2*np.pi*peak_freq)**-alpha)
Z = R/(1+R*Q*(omega*1j)**alpha)
return Z
but I think it would need to returnZ as a function of R, Q and alpha in order to work with the current fitting method, and from what I understand curve_fit can't use a constraint like 1/(2piR1*Q1) = 1000 but it can only accept lower and upper values for R1 and Q1. Therefore, it would not be possible to introduce a constraint on the peak frequency.... But I am very much a beginner so feel free to correct me :) From what I read, lmfit should make it possible to introduce such a constraint, but it would require rewriting the fitting function?