Tutorial: Spectroelectrochemistry data

Data required: available for download here

This example data comes from Caiwu Liang, et al. Unravelling the effects of active site densities and energetics on the water oxidation activity of iridium oxides https://doi.org/10.21203/rs.3.rs-2605628/v1

The data

To run this tutorial, save the data somewhere on you computer and modify the data_dir variable below accordingly. The code in the following lines should then print a list of the data folder contents including several .csv’s

[1]:
from pathlib import Path

data_dir = Path.home() / "Dropbox/ixdat_resources/test_data/sec"

print("data directory containes files and folders:")
for path in data_dir.iterdir():
    print(path)
data directory containes files and folders:
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\decay
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export_reference.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export_spectra.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export_reference.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export_spectra.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\test-2SEC.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\test-2_JV.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\test-7SEC.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\test-7_JV.csv
C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\WL.csv

SEC while scanning potential

[2]:
from ixdat import Measurement

sec = Measurement.read(
    data_dir / "test-7SEC.csv",
    path_to_ref_spec_file = data_dir / "WL.csv",
    path_to_U_J_file = data_dir / "test-7_JV.csv",
    scan_rate=1,
    tstamp=1,
    reader="msrh_sec"
)
importing ixdat v0.2.7.dev1 from C:\Users\Søren\git\ixdat\src\ixdat\__init__.py
C:\Users\Søren\git\ixdat\src\ixdat\techniques\analysis_tools.py:92: RuntimeWarning: invalid value encountered in divide
  v_scan_behind = (v - v_behind) / (t - t_behind)
C:\Users\Søren\git\ixdat\src\ixdat\techniques\analysis_tools.py:93: RuntimeWarning: invalid value encountered in divide
  v_scan_ahead = (v_ahead - v) / (t_ahead - t)
[3]:
sec.plot_measurement()
C:\Users\Søren\git\ixdat\src\ixdat\plotters\base_mpl_plotter.py:61: MatplotlibDeprecationWarning: Auto-removal of overlapping axes is deprecated since 3.6 and will be removed two minor releases later; explicitly call ax.remove() as needed.
  axes = [plt.subplot(gs[0:3, 0])]
