Examples
The following examples are also available in the examples directory.
Load and save data
This example shows how to load/save methods and measurements and how to inspect the data.
from pathlib import Path
import pandas as pd
import pypalmsens as ps
examples_dir = Path(__file__).parent
# load a method file
method = ps.load_method_file(examples_dir / 'PSDummyCell_LSV.psmethod', as_method=True)
# save the method file
ps.save_method_file(examples_dir / 'PSDummyCell_LSV_copy.psmethod', method)
# load a session file
measurements = ps.load_session_file(examples_dir / 'Demo CV DPV EIS IS-C electrode.pssession')
for measurement in measurements:
print(f'loaded measurement: {measurement.title}, {measurement.timestamp}')
print(f'number of curves: {len(measurement.curves)}')
for curve in measurement.curves:
print(f'curve title: {curve.title}')
print(f'number of points: {len(curve.x_array)}')
print(f'number of peaks: {len(curve.peaks)}')
print(f'Has EIS fit results: {"yes" if len(measurement.eis_fit) > 0 else "no"}')
# save the session file
ps.save_session_file(
examples_dir / 'Demo CV DPV EIS IS-C electrode_copy.pssession', [measurements[0]]
)
# convert measurments to pandas dataframes
frames = []
frame_names = []
for measurement in measurements:
dataset = measurement.dataset
frames.append(dataset.to_dataframe())
frame_names.append(measurement.title)
df = pd.concat(frames, keys=frame_names)
print(df)
Manual control
This example shows how to discover devices, establish a connection and control an instrument manually.
import pypalmsens as ps
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.set_cell(True)
print('cell enabled')
manager.set_potential(1)
print('set potential to 1V')
manager.set_current_range(ps.settings.CURRENT_RANGE.cr_1_mA)
print('set cell to to 1mA currrent range')
current = manager.read_current()
print('current = ' + str(current) + ' µA')
manager.set_cell(False)
print('cell disabled')
Manual control async
This example shows how to discover devices, establish a connection and control an instrument manually using the asynchronous instrument manager.
import asyncio
import pypalmsens as ps
async def main():
instruments = await ps.discover_async()
print(instruments)
async with await ps.connect_async(instruments[0]) as manager:
await manager.set_cell(True)
print('cell enabled')
await manager.set_potential(1)
print('set potential to 1V')
await manager.set_current_range(ps.settings.CURRENT_RANGE.cr_1_mA)
print('set cell to to 1mA currrent range')
current = await manager.read_current()
print(f'current = {current} µA')
await manager.set_cell(False)
print('cell disabled')
asyncio.run(main())
Measure CA
This example shows how to set up and run a chronoamperometry measurement.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
serial = manager.get_instrument_serial()
print(serial)
# Chronoamperometry measurement using helper class
method = ps.ChronoAmperometry(
interval_time=0.01,
potential=1.0,
run_time=10.0,
)
measurement = manager.measure(method)
print(measurement)
Measure CA async
This example shows how to set up and run a chronoamperometry measurement using the asynchronous instrument manager.
import asyncio
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
async def main():
instruments = await ps.discover_async()
print(instruments)
async with await ps.connect_async(instruments[0]) as manager:
manager.callback = new_data_callback
serial = await manager.get_instrument_serial()
print(serial)
# Chronoamperometry measurement using helper class
method = ps.ChronoAmperometry(
interval_time=0.02,
potential=1.0,
run_time=2.0,
)
measurement = await manager.measure(method)
print(measurement)
asyncio.run(main())
Measure CV
This example shows how to set up and run a cyclic voltammetry measurement.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
serial = manager.get_instrument_serial()
print(serial)
method = ps.CyclicVoltammetry(
current_range=ps.settings.CurrentRange(
max=ps.settings.CURRENT_RANGE.cr_1_A, # 1 A range
min=ps.settings.CURRENT_RANGE.cr_1_uA, # 1 µA range
start=ps.settings.CURRENT_RANGE.cr_1_mA, # 1 mA range
),
equilibration_time=2, # seconds
begin_potential=-2, # V
vertex1_potential=-2, # V
vertex2_potential=3, # V
step_potential=0.05, # V
scanrate=5, # V/s
n_scans=3, # number of scans
)
measurement = manager.measure(method)
print(measurement)
Measure EIS
This example shows how to set up and run a EIS measurement.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
serial = manager.get_instrument_serial()
print(serial)
# EIS measurement using helper class
method = ps.ElectrochemicalImpedanceSpectroscopy()
measurement = manager.measure(method)
print(measurement)
MethodSCRIPT sandbox
This example shows how to set up and run a MethodSCRIPT Sandbox measurement.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
script = """e
var c
var p
var e
var l
var r
var j
var o
var d
var n
set_gpio_cfg 0x0f 1
set_pgstat_chan 0
set_pgstat_mode 3
set_acquisition_frac_autoadjust 50
set_max_bandwidth 0
cell_off
set_range ba 210m
set_autoranging ba 210m 210m
set_range ab 4200m
set_autoranging ab 210m 4200m
meas_loop_ocp o 200m 1
pck_start
pck_add o
pck_end
endloop
set_range ba 2100u
set_autoranging ba 2100n 2100u
set_range ab 4200m
set_autoranging ab 4200m 4200m
store_var d -200m ab
add_var d o
store_var n 200m ab
add_var n o
set_e d
cell_on
set_gpio 10i
meas_loop_acv p c e l r j d n 10m 200m 10m 100
pck_start
pck_add p
pck_add c
pck_add e
pck_add l
pck_add r
pck_add j
pck_end
endloop
on_finished:
cell_off
"""
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
serial = manager.get_instrument_serial()
print(serial)
method = ps.MethodScript(script=script)
measurement = manager.measure(method)
print(measurement)
Stream data to CSV
This example shows how to set up and run a chronoamperometry measurement and write the results to a CSV file in real-time.
import csv
import pypalmsens as ps
def stream_to_csv_callback(new_data):
for point in new_data:
csv_writer.writerow([point['index'], point['x'], point['y']])
# csv_writer.writerow([point['frequency'], point['zre'], point['zim']]) #for EIS
csv_file = open('test.csv', 'w', newline='')
csv_writer = csv.writer(csv_file, delimiter=' ')
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = stream_to_csv_callback
serial = manager.get_instrument_serial()
print(serial)
# Chronoamperometry measurement using helper class
method = ps.ChronoAmperometry(
interval_time=0.0004,
potential=1.0,
run_time=10.0,
)
measurement = manager.measure(method)
print(measurement)
csv_file.close()
SWV versus OCP
This example shows how to set up and run a square wave voltammetry measurement versus OCP.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
method = ps.SquareWaveVoltammetry(
pretreatment=ps.settings.Pretreatment(
conditioning_potential=2.0, # V
conditioning_time=2, # seconds
),
versus_ocp=ps.settings.VersusOCP(
mode=3, # versus begin and end potential
max_ocp_time=1, # seconds
),
begin_potential=-0.5, # V
end_potential=0.5, # V
step_potential=0.01, # V
amplitude=0.08, # V
frequency=50, # Hz
)
measurement = manager.measure(method)
print(measurement)
print(f'ocp: {measurement.ocp_value}')
Multiplexer
This example shows how to set up and control a multiplexer and run consecutive and alternating multiplexer measurments.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
instruments = ps.discover()
print(instruments)
with ps.connect(instruments[0]) as manager:
manager.callback = new_data_callback
n_multiplexer_channels = manager.initialize_multiplexer(2)
manager.set_mux8r2_settings()
for channel in range(n_multiplexer_channels):
manager.set_multiplexer_channel(channel)
# When measuring alternatingly the selection is restricted to the first n channels
altnernating_multiplexer_method = ps.ChronoAmperometry(
interval_time=0.5, # seconds
potential=1.0, # volts
run_time=5.0, # seconds
multiplexer=ps.settings.Multiplexer(
mode='alternate', # 'none', 'consecutive', 'alternate'
channels=[1, 2], # 8 channels, 1 and 2 are enabled
connect_sense_to_working_electrode=False,
combine_reference_and_counter_electrodes=False,
use_channel_1_reference_and_counter_electrodes=False,
set_unselected_channel_working_electrode=0,
),
)
measurement = manager.measure(altnernating_multiplexer_method)
print(measurement)
consecutive_multiplexer_method = ps.SquareWaveVoltammetry(
begin_potential=-0.5, # volts
end_potential=0.5, # volts
step_potential=0.01, # volts
amplitude=0.1, # volts
frequency=10, # hertz
multiplexer=ps.settings.Multiplexer(
mode='consecutive', # 'none', 'consecutive', 'alternate'
channels=[1, 2, 7, 8], # channels 1, 2, 7 and 8 are enabled
connect_sense_to_working_electrode=False,
combine_reference_and_counter_electrodes=False,
use_channel_1_reference_and_counter_electrodes=False,
set_unselected_channel_working_electrode=0,
),
)
measurement = manager.measure(consecutive_multiplexer_method)
print(measurement)
Multichannel measurement
This example shows how to connect to a collection of instruments and run a chronoamperometry measurement on all channels simultaneously.
import pypalmsens as ps
def new_data_callback(new_data):
for point in new_data:
print(point)
method = ps.ChronoAmperometry(
interval_time=0.004,
potential=1.0,
run_time=5.0,
)
instruments = ps.discover()
print(instruments)
# run multichannel experiment with callback
with ps.InstrumentPool(instruments, callback=new_data_callback) as pool:
results = pool.measure(method=method)
print(results)
Multichannel CSV writer
This example shows how to connect to a how to use a callback to automatically store data to a csv file while collecting data from collection of instruments.
import asyncio
import pypalmsens as ps
import csv
import functools
def stream_to_csv_callback(new_data, csv_writer):
for point in new_data:
csv_writer.writerow([point['index'], point['x'], point['y']])
async def stream_to_csv(manager, *, method):
"""Measure with a custom csv writer callback."""
serial = await manager.get_instrument_serial()
with open(f'{serial}.csv', 'w', newline='') as csv_file:
csv_writer = csv.writer(csv_file, delimiter=' ')
callback = functools.partial(stream_to_csv_callback, csv_writer=csv_writer)
manager.callback = callback
measurement = await manager.measure(method)
print(f'Wrote data to {csv_file.name}')
return measurement
async def main():
method = ps.ChronoAmperometry(
interval_time=0.004,
potential=1.0,
run_time=5.0,
)
instruments = await ps.discover_async(ftdi=True)
print(instruments)
# run multichannel experiment with csv writer
async with ps.InstrumentPoolAsync(instruments) as pool:
results = await pool.submit(stream_to_csv, method=method)
print(results)
asyncio.run(main())
Multichannel custom loop
This example shows how to run and set up a sequence of measurements on a collection of channels simultaneously.
import asyncio
from attrs import evolve
import pypalmsens as ps
async def custom_loop(manager, *, method, steps):
measurements = []
for step in steps:
method = evolve(method, **step)
measurements.append(await manager.measure(method))
return measurements
async def main():
method = ps.ChronoAmperometry(
interval_time=0.004,
run_time=5.0,
)
steps = [
{
'potential': 0.4,
},
{
'potential': 0.6,
},
{
'potential': 1.0,
},
]
instruments = await ps.discover_async(ftdi=True)
print(instruments)
async with ps.InstrumentPoolAsync(instruments) as pool:
results = await pool.submit(custom_loop, method=method, steps=steps)
print(results)
for i, measurements in enumerate(results):
ps.save_session_file(f'example-{i}.pssession', measurements)
asyncio.run(main())
Multichannel HW sync
This example shows how to connect to a collection of instruments and run a chronopotentiometry measurement on all channels simultaneously using hardware synchronization.
import asyncio
import pypalmsens as ps
async def main():
method = ps.ChronoAmperometry(
interval_time=0.004,
potential=1.0,
run_time=5.0,
)
method.general.use_hardware_sync = True
instruments = await ps.discover_async(ftdi=True)
print(instruments)
async with ps.InstrumentPoolAsync(instruments) as pool:
results = await pool.measure(method)
print(results)
asyncio.run(main())