Looping through and fitting multiple impedance data sets
[1]:
import glob
import numpy as np
import os
1. Find all files that match a specified pattern
Using a search string to find .z files that contain “Circuit” at the beginning and EIS towards the end
[2]:
directory = r'../../../data/'
all_files = glob.glob(os.path.join(directory, 'Circuit*EIS*.z'))
all_files
[2]:
['../../../data/Circuit3_EIS_1.z',
'../../../data/Circuit1_EIS_2.z',
'../../../data/Circuit2_EIS_1.z',
'../../../data/Circuit3_EIS_2.z',
'../../../data/Circuit1_EIS_1.z',
'../../../data/Circuit2_EIS_2.z']
2. Use preprocessing module to read in ZPlot data
[3]:
from impedance import preprocessing
# Initialize some empty lists for the frequencies and Z data
freqs = []
Zs = []
# Now loop through file names in our list and extract data one by one
for filename in all_files:
f, Z = preprocessing.readZPlot(filename)
freqs.append(f)
Zs.append(Z)
# Check to see if we extracted data for all the files
print(np.shape(Zs), np.shape(all_files))
(6,) (6,)
3. Create a list of circuit models
[4]:
from impedance.models.circuits import CustomCircuit
# This data comes from dummy circuits I made to check measurement bias in
# our potentiostat, so I know a priori its an R-RC circuit
circuits = []
circ_string = 'R0-p(R1,C1)'
initial_guess = [100, 400, 1e-5]
# Now loop through data list to create circuits and fit them
for f, Z, filename in zip(freqs, Zs, all_files):
name = filename.split('/')[-1]
circuit = CustomCircuit(circ_string, initial_guess=initial_guess, name=name)
circuit.fit(f, Z)
circuits.append(circuit)
We now have a list of our circuit class objects, all fit to different sets of data. As you may notice from the file names, there are three unique circuits each with a replicate set of data. We expect each of the replicates to fit similarly.
[5]:
for circuit in circuits:
print(circuit)
Name: Circuit3_EIS_1.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 1.51e+03 (+/- 2.62e+00) [Ohm]
R1 = 4.63e+03 (+/- 3.14e+00) [Ohm]
C1 = 2.02e-08 (+/- 5.39e-11) [F]
Name: Circuit1_EIS_2.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 2.91e+01 (+/- 3.58e-02) [Ohm]
R1 = 4.67e+01 (+/- 4.64e-02) [Ohm]
C1 = 1.04e-05 (+/- 2.91e-08) [F]
Name: Circuit2_EIS_1.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 1.50e+02 (+/- 3.23e-01) [Ohm]
R1 = 5.02e+02 (+/- 3.57e-01) [Ohm]
C1 = 3.12e-08 (+/- 7.79e-11) [F]
Name: Circuit3_EIS_2.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 1.51e+03 (+/- 2.68e+00) [Ohm]
R1 = 4.63e+03 (+/- 3.21e+00) [Ohm]
C1 = 2.02e-08 (+/- 5.52e-11) [F]
Name: Circuit1_EIS_1.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 2.91e+01 (+/- 3.63e-02) [Ohm]
R1 = 4.67e+01 (+/- 4.69e-02) [Ohm]
C1 = 1.04e-05 (+/- 2.95e-08) [F]
Name: Circuit2_EIS_2.z
Circuit string: R0-p(R1,C1)
Fit: True
Initial guesses:
R0 = 1.00e+02 [Ohm]
R1 = 4.00e+02 [Ohm]
C1 = 1.00e-05 [F]
Fit parameters:
R0 = 1.50e+02 (+/- 3.19e-01) [Ohm]
R1 = 5.02e+02 (+/- 3.53e-01) [Ohm]
C1 = 3.12e-08 (+/- 7.70e-11) [F]
Now we’ll get the impedance predicted by the fit parameters
[6]:
fits = []
for f, circuit in zip(freqs, circuits):
fits.append(circuit.predict(f))
4. Plot the data and fits
Now we can visualize the data and fits. For now we’ll place them all on the same axis
[7]:
import matplotlib.pyplot as plt
from impedance.visualization import plot_nyquist, plot_bode
[8]:
fig, ax = plt.subplots()
for fit, Z in zip(fits, Zs):
# Plotting data
plot_nyquist(ax, Z)
# Plotting fit
plot_nyquist(ax, fit)
plt.show()
Since the circuits have different orders of magnitude impedance, this looks bad so let’s put each pair of data on separate axes.
[9]:
# Nyquist plots
fig, axes = plt.subplots(ncols=3, figsize=(22,6))
for circuit, Z, fit in zip(circuits, Zs, fits):
n = int(circuit.name.split('Circuit')[-1].split('_')[0])
plot_nyquist(axes[n - 1], Z)
plot_nyquist(axes[n - 1], fit)
# Bode plots
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(22,6))
for circuit, f, Z, fit in zip(circuits, freqs, Zs, fits):
n = int(circuit.name.split('Circuit')[-1].split('_')[0])
plot_bode([axes[0][n - 1], axes[1][n - 1]], f, Z)
plot_bode([axes[0][n - 1], axes[1][n - 1]], f, fit)
plt.show()