Comments (11)
Thanks for taking the time to right this up @ngamazza. This is a great suggestion and the right format for making it happen. 👍
In terms of where/what kind of documentation you’re suggesting, it sounds like the gap in docs currently is somewhere between the ”getting started with Impedance.py” and the actual function/api documentation?
Off the top of my head some additional intermediate types of ideas to get things going:
- example use cases
- looping through impedance data
- validating, fitting, and visualizing an experiment
- defining a custom model via a circuit string
- contributing to impedance.py (forking, PRs, etc.)
@anyone have other thoughts on where we should expand the docs/have workflows they’d like to contribute?
from impedance.py.
from impedance.py.
Hi @ngamazza,
Ditto Matt's comments about being busy during the holidays, but I'm back now and working with impedance.py a lot. I agree we can spruce up our documents, but for now I want to address your question
I am not 100% sure how to pass the initial guess parameters of circuit elements, and sometimes get stuck between two errors such as
"in E, input list must be length 2"
"Initial guess length needs to be equal to {circuit_length}"
when building a new custom circuit
If you refer to the Plotting Nyquist plots of impedance spectra example, you'll see a custom circuit with initial parameters is defined in the third cell: circuit = CustomCircuit(initial_guess=[.01, .005, .1, .005, .1, .001, 200], circuit='R_0-p(R_1,C_1)-p(R_1,C_1)-W_1')
The initial guesses array is 7 elements long, but the circuit string only defines 6 elements. This arises from some circuit elements – like CPE (E) and warburg (W) – requiring two parameters. The circuit elements documents will tell you which elements fall under this scenario by having something like "Q = p[0] and α = p[1]" in the Notes section.
Regarding @mdmurbach 's list of example ideas
- example use cases
- looping through impedance data
- validating, fitting, and visualizing an experiment
- defining a custom model via a circuit string
- contributing to impedance.py (forking, PRs, etc.)
Several of these are already addressed in the current examples. Defining custom models, fitting data, and visualizing data appear in the Fitting impedance spectra, and Plotting Nyquist plots of impedance spectra examples. Validating data is addressed in the Validation of EIS data example.
from impedance.py.
Hi @ngamazza,
Like @mdmurbach, I couldn't replicate the 'Initial guess length needs to be equal to {circuit_length}'' error. However, to Matt's point, if the α parameter of a CPE is initialized outside the [0,1] range you may get an error saying, "x0
is infeasible." Here I'll initialize the first α with a value of 10.
# read data
data = np.genfromtxt('data/exampleData.csv', delimiter=',')
f = data[:,0]
Z = data[:,1] + 1j*data[:,2]dfsdf
# define custom circuit
from impedance.circuits import CustomCircuit
circuit = CustomCircuit(initial_guess=[250, 60, 0.00002, 10, 100, 0.0002, 0.1],
circuit='R0-p(R1,E1)-p(R2,E2)')
print(circuit)
Circuit string: R0-p(R1,E1)-p(R2,E2)
Fit: FalseInitial guesses:
R0 = 2.50e+02 [Ohm]
R1 = 6.00e+01 [Ohm]
E1_0 = 2.00e-05 [Ohm^-1 sec^a]
E1_1 = 1.00e+01 []
R2 = 1.00e+02 [Ohm]
E2_0 = 2.00e-04 [Ohm^-1 sec^a]
E2_1 = 1.00e-01 []
# fitting data
circuit.fit(f, Z)
ValueError Traceback (most recent call last)
. . .
ValueError:x0
is infeasible.
But it should work if we change that α to something like 0.6
circuit = CustomCircuit(initial_guess=[250, 60, 0.00002, .6, 100, 0.0002, 0.1],
circuit='R0-p(R1,E1)-p(R2,E2)')
circuit.fit(f, Z)
print(circuit)
Circuit string: R0-p(R1,E1)-p(R2,E2)
Fit: TrueInitial guesses:
R0 = 2.50e+02 [Ohm]
R1 = 6.00e+01 [Ohm]
E1_0 = 2.00e-05 [Ohm^-1 sec^a]
E1_1 = 6.00e-01 []
R2 = 1.00e+02 [Ohm]
E2_0 = 2.00e-04 [Ohm^-1 sec^a]
E2_1 = 1.00e-01 []Fit parameters:
R0 = 1.59e-02 (+/- 2.10e-04) [Ohm]
R1 = 1.81e-02 (+/- 4.87e-04) [Ohm]
E1_0 = 5.62e+00 (+/- 3.22e-01) [Ohm^-1 sec^a]
E1_1 = 5.46e-01 (+/- 1.55e-02) []
R2 = 2.74e-01 (+/- 9.82e-02) [Ohm]
E2_0 = 4.13e+02 (+/- 2.77e+01) [Ohm^-1 sec^a]
E2_1 = 6.26e-01 (+/- 2.07e-02) []
from impedance.py.
Going to go ahead and close this issue, since the version 1.0 release added new examples and refreshed the docs.
from impedance.py.
Hi @dt-schwartz and @ngamazza, my apologies for the delay, was traveling through the holidays and missed your reply.
@dt-schwartz I think it could be a potentially interesting project, although I'm not sure what technical scope makes sense for the capstone team. On the more challenging end implementing a distribution of relaxation times (DRT) algorithm would be an awesome addition (there are examples of implementations, e.g. [Ciucci (2015), matlab], but this would be a relatively math intensive project). Other projects that come to mind are visualization (functions for Bode diagrams, interactive charts with Altair, creating circuit diagrams from user input, plotting fit residuals, etc.) or some statistical model selection (calculating an information criterion or something like that to determine best fitting model).
I can put together a more concrete project write up in the next few days if you think it still makes sense?
from impedance.py.
Hi everyone,
I'm also just back from vacations!
FIrst of all, thanks for the answers and the help!
I agree that what @mdmurbach suggested looks nice.
Maybe, in the part regarding looping through the data, then show that's possible to use a loop to collect the fit outputs in a single table/tsv? Though it is not essential.
@BGerwe: thanks for the detailed answer! Can I push maybe my luck and ask a follow up question?
My data shows roughly two arcs, and as a first attempt I used 'R0-p(R1,C1)-p(R2,C2)', but I'd probably get a better fit using CPEs, but I get an error when doing that.
This runs, and I'm then able to get a Nyquist plot with a code very similar to the one in the example
circuit = impedance.circuits.CustomCircuit(initial_guess=[250, 60, 0.00002, 100, 0.0002],
circuit='R0-p(R1,C1)-p(R2,C2)')
This, where I sub both Cs for Es and use 7 parameters, gets ''Initial guess length needs to be equal to {circuit_length}''
circuit = impedance.circuits.CustomCircuit(initial_guess=[250, 60, 0.00002, 10, 100, 0.0002, 0.1],
circuit='R0-p(R1,E1)-p(R2,E2)')
And, as it should, using 5 parameters gets "in E, input list must be length 2".
The full script (which will probably show that I'm a beginner...), is:
import os
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import impedance
files = ['example.dat']
#run through the files, fit, plot and save
for filename in files:
flnm1 = os.path.splitext(filename)[0]
data_eis = pd.read_csv(filename, sep=('\t'), decimal = '.', skiprows =6)
data_eis.columns= ['Freq', 'Re', 'Im', 'Amp', 'Pha', 'R(DC)', 'C', 'Bias', 'Bias']
data_eis['neg_Imm_part'] = 0 - data_eis['Im']
circuit = impedance.circuits.CustomCircuit(initial_guess=[250, 60, 0.00002, 100, 0.0002],
circuit='R0-p(R1,C1)-p(R2,C2)')
data_eis_pos = data_eis[(data_eis.Im<0)]
Z = data_eis_pos['Re'] + 1j* data_eis_pos['Im']
circuit.fit (np.asarray(data_eis_pos['Freq']), np.asarray(Z))
fig, ax = plt.subplots()
ax = circuit.plot(f_data=np.asarray(data_eis['Freq']), Z_data=np.asarray(Z),
conf_bounds='filled')
ax.tick_params(axis='both', which='major', labelsize=16)
print(circuit, file=open( flnm1 + ".txt", "a"))
ax.grid(False)
fig = ax.get_figure()
fig.savefig(flnm1 + '_nyquist.png')
plt.close()`
Thanks for the help, and happy new year!
from impedance.py.
HI @ngamazza,
I can't seem to reproduce the same error you're having with 7 initial guesses passed to a 2-CPE circuit. The code below works for me:
from impedance.circuits import CustomCircuit
from impedance.plotting import plot_nyquist
import matplotlib.pyplot as plt
import numpy as np
data = np.genfromtxt('./impedance_data/3.369V.csv', delimiter=',')
f = data[:, 0]
Z = data[:, 1] + 1j*data[:, 2]
# initialize circuit
# E (CPE) parameters are Q [1 and 10, below], alpha [0.9, below]
circuit = CustomCircuit(initial_guess=[.01, .01, 1, 0.9, .01, 10, 0.9],
circuit='R0-p(R1,E1)-p(R2,E2)')
# Fit circuit
circuit.fit(f, Z)
print(circuit)
# Plot results
Z_fit = circuit.predict(f)
fig, ax = plt.subplots(figsize=(5,5))
plot_nyquist(ax, f, Z, fmt='o')
plot_nyquist(ax, f, Z_fit)
plt.show()
One thing to note is that the parameters for a CPE (E) are Q [Ohm^-1 sec^a], alpha where alpha should be between 0 and 1. Could you try changing the initial guesses you're passing for alpha to something like 0.9?
from impedance.py.
@ngamazza I also think you might have an older version of impedance.py
(based on the error message of "Initial guess length needs to be equal to {circuit_length}"
which I think was fixed in v0.5, #40). Not sure if this is part of the error, but you can update your version with
pip install --upgrade impedance
from impedance.py.
@ngamazza I wrote up this example of looping through data sets, fitting them, and visualizing. I'm also a self-taught coder so these may not be best practices but they've worked well for me so far. Maybe @mdmurbach can give some advice on improvements if anything looks strange.
The most important feature is that you can use lists to store any kind of object including numpy arrays for data, and the circuit class objects that are used for storing the fit results. Here's a snippet of what that looks like
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 file_name in all_files:
f, Z = preprocessing.readZPlot(file_name)
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))
But you can see all the details in the Jupyter notebook and data I've attached in the zip file (unfortunately attaching Jupyter Notebooks and Zplot files are not supported through GitHub). Note: please place the data files in a subdirectory called "data", or change the direc
variable to point where you're storing the data files.
Looping Files Example.zip
from impedance.py.
Hi @BGerwe and @mdmurbach ,
Great for the new example!
As soon as I get a bit more experienced in Python and the package I can maybe help with the examples.
On the other topic, changing the value of the parameter did not solve it but as I was playing around with impedance.py yesterday, trying to understand what's wrong, I noticed even the Nyquist example code gave me the same error.
I created a new environment, thinking that the problem must be with my installation and not the package, and I was able to run the same exact scripts normally, without the errors I described above.
I was hoping to see understand if some other package was creating the problem, but the scripts now work also in the other environments, strangely enough. I will be doing some fittings over the next days, and I'll see if I can replicate the error, playing around with the environments, or understand what caused it. In case, I'll post here.
Thanks for the help!
from impedance.py.
Related Issues (20)
- [BUG] Subplot aspect ratio HOT 1
- [BUG] .append no longer available in pandas > 2.0
- [Element]
- Error in visualization with looping through and fitting multiple data sets HOT 2
- [BUG] Deprecation warnings with Altair v5
- [BUG] Matplotlib warnings when plotting Bode or Nyquist plot HOT 1
- Very confused about fitting HOT 3
- BaseCircuit.predict() won't take float as input
- Confusion with the word "initial_guess" used in CustomCircuit(circuit_string,initial_guess) HOT 1
- Initial_guess HOT 2
- Replace print with proper logging HOT 1
- RC components
- A worked example of .nox Metrohm file reading and pre-processing HOT 3
- high frequency fitting problem HOT 12
- Accuracy of data in .par file about VersaStudio HOT 3
- Ask for help extracting parameter values from fitted circuits HOT 1
- [BUG] error in impedance definition of La-element
- reading data from Excel files
- Circuit Element Unit scalable feature
- Adding Distribution of relaxation times feature HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from impedance.py.