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()
../_images/examples_looping_files_example_15_0.png

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()
../_images/examples_looping_files_example_17_0.png
../_images/examples_looping_files_example_17_1.png