[3]:
[<Axes: xlabel='time from scan rate', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='time / [s]', ylabel='raw potential / [V]'>,
 None,
 <Axes: ylabel='raw current / [mA]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_4_2.png

The raw data as numpy arrays is accessible as such:

[4]:
wavelength = sec.wavelength.data
absorption_matrix = sec.spectra.data
potential = sec.potential.data

print("wavelength:")
print(wavelength)

print("potential:")
print(potential)

print("absorption:")
print(absorption_matrix)

wavelength:
[450.58331 451.00531 451.42731 ... 873.6803  874.08472 874.48907]
potential:
[0.4   0.401 0.402 ... 1.497 1.498 1.499]
absorption:
[[ 5488.33333333  5501.93333333  5505.3        ... 37897.93333333
  37868.56666667 37805.83333333]
 [ 5483.          5502.46666667  5506.03333333 ... 37881.4
  37856.7        37809.46666667]
 [ 5490.76666667  5503.96666667  5512.33333333 ... 37871.8
  37863.53333333 37794.2       ]
 ...
 [ 3931.63333333  3948.23333333  3949.2        ... 24453.6
  24418.23333333 24395.86666667]
 [ 3927.7         3946.86666667  3950.8        ... 24414.76666667
  24387.76666667 24382.2       ]
 [ 3934.56666667  3939.53333333  3941.83333333 ... 24411.1
  24383.86666667 24374.16666667]]
[5]:
sec.calibrate_RE(RE_vs_RHE=0.26)
sec.normalize_current(A_el=1)
sec.plot_measurement(make_colorbar=True)
C:\Users\Søren\git\ixdat\src\ixdat\plotters\plotting_tools.py:50: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = mpl.cm.get_cmap(cmap_name)
[5]:
[<Axes: xlabel='time from scan rate', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='time / [s]', ylabel='$U_{RHE}$ / [V]'>,
 None,
 <Axes: ylabel='J / [mA cm$^{-2}$]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_7_2.png
[6]:
sec.plot_waterfall()
C:\Users\Søren\git\ixdat\src\ixdat\plotters\spectrum_plotter.py:192: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = mpl.cm.get_cmap(cmap_name)
[6]:
<Axes: xlabel='wavelength / [nm]', ylabel='$\\Delta$ O.D.'>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_8_2.png
[7]:
sec.reference_spectrum.plot()
[7]:
<Axes: xlabel='wavelength / [nm]', ylabel='reference'>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_9_1.png
[8]:
sec.set_reference_spectrum(V_ref=0.66)
sec.reference_spectrum.plot()
[8]:
<Axes: xlabel='wavelength / [nm]', ylabel='spectra_0.66V'>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_10_1.png
[9]:
# help(sec)  # useful but very long output. Shows for example, that the following gives delta OD data:
delta_OD_data = sec.calc_dOD().data
print(delta_OD_data)  # A 2-D numpy array.
[[-0.00000000e+00 -0.00000000e+00 -0.00000000e+00 ... -0.00000000e+00
  -0.00000000e+00 -0.00000000e+00]
 [ 4.22234445e-04 -4.20965657e-05 -5.78463318e-05 ...  1.89506432e-04
   1.36113826e-04 -4.17359084e-05]
 [-1.92508176e-04 -1.60471285e-04 -5.54481744e-04 ...  2.99580384e-04
   5.77284638e-05  1.33658473e-04]
 ...
 [ 1.44867472e-01  1.44112513e-01  1.44271862e-01 ...  1.90272724e-01
   1.90564628e-01  1.90242564e-01]
 [ 1.45302172e-01  1.44262868e-01  1.44095945e-01 ...  1.90962949e-01
   1.91106836e-01  1.90485926e-01]
 [ 1.44543572e-01  1.45070544e-01  1.45082732e-01 ...  1.91028178e-01
   1.91176292e-01  1.90629039e-01]]
[10]:
sec.plot_waterfall()
[10]:
<Axes: xlabel='wavelength / [nm]', ylabel='$\\Delta$ O.D.'>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_12_1.png
[11]:
axes = sec.plot_measurement(cmap_name="jet")
axes[0].set_xlabel("time / [s]")
[11]:
Text(0.5, 0, 'time / [s]')
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_13_1.png
[12]:
sec.plot_vs_potential()
[12]:
[<Axes: xlabel='$U_{RHE}$ / [V]', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='$U_{RHE}$ / [V]', ylabel='J / [mA cm$^{-2}$]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_14_1.png
[13]:
sec.plot_vs_potential(cmap_name="jet")

axes = sec.plot_vs_potential(cmap_name="jet", vspan=[1.0, 1.45], make_colorbar=True, color="g")
axes[1].set_ylim([0, 0.1])
[13]:
(0.0, 0.1)
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_15_1.png
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_15_2.png
[14]:
sec.plot_wavelengths(wavelengths=["w800", "w580"])
C:\Users\Søren\git\ixdat\src\ixdat\plotters\sec_plotter.py:365: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = mpl.cm.get_cmap(cmap_name)
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_16_1.png
[15]:
sec.plot_wavelengths_vs_potential(wavelengths=["w800", "w580", "w480"])
C:\Users\Søren\git\ixdat\src\ixdat\plotters\sec_plotter.py:412: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = mpl.cm.get_cmap(cmap_name)
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_17_1.png
[16]:
spec_1 = sec.get_spectrum(V=1.0)

ax = spec_1.plot(color="r", label="1.0 V vs RHE")
sec.reference_spectrum.plot(ax=ax, label="reference")
ax.legend()
[16]:
<matplotlib.legend.Legend at 0x1bfdddb1590>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_18_1.png
[17]:
spec_1 = sec.get_dOD_spectrum(V=1.0, V_ref=0.66)
spec_1.plot()
[17]:
<Axes: xlabel='wavelength / [nm]', ylabel='$\\Delta$ OD'>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_19_1.png
[18]:
ax = sec.get_dOD_spectrum(V=1.0, V_ref=0.66).plot(color="b", label="species 1")
sec.get_dOD_spectrum(V=1.4, V_ref=1.0).plot(color="g", label="species 2", ax=ax)
sec.get_dOD_spectrum(V=1.7, V_ref=1.4).plot(color="r", label="species 3", ax=ax)
ax.legend()
[18]:
<matplotlib.legend.Legend at 0x1bfe318f810>
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_20_1.png
[19]:
sec.export(data_dir / "sec_export.csv")

print(sec.reference_spectrum.name)
wrote C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export_spectra.csv!
wrote C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export_reference.csv!
writing C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_export.csv!
spectra_0.66V
[20]:


sec_reloaded = Measurement.read(data_dir / "sec_export.csv", reader="ixdat") sec_reloaded.set_reference_spectrum(V_ref=0.66) sec_reloaded.plot_vs_potential(cmap_name="jet")
skipping the following line:
ixdat version = 0.2.7.dev1

skipping the following line:
backend_name = BackendBase(none, address=none)

skipping the following line:
backend_name = BackendBase(none, address=none)

skipping the following line:
backend_name = BackendBase(none, address=none)

C:\Users\Søren\git\ixdat\src\ixdat\plotters\base_mpl_plotter.py:61: MatplotlibDeprecationWarning: Auto-removal of overlapping axes is deprecated since 3.6 and will be removed two minor releases later; explicitly call ax.remove() as needed.
  axes = [plt.subplot(gs[0:3, 0])]
[20]:
[<Axes: xlabel='$U_{RHE}$ / [V]', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='$U_{RHE}$ / [V]', ylabel='J / [mA cm$^{-2}$]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_22_3.png
[21]:
[(s.name, s.shape) for s in sec_reloaded.series_list]


[21]:
[('time from scan rate', (1100,)),
 ('$U_{RHE}$ / [V]', (1100,)),
 ('J / [mA cm$^{-2}$]', (1100,)),
 ('selector', (1100,)),
 ('w800', (1100,)),
 ('w580', (1100,)),
 ('w480', (1100,))]

Open-circuit potential decay

[22]:
sec_decay = Measurement.read(
    data_dir / "decay/PDtest-1.35-1OSP-SP.csv",
    path_to_ref_spec_file=data_dir / "WL.csv",
    path_to_t_U_file=data_dir / "decay/PDtest-1.35-1OSP-E-t.csv",
    path_to_t_J_file=data_dir / "decay/PDtest-1.35-1OSP-J-t.csv",
    tstamp=1,
    reader="msrh_sec_decay",
)
[23]:
sec_decay.plot_measurement()
C:\Users\Søren\git\ixdat\src\ixdat\plotters\base_mpl_plotter.py:61: MatplotlibDeprecationWarning: Auto-removal of overlapping axes is deprecated since 3.6 and will be removed two minor releases later; explicitly call ax.remove() as needed.
  axes = [plt.subplot(gs[0:3, 0])]
[23]:
[<Axes: xlabel='t for spectra', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='time / [s]', ylabel='raw potential / [V]'>,
 None,
 <Axes: ylabel='raw current / [mA]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_26_2.png
[24]:
sec_decay.calibrate_RE(RE_vs_RHE=0.26)
sec_decay.set_reference_spectrum(t_ref=5)
sec_decay.plot_measurement(cmap_name="jet")
[24]:
[<Axes: xlabel='t for spectra', ylabel='wavelength / [nm]'>,
 <Axes: xlabel='time / [s]', ylabel='$U_{RHE}$ / [V]'>,
 None,
 <Axes: ylabel='raw current / [mA]'>]
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_27_1.png
[25]:
sec_decay.plot_wavelengths(wavelengths=["w480", "w600", "w850"])
C:\Users\Søren\git\ixdat\src\ixdat\plotters\sec_plotter.py:365: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
  cmap = mpl.cm.get_cmap(cmap_name)
../../../../_images/tutorials_tutorials_repo_L2_techniques_spectroelectrochemistry_ixdat_demo_spectroelectrochemistry_28_1.png
[26]:
sec_decay.export(data_dir / "sec_decay_export.csv")
wrote C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export_spectra.csv!
wrote C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export_reference.csv!
writing C:\Users\Søren\Dropbox\ixdat_resources\test_data\sec\sec_decay_export.csv!