Kramers-Kronig testing
A collection of functions and classes for performing Kramers-Kronig tests on data sets.
Functions
- pyimpspec.perform_kramers_kronig_test(data, test='real', num_RC=0, add_capacitance=True, add_inductance=True, admittance=None, min_log_F_ext=-1.0, max_log_F_ext=1.0, log_F_ext=0.0, num_F_ext_evaluations=20, rapid_F_ext_evaluations=True, cnls_method='leastsq', max_nfev=0, timeout=60, num_procs=-1, **kwargs)
Performs linear Kramers-Kronig tests, attempts to automatically find a suitable extension of the time constant range, optionally suggests the appropriate immittance representation to test, and automatically suggests the optimal number of RC elements to use. The results can be used to check the validity of an impedance spectrum before performing equivalent circuit fitting. This function acts as a wrapper for
evaluate_log_F_ext()
,suggest_num_RC_limits()
,suggest_num_RC()
, andsuggest_representation()
.References:
M. Schönleber, D. Klotz, and E. Ivers-Tiffée, 2014, Electrochim. Acta, 131, 20-27
V. Yrjänä and J. Bobacka, 2024, Electrochim. Acta, 504, 144951
- Parameters:
data (
DataSet
) – The data set to be tested.test (str, optional) – Supported values include “complex”, “imaginary”, “real”, “complex-inv”, “imaginary-inv”, “real-inv”, and “cnls”. The first three correspond to the complex, imaginary, real tests, respectively, described by Boukamp (1995). These three implementations use least squares fitting (see numpy.linalg.lstsq). The implementations ending with “-inv” use matrix inversion, which was the default in pyimpspec prior to version 5.0.0. The “cnls” implementation uses complex non-linear least squares fitting.
num_RC (int, optional) – The number of RC elements to use. A value greater than or equal to one results in the specific number of RC elements being tested. Otherwise, the number of RC elements is determined automatically.
add_capacitance (bool, optional) – Add an additional capacitance in series (or in parallel if
admittance=True
) with the rest of the circuit.add_inductance (bool, optional) – Add an additional inductance in series (or in parallel if
admittance=True
) with the rest of the circuit.admittance (Optional[bool], optional) – If True, then perform the test(s) using the admittance data (\(Y = \frac{1}{Z}\)) instead of the impedance data (\(Z\)). Each representation uses a different equivalent circuit model: Fig. 1 for impedance and Fig. 13 for admittance (Boukamp, 1995). Operating on the admittance data may be necessary in some cases such as when there is a negative differential resistance. If set to None, then both representations are used and the
suggest_representation()
is used to pick one.min_log_F_ext (float, optional) – The lower limit for \(\log{F_{\rm ext}}\), which extends or contracts the range of time constants.
max_log_F_ext (float, optional) – The upper limit for \(\log{F_{\rm ext}}\), which extends or contracts the range of time constants.
log_F_ext (float, optional) – If
num_F_ext_evaluations == 0
, thenlog_F_ext
is used directly as the value for \(\log{F_{\rm ext}}\).num_F_ext_evaluations (int, optional) – The maximum number of evaluations to perform when trying to automatically estimate the optimal \(\log{F_{\rm ext}}\). Values greater than zero cause an approach based on splitting the range of logarithmic extensions into evenly spaced parts, estimating where the minimum is, and evaluating additional points near that minimum. Values less than zero cause an approach based on using the differential evolution algorithm to find the minimum. A value of zero causes
log_F_ext
to be used directly as \(\log{F_{\rm ext}}\).rapid_F_ext_evaluations (bool, optional) – If possible, minimize the number of time constants that are tested when evaluating extensions in order to perform the optimization faster.
cnls_method (str, optional) – The iterative method used to perform the fitting. Only relevant when performing “cnls” tests.
max_nfev (int, optional) – The maximum number of function evaluations. If less than one, then no limit is imposed. Only relevant when performing “cnls” tests.
timeout (int, optional) – The maximum amount of time in seconds to spend performing tests. Only relevant when performing “cnls” tests.
num_procs (int, optional) – The number of parallel processes to use when performing tests. Only relevant when performing “cnls” tests.
**kwargs – Additional keyword arguments are passed on to the algorithms that are used when automatically determining an optimal number of RC elements.
- Returns:
A single linear Kramers-Kronig test result representing the suggested extension of the range of time constants, the suggested number of RC elements (i.e., time constants), and the suggested representation of the immittance spectrum to test.
- Return type:
- pyimpspec.perform_exploratory_kramers_kronig_tests(data, test='real', num_RCs=None, add_capacitance=True, add_inductance=True, admittance=None, min_log_F_ext=-1.0, max_log_F_ext=1.0, log_F_ext=0.0, num_F_ext_evaluations=20, rapid_F_ext_evaluations=True, cnls_method='leastsq', max_nfev=0, timeout=60, num_procs=-1, **kwargs)
Similar to
perform_kramers_kronig_test()
but returns some intermediate results rather than only the finalKramersKronigResult
. This function acts as a wrapper forevaluate_log_F_ext()
,suggest_num_RC()
, andsuggest_representation()
.References:
M. Schönleber, D. Klotz, and E. Ivers-Tiffée, 2014, Electrochim. Acta, 131, 20-27
V. Yrjänä and J. Bobacka, 2024, Electrochim. Acta, 504, 144951
- Parameters:
data (
DataSet
) – The data set to be tested.test (str, optional) – See
perform_kramers_kronig_test()
for details.num_RCs (Optional[List[int]], optional) – A list of integers of the various numbers of RC elements to test. If a None value is provided (i.e., the default), then the range of values to test is determined automatically.
add_capacitance (bool, optional) – See
perform_kramers_kronig_test()
for details.add_inductance (bool, optional) – See
perform_kramers_kronig_test()
for details.admittance (bool, optional) – See
perform_kramers_kronig_test()
for details.min_log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.max_log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.num_F_ext_evaluations (int, optional) – See
perform_kramers_kronig_test()
for details.rapid_F_ext_evaluations (bool, optional) – See
perform_kramers_kronig_test()
for details.cnls_method (str, optional) – See
perform_kramers_kronig_test()
for details.max_nfev (int, optional) – See
perform_kramers_kronig_test()
for details.timeout (int, optional) – See
perform_kramers_kronig_test()
for details.num_procs (int, optional) – See
perform_kramers_kronig_test()
for details.**kwargs – See
perform_kramers_kronig_test()
for details.
- Returns:
A tuple containing a list of
KramersKronigResult
and the corresponding result ofsuggest_num_RC()
for the suggested extension of the range of time constants and the suggested representation of the immittance spectrum to test.- Return type:
Tuple[List[
KramersKronigResult
], Tuple[KramersKronigResult
, Dict[int, float], int, int]]
- pyimpspec.analysis.kramers_kronig.evaluate_log_F_ext(data, test='real', num_RCs=None, add_capacitance=True, add_inductance=True, admittance=False, min_log_F_ext=-1.0, max_log_F_ext=1.0, log_F_ext=0.0, num_F_ext_evaluations=20, rapid_F_ext_evaluations=True, cnls_method='leastsq', max_nfev=0, timeout=60, num_procs=-1, **kwargs)
Evaluates extensions (or contractions) of the range of time constants in order to find an optimum. Linear Kramers-Kronig tests are performed at various ranges of time constants. The limits of the default range are defined by the reciprocals of the maximum and minimum excitation frequencies. The lower and upper limits of the extended (or contracted) ranges are defined as \(\tau_{\rm min} = 1/(F_{\rm ext}\omega_{\rm max})\) and \(\tau_{\rm max} = F_{\rm ext}/\omega_{\rm min}\), respectively.
References:
- Parameters:
data (
DataSet
) – The data set to be tested.test (str, optional) – See
perform_kramers_kronig_test()
for details.num_RCs (Optional[List[int]], optional) – See
perform_exploratory_kramers_kronig_tests()
for details.add_capacitance (bool, optional) – See
perform_kramers_kronig_test()
for details.add_inductance (bool, optional) – See
perform_kramers_kronig_test()
for details.admittance (bool, optional) – Perform the linear Kramers-Kronig test on the admittance representation instead of the impedance representation.
min_log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.max_log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.log_F_ext (float, optional) – See
perform_kramers_kronig_test()
for details.num_F_ext_evaluations (int, optional) – See
perform_kramers_kronig_test()
for details.rapid_F_ext_evaluations (bool, optional) – See
perform_kramers_kronig_test()
for details.cnls_method (str, optional) – See
perform_kramers_kronig_test()
for details.max_nfev (int, optional) – See
perform_kramers_kronig_test()
for details.timeout (int, optional) – See
perform_kramers_kronig_test()
for details.num_procs (int, optional) – See
perform_kramers_kronig_test()
for details.**kwargs
- Returns:
A list of tuples containing:
The extension in terms of decades beyond the default range.
A list of linear Kramers-Kronig test results performed with a different number of RC elements (i.e., time constants).
The statistic indicating the quality of the extension (the smaller the better).
The list of tuples is sorted from best to worst. The list of
KramersKronigResult
instances within each tuple is sorted from lowest to highest number of RC elements, and the optimal number of RC elements still needs to be determined.- Return type:
List[Tuple[float, List[
KramersKronigResult
], float]]
- pyimpspec.analysis.kramers_kronig.suggest_num_RC(tests, lower_limit=0, upper_limit=0, limit_delta=0, methods=None, use_mean=False, use_ranking=False, use_sum=False, **kwargs)
Suggest the optimal number of RC elements to use as part of the linear Kramers-Kronig test by applying one or more of the following methods:
1: \(\mu\)-criterion (Schönleber et al., 2014). With optional modifications that are enabled by default (Yrjänä and Bobacka, 2024).
2: The norm of the fitted variables (Plank et al., 2022).
3: The norm of the curvatures across the fitted impedance spectrum (Plank et al., 2022). With optional modifications that are enabled by default (Yrjänä and Bobacka, 2024).
4: The number of sign changes across the curvatures of the fitted impedance spectrum (Plank et al., 2022). With optional modifications that are enabled by default (Yrjänä and Bobacka, 2024).
5: The mean distance between sign changes across the curvatures of the fitted impedance spectrum (Yrjänä and Bobacka, 2024).
6: The apex of a \(\log{\Sigma_{k=1}^{N_\tau} |\tau_k / R_k|}\) (or \(\log{\Sigma_{k=1}^{N_\tau} |\tau_k / C_k|}\)) versus the number of RC elements (Yrjänä and Bobacka, 2024).
If multiple methods are used, then one of several approaches can be used to determine which number of RC elements to suggest:
Each method suggests a number of RC elements and the mean is chosen.
Each method ranks the different numbers of RC elements, exponentially decreasing points are assigned based on rank, the points assigned by each method are summed up, and the highest-scoring number of RC elements is chosen.
Each method returns a relative score from 0.0 to 1.0 (worst to best), the relative scores are added up, and the highest-scoring number of RC elements is chosen.
If no methods are chosen, then the default approach is used:
Use method 4 to obtain an initial list of candidates.
Use method 3 to reduce the list of candidates.
Use method 5 to reduce the list of candidates, if necessary.
Use \(\chi^2_{\rm ps}\) to reduce the list of candidates, if necessary.
Try to find a lower number of RC elements with a lower \(\chi^2_{\rm ps}\) and an equal number or fewer sign changes among the curvatures.
If the lower and/or upper limit is not specified, then
suggest_num_RC_limits()
is used to estimate the limit(s).References:
M. Schönleber, D. Klotz, and E. Ivers-Tiffée, 2014, Electrochim. Acta, 131, 20-27
V. Yrjänä and J. Bobacka, 2024, Electrochim. Acta, 504, 144951
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – See
suggest_num_RC_limits()
for details.upper_limit (int, optional) – See
suggest_num_RC_limits()
for details.limit_delta (int, optional) – See
suggest_num_RC_limits()
for details.methods (Optional[List[int]], optional) – A list of integers corresponding to the supported methods.
use_mean (bool, optional) – If true, then the mean value of the number of RC elements suggested by each of the selected methods is chosen.
use_ranking (bool, optional) – If true, then each selected method ranks the numbers of RC elements, a score is assigned based on ranking, and the highest-scoring number of RC elements is chosen.
use_sum (bool, optional) – If true, then the scores returned by each of the selected methods are summed up and the highest-scoring number of RC elements is chosen.
**kwargs – Keyword arguments are passed on to the underlying methods.
- Returns:
A tuple containing:
The
KramersKronigResult
corresponding to the suggested number of RC elements.A dictionary that maps the number of RC elements to their corresponding scores.
The lower limit for the number of RC elements to consider.
The upper limit for the number of RC elements to consider.
- Return type:
Tuple[
KramersKronigResult
, Dict[int, float], int, int]
- pyimpspec.analysis.kramers_kronig.suggest_num_RC_limits(tests, lower_limit=0, upper_limit=0, limit_delta=0, threshold=4.0)
Suggest lower and upper limits for the range of number of time constants where the optimal number of time constants should be looked for. The lower limit is the point at which incrementing the number of time constants no longer significantly improves the fit. The upper limit is suggested based on the mean distances between sign changes of the curvatures and when those drop below a threshold.
References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce if this value is greater than zero. If this value is set to zero, then the lower limit is automatically estimated. If this value is less than zero, then no lower limit is enforced.
upper_limit (int, optional) – The upper limit to enforce if this value is greater than zero. If this value is set to zero, then the upper limit is automatically estimated. If this value is less than zero, then no upper limit is enforced.
limit_delta (int, optional) – Alternative way of defining the upper limit as lower limit + delta. Only used if the value is greater than zero.
threshold (float, optional) – The threshold for the mean distance between curvature sign changes. This value is used when estimating the upper limit.
- Returns:
The suggested lower and upper limits for the number of RC elements where the optimal number of RC elements is likely to exist. Values outside these limits are likely to result in under- or overfitting.
- Return type:
Tuple[int, int]
- pyimpspec.analysis.kramers_kronig.suggest_representation(suggestions)
Suggest the most appropriate representation (impedance or admittance) of the immittance spectrum that was tested. If the difference between \(\chi^2_{\rm ps}\) values is greater than 0.5 decades, then the representation that provides the best fit is picked. Otherwise, the representations are scored according to various criteria:
One point to whichever has the lowest number of RC elements.
One point to whichever has the lowest lower limit for the number of RC elements.
One point to whichever comes closest to having the imaginary part of each frequency extreme reach zero.
The tuple in the input list that corresponds to the representation with the highest score is returned.
References:
- Parameters:
suggestions (List[Tuple[
KramersKronigResult
, Dict[int, float], int, int]]) – A list obtained by processing List[KramersKronigResult
] for different representations withsuggest_num_RC()
and collecting the return values.- Returns:
A tuple containing:
The
KramersKronigResult
corresponding to the suggested number of RC elements and representation.A dictionary that maps the number of RC elements to their corresponding scores for the suggested representation.
The lower limit for the number of RC elements to consider for the suggested representation.
The upper limit for the number of RC elements to consider for the suggested representation.
- Return type:
Tuple[
KramersKronigResult
, Dict[int, float], int, int]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_1(tests, lower_limit=0, upper_limit=0, mu_criterion=0.85, beta=0.75, relative_scores=True)
The value \(\mu\) describes the ratio of the total mass of negative resistances to the total mass of positive resistances:
\(\mu = 1 - \frac{\Sigma_{R_k < 0} |R_k|}{\Sigma_{R_k \geq 0} |R_k|}\)
\(\mu\) ranges from 0.0 to 1.0 and these extremes represent overfitting and underfitting, respectively. Overfitting manifests as an oscillating fitted impedance spectrum, which is made possible by a mix of positive and negative resistances. The number of RC elements is incremented until the corresponding \(\mu\) drops below the threshold \(\mu_{\rm crit}\).
The first modification is to adapt the equation above for use with validation of immittance data in the admittance representation:
\(\mu = 1 - \frac{\Sigma_{C_k < 0} |C_k|}{\Sigma_{C_k \geq 0} |C_k|}\)
The denominator can be less than one, so the calculated values are clamped to only range from 0.0 to 1.0.
The second modification is that the iteration is done in reverse (i.e., by decrementing the number of RC elements instead of incrementing it) since there can be significant fluctuation of \(\mu\) at low numbers of RC elements, which can cause the iterative process to stop too early.
The third modification is to calculate an additional score, \(S\), as follows:
\(S = \frac{-\log{\chi^2_{\rm ps}}}{{\left(\mu_{\rm crit} - \mu\right)}^{\beta}}\)
The exponent \(\beta\) is determined heuristically and a value of 0.75 seems to work well. Only \(\mu\) values less than \(\mu_{\rm crit}\) are considered when calculating \(S\). The use of this score helps to deal with the fluctuation that affects the use of \(\mu\) directly. If \(\beta\) is set to zero, then the second and third modification are skipped.
If \(\mu\) is negative, then an alternative approach is used whereby a logistic function is fitted to a plot of \(\mu\) versus the number of RC elements. The intercept (rounded up) of the slope at the midpoint of that function and a line at the highest point of the function is used to pick the optimal number of RC elements.
The returned dictionary maps the number of RC elements to a score ranging from 0.0 to 1.0 with the latter representing the highest-ranking candidate.
References:
M. Schönleber, D. Klotz, and E. Ivers-Tiffée, 2014, Electrochim. Acta, 131, 20-27
V. Yrjänä and J. Bobacka, 2024, Electrochim. Acta, 504, 144951
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
mu_criterion (float, optional) – The \(\mu_{\rm crit}\) to apply. Schönleber et al. (2014) recommended 0.85 based on their experiences. If a value less than zero is provided, then the alternative approach based on fitting a logistic function to pick the optimal number of RC elements is used.
beta (float, optional) – Exponent used to tweak the influence of the proximity of \(\mu\) to \(\mu_{\rm crit}\) when calculating scores. If set to zero, then the iteration direction is not reversed and the score \(S\) is not calculated.
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_2(tests, lower_limit=0, upper_limit=0, relative_scores=True)
Suggest the optimal number of RC elements to use based on the norm of the fitted variables divided by the number of RC elements. Growing norms are used as indications of underfitting and overfitting. Thus, a minimum of the norm of the fitted variables should coincide with the desired optimum.
References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_3(tests, lower_limit=0, upper_limit=0, subdivision=4, subdivided_frequencies=None, curvatures=None, relative_scores=True)
Suggest the optimal number of RC elements to use based on the norm of the curvatures of the fitted impedance spectrum. The curvatures at each point of the fitted impedance spectrum is approximated using an osculating circle. A minimum of the norm of these curvatures should coincide with the desired optimum.
A modification whereby the frequency intervals are subdivided before determining curvatures is used to make the method less prone to suggesting circuits that produce oscillating impedance spectra. This modified approach is used by default, but the original approach can be used by setting
subdivision = 0
.References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
subdivision (int, optional) – If greater than zero, then that number of additional frequencies are inserted into each frequency interval.
subdivided_frequencies (Optional[Frequencies], optional) – Frequencies that have already been subdivided. If multiple methods that require subdividing frequencies will be used, then this provides a means of reusing those frequencies.
curvatures (Optional[Dict[int, NDArray[float64]]], optional) – Curvatures that have already been estimated. If multiple methods that require curvatures will be used, then this provides a means of reusing those curvatures.
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_4(tests, lower_limit=0, upper_limit=0, subdivision=4, subdivided_frequencies=None, curvatures=None, offset_factor=0.1, relative_scores=True)
Suggest the optimal number of RC elements to use based on the number of sign changes of curvatures of the fitted impedance spectrum. The curvatures at each point of the fitted impedance spectrum is approximated using an osculating circle. An increasing number of sign changes of these curvatures results from oscillations brought on by overfitting. Thus, a minimum of the number of sign changes should coincide with the desired optimum.
The method is modified by subdividing the frequency intervals, which makes the method less prone to suggesting circuits that produce oscillating impedance spectra. Small offsets are also added to the number of sign changes based on the corresponding pseudo chi-squared values in order to act as tiebreakers in case there are multiple numbers of RC elements that correspond to the same number of sign changes. This modified approach is used by default, but the original approach can be used by setting
subdivision = 0
andoffset_factor = 0.0
.References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
subdivision (int, optional) – If greater than zero, then that number of additional frequencies are inserted into each frequency interval.
subdivided_frequencies (Optional[Frequencies], optional) – Frequencies that have already been subdivided. If multiple methods that require subdividing frequencies will be used, then this provides a means of reusing those frequencies.
curvatures (Optional[Dict[int, NDArray[float64]]], optional) – Curvatures that have already been estimated. If multiple methods that require curvatures will be used, then this provides a means of reusing those curvatures.
offset_factor (float, optional) – The factor that an offset is multiplied by when it is being added to a number of sign changes. Must be in the range [0.0, 1.0).
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_5(tests, lower_limit=0, upper_limit=0, subdivision=4, subdivided_frequencies=None, curvatures=None, relative_scores=True)
Suggest the optimal number of RC elements to use based on the average distance between sign changes of the curvatures of the fitted impedance spectrum. The curvatures at each point of the fitted impedance spectrum is approximated using an osculating circle. The largest average distance should occur at the lowest number of RC elements, but the optimum coincides with a local maximum at an intermediate number of RC elements. The average distance will tend towards one as the number of RC elements is incremented further.
References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
subdivision (int, optional) – If greater than zero, then that number of additional frequencies are inserted into each frequency interval.
subdivided_frequencies (Optional[Frequencies], optional) – Frequencies that have already been subdivided. If multiple methods that require subdividing frequencies will be used, then this provides a means of reusing those frequencies.
curvatures (Optional[Dict[int, NDArray[float64]]], optional) – Curvatures that have already been estimated. If multiple methods that require curvatures will be used, then this provides a means of reusing those curvatures.
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.suggest_num_RC_method_6(tests, lower_limit=0, upper_limit=0, relative_scores=True)
Suggest the optimal number of RC elements to use based on the approximate position of the apex in a plot of \(\log{\Sigma_{k=1}^{N_\tau} |\tau_k / R_k|}\) versus the number of RC elements. If the tests were performed on the admittance representation of the immittance data, then \(C_k\) is substituted for \(R_k\). The sum grows initially as the number of RC elements increases. However, the magnitudes of the fitted \(R_k\) (or \(C_k\)) also tend to increase, which causes the magnitudes of the corresponding \(C_k\) (or \(R_k\)) to decrease. Thus, the sum begins to decline despite the increasing number of RC elements and the fitted impedance spectrum begins to oscillate (i.e., overfitting takes place). The apex should coincide with or be near the optimum.
References:
- Parameters:
tests (List[
KramersKronigResult
]) – The test results to evaluate.lower_limit (int, optional) – The lower limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the lower limit must have a smaller value than the upper limit.
upper_limit (int, optional) – The upper limit to enforce for the number of RC elements. If this value is less than one, then no limit is enforced. If both the lower and upper limit are greater than zero, then the upper limit must have a greater value than the lower limit.
relative_scores (bool, optional) – Return relative scores ranging from 0.0 to 1.0 (from worst to best) rather than the raw values.
- Returns:
A dictionary mapping the number of RC elements to its corresponding score.
- Return type:
Dict[int, float]
- pyimpspec.analysis.kramers_kronig.algorithms.utility.calculate_curvatures(Z)
Estimate the curvatures of an impedance spectrum.
References:
- Parameters:
Z (ComplexImpedances) – The impedances to use when estimating the curvatures using osculating circles.
- Returns:
An array of curvatures. If the impedances were sorted in order of decreasing frequency, then a curvature with a negative sign indicates a clockwise motion within the context of a plot of \(-{\rm Im}(Z)\ {\rm versus}\ {\rm Re}(Z)\).
- Return type:
NDArray[float64]
- pyimpspec.analysis.kramers_kronig.algorithms.utility.subdivide_frequencies(frequencies, subdivision=4)
Insert additional frequencies between each pair of frequencies.
- Parameters:
frequencies (Frequencies) – The original frequencies that are to be subdivided.
subdivision (int, optional) – The number of frequencies added between each of the original frequencies.
- Returns:
A new set of frequencies with additional frequencies inserted between each of the original frequencies.
- Return type:
Frequencies
Class
- class pyimpspec.KramersKronigResult(circuit, pseudo_chisqr, frequencies, impedances, residuals, test)
An object representing the results of a linear Kramers-Kronig test applied to a data set.
- Parameters:
circuit (Circuit) – The fitted circuit.
pseudo_chisqr (float) – The pseudo chi-squared value (\(\chi^2_{\rm ps}\), eq. 14 in Boukamp, 1995).
frequencies (
Frequencies
) – The frequencies used to perform the test.impedances (
ComplexImpedances
) – The impedances produced by the fitted circuit at each of the tested frequencies.residuals (
ComplexResiduals
) – The residuals for the real (eq. 15 in Schönleber et al., 2014) and imaginary (eq. 16 in Schönleber et al., 2014) parts of the fit.test (str) –
The type of test (and implementation) that was performed:
’complex’
’real’
’imaginary’
’complex-inv’
’real-inv’
’imaginary-inv’
’cnls’
- get_bode_data(num_per_decade=-1)
Get the data necessary to plot this KramersKronigResult as a Bode plot: the frequencies, the absolute magnitudes of the impedances, and the negative phase angles/shifts of the impedances in degrees.
- Parameters:
num_per_decade (int, optional) – The number of points per decade. A positive value results in data points being calculated using the fitted circuit within the original frequency range. Otherwise, only the original frequencies are used.
- Return type:
Tuple[
Frequencies
,Impedances
,Phases
]
- get_estimated_percent_noise()
Estimate the standard deviation of the noise (as a percentage of \(|Z|\)) using the approximation \({\rm SD}_{\rm est} \approx \sqrt{\chi^2_{\rm ps} \times 5000 / N_\omega}\) where \(\chi^2_{\rm ps}\) is the pseudo chi-squared value of the fit and \(N_\omega\) is the number of excitation frequencies. This approximation assumes that the error is spread evenly across the real and imaginary parts of the immittance spectrum.
References:
- Return type:
float
- get_frequencies(num_per_decade=-1)
Get the frequencies in the tested frequency range.
- Parameters:
num_per_decade (int, optional) – The number of points per decade. A positive value results in frequencies being calculated within the original frequency range. Otherwise, only the original frequencies are used.
- Return type:
- get_impedances(num_per_decade=-1)
Get the fitted circuit’s impedance response within the tested frequency range.
- Parameters:
num_per_decade (int, optional) – The number of points per decade. A positive value results in data points being calculated using the fitted circuit within the original frequency range. Otherwise, only the original frequencies are used.
- Return type:
- get_label()
Get the label of this result.
- Return type:
str
- get_log_F_ext()
Get the value of \(\log{F_{\rm ext}}\), which affects the range of time constants.
- Return type:
float
- get_nyquist_data(num_per_decade=-1)
Get the data necessary to plot this KramersKronigResult as a Nyquist plot: the real and the negative imaginary parts of the impedances.
- Parameters:
num_per_decade (int, optional) – The number of points per decade. A positive value results in data points being calculated using the fitted circuit within the original frequency range. Otherwise, only the original frequencies are used.
- Return type:
Tuple[
Impedances
,Impedances
]
- get_parallel_capacitance()
Get the value of the parallel capacitance (or numpy.nan if not included in the circuit).
- Return type:
float
- get_parallel_inductance()
Get the value of the parallel inductance (or numpy.nan if not included in the circuit).
- Return type:
float
- get_parallel_resistance()
Get the value of the parallel resistance.
- Return type:
float
- get_residuals_data()
Get the data necessary to plot the relative residuals for this result: the frequencies, the relative residuals for the real parts of the impedances in percents, and the relative residuals for the imaginary parts of the impedances in percents.
- Return type:
Tuple[
Frequencies
,Residuals
,Residuals
]
- get_series_capacitance()
Get the value of the series capacitance (or numpy.nan if not included in the circuit).
- Return type:
float
- get_series_inductance()
Get the value of the series inductance (or numpy.nan if not included in the circuit).
- Return type:
float
- get_series_resistance()
Get the value of the series resistance.
- Return type:
float
- get_time_constants()
Get the time constants that were used during fitting.
- Return type:
- perform_kolmogorov_smirnov_test(standard_deviation=0.0)
Perform one-sample Kolmogorov-Smirnov test on the residuals of the real and imaginary parts. The residuals are tested against a normal distribution with a mean that is assumed to be zero and a standard deviation that can either be provided or estimated automatically.
- Parameters:
standard_deviation (float, optional) – If greater than zero, then the provided value is used. Otherwise, the standard deviation estimated based on the pseudo chi-squared and the number of frequencies is used.
- Returns:
The p-values for the tests performed on the residuals of the real and imaginary parts. The null hypothesis is that the distributions of the residuals are identical to the normal distribution with a mean of zero and the provided (or estimated) standard deviation.
- Return type:
Tuple[float, float]
- perform_lilliefors_test()
Perform the Lilliefors test for normality on the residuals of the real and imaginary parts.
- Returns:
The p-values for the tests performed on the residuals of the real and imaginary parts. The null hypothesis is that the residuals come from a normal distribution.
- Return type:
Tuple[float, float]
- perform_shapiro_wilk_test()
Perform the Shapiro-Wilk test for normality on the residuals of the real and imaginary parts.
- Returns:
The p-values for the tests performed on the residuals of the real and imaginary parts. The null hypothesis is that the residuals come from a normal distribution.
- Return type:
Tuple[float, float]
- to_statistics_dataframe(extended_statistics=3)
Get the statistics related to the test as a pandas.DataFrame object.
- Parameters:
extended_statistics (int, optional) –
Include different amounts of additional statistics depending on the chosen level. Level 1 includes:
The estimated equivalent standard deviation of a Gaussian noise calculated based on the pseudo chi-squared value assuming that the noise in the real and imaginary parts of the impedance are independent, have a Gaussian distribution, a mean of zero, and the same standard deviation.
The means of the real and imaginary residuals.
The sample standard deviations of the real and imaginary residuals.
The percentage of points found within 1, 2, or 3 standard deviations.
Level 2 includes:
The p-values of normality tests performed on the real or imaginary residuals. These tests include: Lilliefors and Shapiro-Wilk.
Level 3 includes:
The p-values for one-sample Kolmogorov-Smirnov tests comparing the real or imaginary residuals against a normal distribution with a mean of zero and a standard deviation (as a percentage of \(|Z|\)) equal to the approximation obtained with \({\rm SD}_{\rm est} \approx \sqrt{\chi^2_{\rm ps} \times 5000 / N_\omega}\) where \(\chi^2_{\rm ps}\) is the pseudo chi-squared value of the fit and \(N_\omega\) is the number of excitation frequencies. This approximation assumes that the error is spread evenly across the real and imaginary parts of the immittance spectrum.
- Return type: