Electrochemistry
ECMeasurement
The main TechniqueMeasurement class for electrochemistry is the ECMeasurement
class.
Subclasses of ECMeasurement
include CyclicVoltammogram
and CyclicVoltammogramDiff
.
Direct-current electrochemistry measurements are characterized by the essential quantities being
working-electrode current and potential (vs the reference electrode) as a function of time. Either
current or potential can be controlled as the input variable, so the other acts as the response,
and it is common to plot current vs potential, but in all cases both are tracked or controlled as
a function of time. This results in the essential variables t
(time), U
(potential), and J
(current). The main job of ECMeasurement
and subclasses is to give standardized,
convenient, and powerful access to these three variables for data selection, analysis,
and visualization, regardless of which hardware the data was acquired with.
At the present, ixdat
does not yet offer specific functionality for electrochemical impedance spectroscopy (EIS) data.
The default plotter, ECPlotter, plots these variables.
The default exporter, ECExporter, exports these variables as well as an incrementer for
selecting data, selector
.
Electrochemistry is the most thoroughly developed technique in ixdat
. For in-depth
examples of the functionality in the ECMeasurement
class and its subclasses, see
the following Tutorials:
data_in_and_out
The full module documentation is available below: The ec module.
CyclicVoltammogram
CyclicVoltammogram
inherits from ECMeasurement
and adds useful functionality for
cyclic voltammetry analysis. This includes:
Current vs potential as the default
plot()
(same asplot_vs_potential()
for anECMeasurement
).A new counter,
cycle
, which counts cycles. At first this counter will point to a counter in the raw data, if available (Biologic, for example, exports a “cycle number” column). However, it is recommended to control this counter yourself using theredefine_cycle
method. For examplemy_cv.redefine_cycle(start_potential=0.4, redox=False)
makescycle
increment each time the potential passes 0.4 V in the cathodic direction.The ability to select a cycle by indexing with an integer. For example
my_cv[1]
is aCyclicVoltammogram
containing the first full cycle.A new built-in series,
scan_rate
. This is derived automatically frompotential
and stored in V/s. It can be grabbed (t, v_scan = my_cv.grab("scan_rate")
), indexed, or plotted like anything else.An additional function
select_sweep
which can select a portion of the CV where the potential is scanned through a certain range.A
calc_capacitance
function which uses the two above to calculate capacitance in Farads.
A common workflow is to read in cyclic voltammetry data as an ECMeasurement
, convert
it to a CyclicVoltammogram
with the as_cv()
method, tell it when to increment the
cycle with redefine_cycle()
, coplot potential and cycle vs time with plot_measurement()
to see which cycle number to use, and then index to analyze or plot individual cycles.
For example, to coplot two cycles (the sedond and the 50th) which both start and end at
0.2 V in the anodic direction:
>>> from ixdat import Measurement
>>> my_ec_meas = Measurement.read("my_data.mpt", reader="biologic")
>>> my_cv = my_ec_meas.as_cv()
>>> my_cv.redefine_cycle(start_potential=0.2, redox=True)
>>> my_cv.plot_measurement(J_name="cycle") # co-plots potential and cycle counter
>>> ax = my_cv[2].plot(color="b", label="earlier")
>>> my_cv[50].plot(ax=ax, color="r", label="later")
>>> ax.legend()
>>> ax.get_figure().savefig("two_cycles.png")
Note that as_cv()
is available for any hyphenated technique which inherits from ECMeasurement
,
such as ECMSMeasurement
, and that all the data from the second technique (here MS)
comes along for the ride when using the cycle counter to select data. For full documentation of the cyclic voltammetry
module see below: cv_module
The ec
module
Source: https://github.com/ixdat/ixdat/tree/user_ready/src/ixdat/techniques/ec.py
Module for representation and analysis of EC measurements
- class ixdat.techniques.ec.ECCalibration(name=None, technique='EC', tstamp=None, measurement=None, RE_vs_RHE=None, A_el=None, R_Ohm=None)[source]
An electrochemical calibration with RE_vs_RHE, A_el, and/or R_Ohm
- calibrate_series(key, measurement=None)[source]
Return a calibrated series for key based on the raw data in the measurement.
Key should be “potential” or “current”. Anything else will return None.
“potential”: the calibration looks up “raw_potential” in the measurement,
shifts it to the RHE potential if RE_vs_RHE is available, corrects it for Ohmic drop if R_Ohm is available, and then returns a calibrated potential series with a name indicative of the corrections done. - “current”: The calibration looks up “raw_current” in the measurement, normalizes it to the electrode area if A_el is available, and returns a calibrated current series with a name indicative of whether the normalization was done.
- class ixdat.techniques.ec.ECMeasurement(name, *, ec_technique=None, RE_vs_RHE=None, R_Ohm=None, A_el=None, **kwargs)[source]
Class implementing electrochemistry measurements
- TODO: Implement a unit library for current and potential, A_el and RE_vs_RHE
so that e.g. current can be seamlessly normalized to mass OR area.
The main job of this class is making sure that the ValueSeries most essential for visualizing and normal electrochemistry measurements (i.e. excluding impedance spec., RRDE, etc, which would need new classes) are always available in the correct form as the measurement is added with others, reduced to a selection, calibrated and normalized, etc. These most important ValueSeries are:
potential: The working-electrode potential typically in [V]. If ec_meas is an ECMeasurement, then ec_meas[“potential”] always returns a ValueSeries characterized by:
calibrated and/or corrected, if the measurement has been calibrated with the reference electrode potential (RE_vs_RHE, see calibrate) and/or corrected for ohmic drop (R_Ohm, see correct_ohmic_drop).
A name that makes clear any calibration and/or correction
Data which spans the entire timespan of the measurement - i.e. whenever EC data is being recorded, potential is there, even if the name of the raw ValueSeries (what the acquisition software calls it) changes. Indeed ec_meas[“potential”].tseries is the measurement’s definitive time variable.
current: The working-electrode current typically in [mA] or [mA/cm^2]. ec_meas[“current”] always returns a ValueSeries characterized by:
normalized if the measurement has been normalized with the electrode area (A_el, see normalize)
A name that makes clear whether it is normalized
Data which spans the entire timespan of the measurement
selector: A counter series distinguishing sections of the measurement program. This is essential for analysis of complex measurements as it allows for corresponding parts of experiments to be isolated and treated identically. selector in ECMeasurement is defined to increment each time one or more of the following changes:
loop_number: A parameter saved by some potentiostats (e.g. BioLogic) which allow complex looped electrochemistry programs.
file_number: The id of the component measurement from which each section of the data (the origin of each ValueSeries concatenated to potential)
cycle_number: An incrementer within a file saved by a potentiostat.
The names of these ValueSeries, which can also be used to index the measurement, are conveniently available as properties:
ec_meas.t_name is the name of the definitive time, i.e. that of the potential
ec_meas.E_name is the name of the raw potential
ec_meas.U_name is the name of the calibrated and/or corrected potential
ec_meas.I_name is the name of the raw current
ec_meas.J_name is the name of the normalized current
ec_meas.selector_name is the name of the default selector, i.e. “selector”
Numpy arrays from important DataSeries are directly accessible via attributes:
ec_meas.t for ec_meas[“potential”].t
ec_meas.U for ec_meas[“potential”].data
ec_meas.J for ec_meas[“current”].data
ECMeasurement comes with an ECPlotter which either plots potential and current against time (ec_meas.plot_measurement()) or plots current against potential (`ec_meas.plot_vs_potential()).
It turns out that keeping track of current, potential, and selector when combining datasets is enough of a job to fill a class. Thus, the more exciting electrochemistry-related functionality should be implemented in inheriting classes such as CyclicVoltammogram.
- property A_el
The electrode area in [cm^2]
- property J
The current ([mA] or [mA/cm^2]) numpy array of the measurement
- property RE_vs_RHE
The refernce electrode potential on the RHE scale in [V]
- property R_Ohm
The ohmic drop resistance in [Ohm]
- property U
The potential [V] numpy array of the measurement
- property aliases
A dictionary with the names of other data series a given name can refer to
- property calibrations
The list of calibrations of the measurement.
The following is necessary to ensure that all EC Calibration parameters are joined in a single calibration when processing. So that “potential” is both calibrated to RHE and ohmic drop corrected, even if the two calibration parameters were added separately.
- control_series_name = 'raw_potential'
Name (or alias) for main time variable or main time-dependent value variable, typically of the control technique
- default_exporter
alias of
ECExporter
- property ec_calibration
A calibration joining the first RE_vs_RHE, A_el, and R_Ohm
- essential_series_names = ('t', 'raw_potential', 'raw_current')
Series which should always be present
- property j
The current ([mA] or [mA/cm^2]) numpy array of the measurement
- normalize_current(A_el)[source]
Normalize current to electrode surface area by providing A_el in [cm^2].
- selection_series_names = ('file_number', 'loop_number', 'cycle number', 'Ns')
Name of the default things to use to construct the selector
- property v
The potential [V] numpy array of the measurement
The cv
module
Source: https://github.com/ixdat/ixdat/tree/user_ready/src/ixdat/techniques/cv.py
- class ixdat.techniques.cv.CyclicVoltammogram(*args, **kwargs)[source]
Class for cyclic voltammetry measurements.
Onto ECMeasurement, this adds: - a property cycle which is a ValueSeries on the same TimeSeries as potential, which counts cycles. “cycle” becomes the Measurement’s sel_str. Indexing with integer or iterable selects according to cycle. - functions for quantitatively comparing cycles (like a stripping cycle, base cycle) - the default plot() is plot_vs_potential()
- calc_capacitance(vspan)[source]
Return the capacitance in [F], calculated by the first sweeps through vspan
- Parameters
vspan (iter of floats) – The potential range in [V] to use for capacitance
- diff_with(other, v_list=None, cls=None, v_scan_res=0.001, res_points=10)[source]
Return a CyclicVotammagramDiff of this CyclicVotammagram with another one
Each anodic and cathodic sweep in other is lined up with a corresponding sweep in self. Each variable given in v_list (defaults to just “current”) is interpolated onto self’s potential and subtracted from self.
- Parameters
other (CyclicVoltammogram) – The cyclic voltammogram to subtract from self.
v_list (list of str) – The names of the series to calculate a difference between self and other for (defaults to just “current”).
cls (ECMeasurement subclass) – The class to return an object of. Defaults to CyclicVoltammogramDiff.
v_scan_res (float) – see
get_timed_sweeps()
res_points (int) – see
get_timed_sweeps()
- essential_series_names = ('t', 'raw_potential', 'raw_current', 'cycle')
Series which should always be present
- get_timed_sweeps(v_scan_res=0.0005, res_points=10)[source]
Return list of [(tspan, type)] for all the potential sweeps in self.
There are three types: “anodic” (positive scan rate), “cathodic” (negative scan rate), and “hold” (zero scan rate)
- Parameters
v_scan_res (float) – The minimum scan rate considered significantly different than zero, in [V/s]. Defaults to 5e-4 V/s (0.5 mV/s). May need be higher for noisy potential, and lower for very low scan rates.
res_points (int) – The minimum number of points to be considered a sweep. During a sweep, a potential difference of at least v_res should be scanned through every res_points points.
- integrate(item, tspan=None, vspan=None, ax=None)[source]
Return the time integral of item while time in tspan or potential in vspan
- Parameters
item (str) – The name of the ValueSeries to integrate
tspan (iter of float) – A time interval over which to integrate it
vspan (iter of float) – A potential interval over which to integrate it
- plot_cycles(ax=None, cmap_name='jet')[source]
Plot the cycles on a color scale.
- Parameters
ax (mpl.Axis) – The axes to plot on. A new one is made by default
cmap_name (str) – The name of the colormap to use. Defaults to “jet”, which ranges from blue to red
- redefine_cycle(start_potential=None, redox=None, N_points=5)[source]
Build cycle which iterates when passing through start_potential
- Parameters
start_potential (float) – The potential in [V] at which the cycle counter will iterate. If start_potential is not given, the cycle is just the selector inherited from ECMeasurement shifted to start at 0.
redox (bool) – True (or 1) for anodic, False (or 0) for cathodic. The direction in which the potential is scanning through start_potential to trigger an iteration of cycle.
N_points (int) – The number of consecutive points for which the potential needs to be above (redox=True) or below (redox=False) the start_potential for the new cycle to register.
- select_sweep(vspan, t_i=None)[source]
Return the cut of the CV for which the potential is sweeping through vspan
- Parameters
vspan (iter of float) – The range of self.potential for which to select data. Vspan defines the direction of the sweep. If vspan[0] < vspan[-1], an oxidative sweep is returned, i.e. one where potential is increasing. If vspan[-1] < vspan[0], a reductive sweep is returned.
t_i (float) – Optional. Time before which the sweep can’t start
- selector_name = 'cycle'
Name of the default selector
- series_constructors = {'file_number': '_build_file_number_series', 'scan_rate': '_build_scan_rate', 'selector': '_build_selector_series'}
Series which should be constructed from other series by the specified method and cached the first time they are looked up
- class ixdat.techniques.cv.CyclicVoltammogramDiff(*args, **kwargs)[source]
- default_plotter
alias of
CVDiffPlotter