Live Data Callbacks
This example demonstrates how to use the zahner_link library’s event-driven callback system to receive live measurement data as it is being recorded. In addition to waiting for a job to finish and retrieving all the data at once, callbacks provide real-time access to each data row, header, and status update as they occur.
This is particularly useful for:
Monitoring long-running measurements - see data as it arrives, not just at the end
Building custom GUIs - update plots or status indicators in real time
Logging and diagnostics - track exactly when each measurement phase starts, progresses, and finishes
This notebook covers:
Registering event handlers: Using ZahnerLinkEventHandler factory methods to create callbacks for DC and EIS live data
DC live data callbacks: Observing header, data rows, and finished events during an OcvJob measurement
EIS live data callbacks: Observing EIS-specific header, impedance row, wave, and finished events during an EisGenerateJob measurement
Job status updates: Tracking when a job starts, is running, and completes
Connection status: Monitoring the connection state via set_connection_status_callback() (see ErrorHandling.ipynb for a detailed example of connection error handling)
Cleanup: Properly removing event handlers with clear_event_handler() before disconnecting
All callback print statements include a relative timestamp (seconds since notebook start) so you can see exactly when each event occurs.
import time
import zahner_link as zl
import numpy as np
START_TIME = time.perf_counter()
def elapsed() -> str:
"""Return a formatted string with seconds elapsed since notebook start."""
return f"{time.perf_counter() - START_TIME:>8.3f}s"
Defining Callback Functions
Each callback receives specific event data from the library. We define one function per event type:
on_connection_status_changed- called when the connection state transitions (connected, disconnected). Receives a ZahnerLinkConnectionStatusEnumon_live_data_header- called once at the start of a DC measurement job with a LiveDataHeader describing the data columns and a JobInfo identifying the jobon_live_data_header_eis- same concept for EIS measurements, providing a LiveDataHeaderEis with impedance and path header informationon_live_data_rows- delivers one or more rows of DC live data as a list of lists of floatson_live_data_row_eis- delivers a single EIS data point as a LiveDataRowEis containing impedance valueson_live_data_wave- delivers raw waveform data for EIS as a LiveDataWavesEis objecton_live_data_finished- signals that a job’s live data stream has endedon_job_status_update- reports job lifecycle transitions (queued, running, finished) via JobStatusEnum
def on_connection_status_changed(status: zl.ZahnerLinkConnectionStatusEnum):
print(f"[{elapsed()}] [CONNECTION] Status changed: {status}")
def on_live_data_header(header: zl.LiveDataHeader, job_info: zl.JobInfo):
column_names = [column.get_dimension() for column in header.get_columns()]
print(
f"[{elapsed()}] [HEADER DC] Job {job_info.get_job_id()}"
f" - type: {header.get_short_type()}, columns: {column_names}"
)
def on_live_data_header_eis(header: zl.LiveDataHeaderEis, job_info: zl.JobInfo):
impedance_columns = [column.get_dimension() for headers in header.get_impedances_headers() for column in headers.get_columns()]
meta_columns = [column.get_dimension() for column in header.get_meta_data_header()]
print(
f"[{elapsed()}] [HEADER EIS] Job {job_info.get_job_id()}"
f" - impedance headers length: {len(header.get_impedances_headers())} impedance columns: {impedance_columns} meta columns: {meta_columns}"
)
def on_live_data_rows(rows: list[list[float]]):
text = f"[{elapsed()}] [DC ROW]"
for row in rows:
text += f" {row}"
print(text)
def on_live_data_row_eis(row: zl.LiveDataRowEis):
print(f"[{elapsed()}] [EIS ROW] impedances: {row.get_impedances()} meta: {row.get_meta()}")
def on_live_data_wave(waves: zl.LiveDataWavesEis):
print(
f"[{elapsed()}] [EIS WAVE] position={waves.get_position()},"
f" {len(waves.get_waves())} wave channels"
)
def on_live_data_finished(job_info: zl.JobInfo):
print(f"[{elapsed()}] [FINISHED] Job {job_info.get_job_id()} live data complete")
def on_job_status_update(status: zl.JobStatusEnum, job_info: zl.JobInfo):
print(f"[{elapsed()}] [JOB STATUS] Job {job_info.get_job_id()}: {status}")
Connecting and Registering Event Handlers
We create a ZahnerLinkExc instance and register all event handlers connecting. Each handler is created via a static factory method on ZahnerLinkEventHandler and then passed to set_event_handler().
The connection status callback is set separately via set_connection_status_callback().
We keep references to all handlers in a list so we can cleanly remove them later.
link = zl.ZahnerLinkExc("10.10.253.150", "1994")
# Register connection status callback
link.set_connection_status_callback(on_connection_status_changed)
# Create and register all event handlers
handlers = [
zl.ZahnerLinkEventHandler.make_live_data_header_event_handler(on_live_data_header),
zl.ZahnerLinkEventHandler.make_live_data_header_eis_event_handler(on_live_data_header_eis),
zl.ZahnerLinkEventHandler.make_live_data_rows_event_handler(on_live_data_rows),
zl.ZahnerLinkEventHandler.make_live_data_row_eis_event_handler(on_live_data_row_eis),
zl.ZahnerLinkEventHandler.make_live_data_wave_event_handler(on_live_data_wave),
zl.ZahnerLinkEventHandler.make_live_data_finished_event_handler(on_live_data_finished),
zl.ZahnerLinkEventHandler.make_job_status_update_event_handler(on_job_status_update),
]
for handler in handlers:
link.set_event_handler(handler)
# Connect
print(f"[{elapsed()}] Connecting...")
error: zl.ErrorObject = link.connect()
if not error:
print(f"[{elapsed()}] Connected successfully")
else:
print(f"[{elapsed()}] Failed to connect: {error.get_error_code_enum()}")
[ 0.021s] Connecting...
[ 0.024s] Connected successfully
[ 0.024s] [CONNECTION] Status changed: ZahnerLinkConnectionStatusEnum.CONNECTED
OCV Measurement - Observing DC Live Data
An OcvJob measures the Open Circuit Voltage over time. This is a DC measurement, so the following callbacks will fire:
on_live_data_header- once at the start, describing the data columnson_live_data_rows- repeatedly during the measurement, delivering data rowson_live_data_finished- once when the measurement is doneon_job_status_update- at each job lifecycle transition
Watch the timestamps to see how the data arrives in real time while do_job() blocks until the job completes.
Note that live DC data may be incomplete depending on the output data rate.
ocv_job = zl.meas.OcvJob(duration=5, output_data_rate=5)
print(f"[{elapsed()}] Starting OCV measurement...")
link.do_job(ocv_job)
print(f"[{elapsed()}] OCV measurement complete")
result = link.get_job_result_data(ocv_job)
print(f"[{elapsed()}] OCV result: {result.get_row_count()} data points")
[ 0.033s] Starting OCV measurement...
[ 0.035s] [JOB STATUS] Job 06c42b5d-1dab-43f9-8a35-46dab1c2f52f: JobStatusEnum.PENDING
[ 0.035s] [JOB STATUS] Job 06c42b5d-1dab-43f9-8a35-46dab1c2f52f: JobStatusEnum.RUNNING
[ 0.035s] [HEADER DC] Job 06c42b5d-1dab-43f9-8a35-46dab1c2f52f - type: ocv, columns: ['time', 'voltage', 'current', 'shunt']
[ 0.240s] [DC ROW] [0.2, -0.00010937730808857705, -6.684560288316892e-11, 11.0]
[ 0.640s] [DC ROW] [0.4, -0.00014749760645954284, 5.859794670546467e-13, 11.0]
[ 0.846s] [DC ROW] [0.6, -0.00014247600429531535, 4.3931734872539164e-13, 11.0]
[ 1.041s] [DC ROW] [0.8, -0.00014879932274871637, 4.912575847217919e-13, 11.0]
[ 1.245s] [DC ROW] [1.0, -0.00014670780107060608, 4.563612422716026e-13, 11.0]
[ 1.440s] [DC ROW] [1.2, -0.0001448210437525905, 4.335327774508962e-13, 11.0]
[ 1.646s] [DC ROW] [1.4, -0.0001440702410989099, 4.2701143844385563e-13, 11.0]
[ 1.841s] [DC ROW] [1.6, -0.0001415691907006102, 3.719918911550231e-13, 11.0]
[ 2.046s] [DC ROW] [1.8, -0.00014178370574451893, 3.9979259359639304e-13, 11.0]
[ 2.241s] [DC ROW] [2.0, -0.00014342669596718367, 4.550123905766353e-13, 11.0]
[ 2.446s] [DC ROW] [2.2, -0.00014163257014540142, 3.6477912396820935e-13, 11.0]
[ 2.641s] [DC ROW] [2.4, -0.00014336331652239245, 3.8745267865027803e-13, 11.0]
[ 2.846s] [DC ROW] [2.6, -0.00014462603007630984, 3.9596517968322265e-13, 11.0]
[ 3.040s] [DC ROW] [2.8, -0.00014377772058448888, 3.8703328778713694e-13, 11.0]
[ 3.246s] [DC ROW] [3.0, -0.00014407511644081691, 4.144070427732372e-13, 11.0]
[ 3.441s] [DC ROW] [3.2, -0.00014319755489755387, 3.17656215453835e-13, 11.0]
[ 3.646s] [DC ROW] [3.4, -0.0001451281902927326, 3.565537734361541e-13, 11.0]
[ 3.842s] [DC ROW] [3.6, -0.00014478691635924138, 4.2274196389115815e-13, 11.0]
[ 4.047s] [DC ROW] [3.8, -0.0001456498518767834, 3.6562168399055587e-13, 11.0]
[ 4.241s] [DC ROW] [4.0, -0.00014652253807813945, 4.172294299332947e-13, 11.0]
[ 4.446s] [DC ROW] [4.2, -0.0001472050859451218, 3.0197628678684866e-13, 11.0]
[ 4.641s] [DC ROW] [4.4, -0.00014838004334471292, 3.666493805200547e-13, 11.0]
[ 4.846s] [DC ROW] [4.6, -0.00015026680066272847, 4.3427332347950565e-13, 11.0]
[ 5.037s] [FINISHED] Job 06c42b5d-1dab-43f9-8a35-46dab1c2f52f live data complete
[ 5.037s] [JOB STATUS] Job 06c42b5d-1dab-43f9-8a35-46dab1c2f52f: JobStatusEnum.FINISHED
[ 5.037s] OCV measurement complete
[ 5.038s] [JOB STATUS] Job 9cb822aa-7401-4df5-9a68-feb70625391d: JobStatusEnum.DELETED
[ 5.040s] OCV result: 25 data points
EIS Measurement - Observing EIS Live Data
Now we run an EisGenerateJob in galvanostatic mode. This triggers the EIS-specific callbacks:
on_live_data_header_eis- once at the start, describing impedance headers, path headers, and potentiostat headerson_live_data_row_eis- for each measured frequency point, delivering impedance dataon_live_data_wave- for each frequency point, delivering the raw waveform dataon_live_data_finished- once when the EIS spectrum is completeon_job_status_update- at each job lifecycle transition
Before starting the EIS measurement, we switch on the potentiostat in galvanostatic mode using SwitchOnJob. Afterwards, we switch it off with SwitchOffJob.
main_pot = "MAIN:1:POT"
switch_on_job = zl.control.SwitchOnJob(
potentiostat=main_pot,
coupling=zl.PotentiostatCoupling.POTENTIOSTATIC,
bias=0,
voltage_range_index=0,
compliance_range_index=0,
)
switch_off_job = zl.control.SwitchOffJob(potentiostat=main_pot)
print(f"[{elapsed()}] Switching off potentiostat...")
link.do_job(switch_off_job)
print(f"[{elapsed()}] Switching on potentiostat (galvanostatic, 0 A)...")
link.do_job(switch_on_job)
eis_job = zl.meas.EisGenerateJob(
bias=0.0,
min_frequency=10,
max_frequency=10e3,
start_frequency=1000,
points_per_decade_upper=10,
points_per_decade_lower=10,
pre_duration=0.0,
pre_waves=1,
meas_duration=0.1,
meas_waves=3,
amplitude=0.01,
)
print(f"[{elapsed()}] Starting EIS measurement...")
link.do_job(eis_job)
print(f"[{elapsed()}] EIS measurement complete")
print(f"[{elapsed()}] Switching off potentiostat...")
link.do_job(switch_off_job)
[ 5.046s] Switching off potentiostat...
[ 5.091s] Switching on potentiostat (galvanostatic, 0 A)...
[ 6.372s] Starting EIS measurement...
[ 6.374s] [JOB STATUS] Job cd95f72e-09f4-4ff6-8a99-ab274322a829: JobStatusEnum.PENDING
[ 6.375s] [JOB STATUS] Job cd95f72e-09f4-4ff6-8a99-ab274322a829: JobStatusEnum.RUNNING
[ 6.707s] [HEADER EIS] Job cd95f72e-09f4-4ff6-8a99-ab274322a829 - impedance headers length: 1 impedance columns: ['|impedance|', 'phase', 'impedance error', 'phase error', 'impedance drift', 'phase drift'] meta columns: ['frequency', 'periods', 'time']
[ 7.427s] [EIS ROW] impedances: [[282.65488612860753, -0.4959276986037121, 0.030378253606784256, 9.900392944311998e-05, -0.0041894284908607915, 9.931223285408741e-08]] meta: [1000.0, 3.0, 0.7260000705718994]
[ 7.537s] [EIS ROW] impedances: [[262.6359117394668, -0.5643713294628673, 0.01602030438291043, 7.558123261497408e-05, 0.016838091702339852, 0.0001890546041151686]] meta: [1316.8731278794617, 3.0, 0.8369998931884766]
[ 7.650s] [EIS ROW] impedances: [[241.82303935645115, -0.6297183733972297, 0.026122787582405868, 5.522961584839151e-05, -0.05582777869962854, -0.00032058141530399986]] meta: [1657.8450447963244, 11.0, 0.9489998817443848]
[ 7.754s] [EIS ROW] impedances: [[217.71748345865961, -0.6953787152242742, 0.022447811326604457, 7.698938014809308e-05, 0.07012652321770241, 0.0005614736610528986]] meta: [2087.1032557111325, 10.0, 1.053999900817871]
[ 8.188s] [EIS ROW] impedances: [[191.7548125156789, -0.7540858487862567, 0.01744303104642688, 7.624767052141433e-05, -0.005121720460942924, -9.281649836827554e-05]] meta: [2627.5073256530845, 11.0, 1.4869999885559082]
[ 8.297s] [EIS ROW] impedances: [[165.7504958480192, -0.798447368688576, 0.010784991129573145, 8.156439903219713e-05, -0.003910095609040809, 7.139488188531162e-05]] meta: [3307.835741940001, 11.0, 1.5959999561309814]
[ 8.407s] [EIS ROW] impedances: [[141.43760696343705, -0.8222452396223744, 0.011859273641213112, 6.2602626419104e-05, 0.04896567763163659, -0.00015909455300523457]] meta: [4164.31847356928, 11.0, 1.7070000171661377]
[ 8.514s] [EIS ROW] impedances: [[120.00165447817258, -0.8227417556499314, 0.008628696008803493, 7.688831912300744e-05, 0.004057302322458156, 4.487687158145626e-05]] meta: [5242.566349180264, 11.0, 1.813999891281128]
[ 8.619s] [EIS ROW] impedances: [[102.06443321174937, -0.7990346998533226, 0.0067707167567765325, 5.989392000750535e-05, -0.0012651208309226124, 0.000648721303694168]] meta: [6600.000000000008, 38.0, 1.9179999828338623]
[ 9.050s] [EIS ROW] impedances: [[78.51530165726489, -0.7015662751331168, 0.0047676488967934435, 5.1073225519658365e-05, -0.01727656300467691, 3.088271219494835e-05]] meta: [10000.0, 37.0, 2.3499999046325684]
[ 9.479s] [EIS ROW] impedances: [[102.06274962062284, -0.7991072611359502, 0.0072362492298287725, 6.851565386629422e-05, 0.023338246782931747, 9.203002364317143e-05]] meta: [6600.000000000008, 38.0, 2.7790000438690186]
[ 9.586s] [EIS ROW] impedances: [[120.00641187114137, -0.8227909099311663, 0.009281618079519383, 4.386794716415869e-05, -0.0033921620998142994, -3.5437621658840345e-05]] meta: [5242.566349180264, 11.0, 2.885999917984009]
[ 9.697s] [EIS ROW] impedances: [[141.44270056207733, -0.8224025051271574, 0.0095639351272811, 4.789892444449213e-05, -0.03590994846854869, -7.366126398414829e-05]] meta: [4164.31847356928, 11.0, 2.996000051498413]
[ 9.806s] [EIS ROW] impedances: [[165.74129146724167, -0.7983200872790199, 0.014969299356740852, 7.107125423706731e-05, -0.045014432853545824, 0.0001242221270137733]] meta: [3307.835741940001, 11.0, 3.1050000190734863]
[ 9.915s] [EIS ROW] impedances: [[191.76118828808242, -0.7542772415942464, 0.01508551045615563, 8.237807461299236e-05, -0.05100478678516822, 0.0001768882273273986]] meta: [2627.5073256530845, 11.0, 3.2149999141693115]
[ 10.344s] [EIS ROW] impedances: [[217.7326998569963, -0.6952803693400652, 0.01881442712021186, 0.00012541245759435055, 0.1454498311597342, -0.00038176249454281675]] meta: [2087.1032557111325, 10.0, 3.6429998874664307]
[ 10.456s] [EIS ROW] impedances: [[241.79867134891342, -0.6295817550102568, 0.0284473878584637, 5.834301422705451e-05, 0.05582073575674541, 3.334415524733902e-05]] meta: [1657.8450447963244, 11.0, 3.75600004196167]
[ 10.567s] [EIS ROW] impedances: [[262.66791029525893, -0.5643085741537377, 0.04651746851995616, 9.586806840918469e-05, 0.005203697260952822, -0.00020857477273300562]] meta: [1316.8731278794617, 3.0, 3.865999937057495]
[ 10.674s] [EIS ROW] impedances: [[279.7502381051408, -0.5063474949891107, 0.02309247956266821, 0.00010907924096522266, -0.22092581717777193, -0.0005591117547989466]] meta: [1046.0295070243358, 3.0, 3.9739999771118164]
[ 10.789s] [EIS ROW] impedances: [[293.4663374220401, -0.46043119532606275, 0.00853700620405107, 0.00011318308942257864, 0.060518119687259286, 0.00029757250403122937]] meta: [830.8907717841511, 3.0, 4.08899998664856]
[ 10.896s] [EIS ROW] impedances: [[304.7701200790804, -0.42940931883716615, 0.007267752197587167, 5.170506548172564e-06, -0.13568392943187746, -0.00015413748860321208]] meta: [660.0000000000006, 3.0, 4.19599986076355]
[ 11.339s] [EIS ROW] impedances: [[314.83643617808804, -0.4148162490138249, 0.020930911083553383, 2.774628399426771e-05, 0.10006938005659549, -0.0003287461119424462]] meta: [524.2566349180262, 3.0, 4.638999938964844]
[ 11.449s] [EIS ROW] impedances: [[325.581583710885, -0.4159014695601678, 0.014508660051205881, 6.408354428993901e-05, -0.2527975655355874, 2.9499444747532744e-05]] meta: [416.4318473569278, 3.0, 4.749000072479248]
[ 11.562s] [EIS ROW] impedances: [[338.3973898469851, -0.43216080574639615, 0.01935528570658107, 2.4943437191874793e-05, -0.2559952756721202, -0.00017650208081487762]] meta: [330.78357419399987, 3.0, 4.861999988555908]
[ 11.673s] [EIS ROW] impedances: [[355.4813686843904, -0.45977093831149474, 0.003059318619553627, 3.7330113129507854e-05, 0.0022492022854976312, 0.00015735354039492222]] meta: [262.7507325653083, 3.0, 4.9730000495910645]
[ 11.812s] [EIS ROW] impedances: [[378.6808811466669, -0.49598384008825414, 0.020703371610655573, 1.595986442357959e-05, -0.06648172794118068, -0.0007854324837352211]] meta: [208.7103255711131, 3.0, 5.111000061035156]
[ 12.018s] [EIS ROW] impedances: [[410.5433100676387, -0.533095162399985, 0.055435850775306036, 5.067034330467439e-05, 0.24112693700178056, 0.000176662000935357]] meta: [165.78450447963232, 3.0, 5.316999912261963]
[ 12.498s] [EIS ROW] impedances: [[452.7773237028681, -0.5643025989008165, 0.0036750765107550856, 1.8720325151081834e-05, 0.2320919373746051, 0.00041323843821777784]] meta: [131.68731278794607, 3.0, 5.797999858856201]
[ 12.617s] [EIS ROW] impedances: [[506.1444346997493, -0.5816749375976323, 0.0019317876605668973, 7.470890475232603e-05, -0.14486827912318745, 0.0001845146808615028]] meta: [104.6029507024335, 3.0, 5.91700005531311]
[ 12.766s] [EIS ROW] impedances: [[569.7620295630629, -0.5799589941909735, 0.04194043788288582, 6.994506035851168e-05, 0.04205612961141014, -0.000198140591823881]] meta: [83.08907717841504, 3.0, 6.065999984741211]
[ 12.952s] [EIS ROW] impedances: [[640.2979468006299, -0.5577135554907628, 0.031005202173560068, 4.318155326876738e-05, 0.022796491737722135, 0.0001277475392869043]] meta: [66.0, 3.0, 6.251999855041504]
[ 13.186s] [EIS ROW] impedances: [[712.4635436843708, -0.5166588465331953, 0.012317449946105322, 6.014400186471481e-05, 0.21224879397362884, 0.0003367062478428773]] meta: [52.425663491802574, 3.0, 6.486000061035156]
[ 13.479s] [EIS ROW] impedances: [[780.4589952868012, -0.46244185662368326, 0.02267565500521111, 0.0002121828401529339, 0.31820484042697217, -0.00039030100419504277]] meta: [41.64318473569275, 3.0, 6.7790000438690186]
[ 13.497s] [EIS WAVE] position=134, 2 wave channels
[ 13.513s] [EIS WAVE] position=6, 2 wave channels
[ 13.529s] [EIS WAVE] position=142, 2 wave channels
[ 13.545s] [EIS WAVE] position=22, 2 wave channels
[ 13.561s] [EIS WAVE] position=158, 2 wave channels
[ 13.577s] [EIS WAVE] position=38, 2 wave channels
[ 13.594s] [EIS WAVE] position=174, 2 wave channels
[ 13.604s] [EIS ROW] impedances: [[839.1294403519418, -0.4006386189863318, 0.09170737619145561, 7.202028848159644e-05, 0.22630810644454868, -0.0008484852582578695]] meta: [33.078357419399964, 3.0, 6.9040000438690186]
[ 13.977s] [EIS WAVE] position=106, 2 wave channels
[ 13.993s] [EIS WAVE] position=214, 2 wave channels
[ 14.010s] [EIS WAVE] position=65, 2 wave channels
[ 14.026s] [EIS WAVE] position=173, 2 wave channels
[ 14.042s] [EIS WAVE] position=25, 2 wave channels
[ 14.058s] [EIS WAVE] position=133, 2 wave channels
[ 14.074s] [EIS WAVE] position=241, 2 wave channels
[ 14.090s] [EIS WAVE] position=93, 2 wave channels
[ 14.106s] [EIS WAVE] position=201, 2 wave channels
[ 14.115s] [EIS ROW] impedances: [[886.6584479746053, -0.3394609011666577, 0.31424506792150936, 2.3758234251991528e-05, 0.8752252708530364, 4.348203858514643e-05]] meta: [26.275073256530813, 3.0, 7.414999961853027]
[ 14.122s] [EIS WAVE] position=23, 2 wave channels
[ 14.139s] [EIS WAVE] position=113, 2 wave channels
[ 14.156s] [EIS WAVE] position=203, 2 wave channels
[ 14.172s] [EIS WAVE] position=28, 2 wave channels
[ 14.189s] [EIS WAVE] position=118, 2 wave channels
[ 14.206s] [EIS WAVE] position=208, 2 wave channels
[ 14.223s] [EIS WAVE] position=42, 2 wave channels
[ 14.240s] [EIS WAVE] position=132, 2 wave channels
[ 14.257s] [EIS WAVE] position=222, 2 wave channels
[ 14.274s] [EIS WAVE] position=56, 2 wave channels
[ 14.290s] [EIS WAVE] position=146, 2 wave channels
[ 14.307s] [EIS WAVE] position=236, 2 wave channels
[ 14.312s] [EIS ROW] impedances: [[921.4706124760097, -0.28135594734806435, 0.05914561270727367, 7.738669843606236e-05, 0.1961268519680175, 0.00048268477352381156]] meta: [20.8710325571113, 3.0, 7.611999988555908]
[ 14.323s] [EIS WAVE] position=39, 2 wave channels
[ 14.339s] [EIS WAVE] position=107, 2 wave channels
[ 14.355s] [EIS WAVE] position=175, 2 wave channels
[ 14.372s] [EIS WAVE] position=243, 2 wave channels
[ 14.387s] [EIS WAVE] position=51, 2 wave channels
[ 14.403s] [EIS WAVE] position=119, 2 wave channels
[ 14.420s] [EIS WAVE] position=187, 2 wave channels
[ 14.436s] [EIS WAVE] position=255, 2 wave channels
[ 14.452s] [EIS WAVE] position=67, 2 wave channels
[ 14.468s] [EIS WAVE] position=135, 2 wave channels
[ 14.484s] [EIS WAVE] position=203, 2 wave channels
[ 14.500s] [EIS WAVE] position=15, 2 wave channels
[ 14.516s] [EIS WAVE] position=83, 2 wave channels
[ 14.532s] [EIS WAVE] position=151, 2 wave channels
[ 14.548s] [EIS WAVE] position=219, 2 wave channels
[ 14.557s] [EIS ROW] impedances: [[946.9705662559545, -0.23052058380452436, 0.016447297617446566, 0.0002391429212958707, -0.2121238128825098, -0.0002060137147185115]] meta: [16.578450447963224, 3.0, 7.85699987411499]
[ 14.563s] [EIS WAVE] position=14, 2 wave channels
[ 14.580s] [EIS WAVE] position=68, 2 wave channels
[ 14.596s] [EIS WAVE] position=122, 2 wave channels
[ 14.612s] [EIS WAVE] position=176, 2 wave channels
[ 14.628s] [EIS WAVE] position=230, 2 wave channels
[ 14.645s] [EIS WAVE] position=26, 2 wave channels
[ 14.660s] [EIS WAVE] position=80, 2 wave channels
[ 14.677s] [EIS WAVE] position=134, 2 wave channels
[ 14.693s] [EIS WAVE] position=188, 2 wave channels
[ 14.709s] [EIS WAVE] position=242, 2 wave channels
[ 14.725s] [EIS WAVE] position=40, 2 wave channels
[ 14.741s] [EIS WAVE] position=94, 2 wave channels
[ 14.757s] [EIS WAVE] position=148, 2 wave channels
[ 14.773s] [EIS WAVE] position=202, 2 wave channels
[ 14.789s] [EIS WAVE] position=0, 2 wave channels
[ 14.805s] [EIS WAVE] position=54, 2 wave channels
[ 14.821s] [EIS WAVE] position=108, 2 wave channels
[ 14.837s] [EIS WAVE] position=162, 2 wave channels
[ 14.853s] [EIS WAVE] position=216, 2 wave channels
[ 14.866s] [EIS ROW] impedances: [[963.8362118372272, -0.18723009558000825, 0.057009518721846085, 9.165857236927608e-05, -0.16998747394131897, 1.2090767372921474e-05]] meta: [13.168731278794601, 3.0, 8.164999961853027]
[ 14.869s] [EIS WAVE] position=4, 2 wave channels
[ 14.886s] [EIS WAVE] position=46, 2 wave channels
[ 14.902s] [EIS WAVE] position=88, 2 wave channels
[ 14.919s] [EIS WAVE] position=130, 2 wave channels
[ 14.935s] [EIS WAVE] position=172, 2 wave channels
[ 14.952s] [EIS WAVE] position=214, 2 wave channels
[ 14.967s] [EIS WAVE] position=0, 2 wave channels
[ 14.984s] [EIS WAVE] position=39, 2 wave channels
[ 15.001s] [EIS WAVE] position=81, 2 wave channels
[ 15.017s] [EIS WAVE] position=123, 2 wave channels
[ 15.034s] [EIS WAVE] position=165, 2 wave channels
[ 15.050s] [EIS WAVE] position=207, 2 wave channels
[ 15.067s] [EIS WAVE] position=249, 2 wave channels
[ 15.083s] [EIS WAVE] position=35, 2 wave channels
[ 15.099s] [EIS WAVE] position=77, 2 wave channels
[ 15.116s] [EIS WAVE] position=119, 2 wave channels
[ 15.132s] [EIS WAVE] position=161, 2 wave channels
[ 15.149s] [EIS WAVE] position=203, 2 wave channels
[ 15.165s] [EIS WAVE] position=245, 2 wave channels
[ 15.181s] [EIS WAVE] position=31, 2 wave channels
[ 15.198s] [EIS WAVE] position=73, 2 wave channels
[ 15.214s] [EIS WAVE] position=115, 2 wave channels
[ 15.231s] [EIS WAVE] position=157, 2 wave channels
[ 15.247s] [EIS WAVE] position=199, 2 wave channels
[ 15.264s] [EIS WAVE] position=241, 2 wave channels
[ 15.270s] [EIS ROW] impedances: [[977.4649683598765, -0.14385596080173174, 0.08885757880386791, 0.00011489799315001863, -0.2253068801032896, 0.0008081682553544717]] meta: [10.0, 3.0, 8.569999933242798]
[ 15.270s] [FINISHED] Job cd95f72e-09f4-4ff6-8a99-ab274322a829 live data complete
[ 15.270s] [JOB STATUS] Job cd95f72e-09f4-4ff6-8a99-ab274322a829: JobStatusEnum.FINISHED
[ 15.270s] [JOB STATUS] Job c0ba0d4f-6cde-44a7-8b37-cbede86c866b: JobStatusEnum.DELETED
[ 15.270s] EIS measurement complete
[ 15.270s] Switching off potentiostat...
<zahner_link._zahner_link.ErrorObject at 0x1f7d75d8530>
Retrieving EIS Result Data
After the measurement completes, we can still retrieve the full result dataset using get_job_result_data(). This returns an EisDataset from which we extract the frequencies and complex impedances.
The callbacks provided the data in real time. Here we show the final consolidated result, which can then be saved in the Zahner file format.
eis_data = link.get_job_result_data(eis_job)
impedance_data = eis_data.get_impedance_data()
complex_impedances = impedance_data.get_calculated_complex_impedance_track()
frequencies = eis_data.get_frequencies()
print(f"EIS result: {len(frequencies)} frequency points\n")
for freq, z in zip(frequencies, complex_impedances):
print(f" {freq:>8.2f} Hz |Z| = {np.abs(z):>6.2f} Ohm phase = {np.angle(z,deg=True):>6.2f}°")
EIS result: 39 frequency points
1000.00 Hz |Z| = 282.65 Ohm phase = -28.41°
1316.87 Hz |Z| = 262.64 Ohm phase = -32.34°
1657.85 Hz |Z| = 241.82 Ohm phase = -36.08°
2087.10 Hz |Z| = 217.72 Ohm phase = -39.84°
2627.51 Hz |Z| = 191.75 Ohm phase = -43.21°
3307.84 Hz |Z| = 165.75 Ohm phase = -45.75°
4164.32 Hz |Z| = 141.44 Ohm phase = -47.11°
5242.57 Hz |Z| = 120.00 Ohm phase = -47.14°
6600.00 Hz |Z| = 102.06 Ohm phase = -45.78°
10000.00 Hz |Z| = 78.52 Ohm phase = -40.20°
6600.00 Hz |Z| = 102.06 Ohm phase = -45.79°
5242.57 Hz |Z| = 120.01 Ohm phase = -47.14°
4164.32 Hz |Z| = 141.44 Ohm phase = -47.12°
3307.84 Hz |Z| = 165.74 Ohm phase = -45.74°
2627.51 Hz |Z| = 191.76 Ohm phase = -43.22°
2087.10 Hz |Z| = 217.73 Ohm phase = -39.84°
1657.85 Hz |Z| = 241.80 Ohm phase = -36.07°
1316.87 Hz |Z| = 262.67 Ohm phase = -32.33°
1046.03 Hz |Z| = 279.75 Ohm phase = -29.01°
830.89 Hz |Z| = 293.47 Ohm phase = -26.38°
660.00 Hz |Z| = 304.77 Ohm phase = -24.60°
524.26 Hz |Z| = 314.84 Ohm phase = -23.77°
416.43 Hz |Z| = 325.58 Ohm phase = -23.83°
330.78 Hz |Z| = 338.40 Ohm phase = -24.76°
262.75 Hz |Z| = 355.48 Ohm phase = -26.34°
208.71 Hz |Z| = 378.68 Ohm phase = -28.42°
165.78 Hz |Z| = 410.54 Ohm phase = -30.54°
131.69 Hz |Z| = 452.78 Ohm phase = -32.33°
104.60 Hz |Z| = 506.14 Ohm phase = -33.33°
83.09 Hz |Z| = 569.76 Ohm phase = -33.23°
66.00 Hz |Z| = 640.30 Ohm phase = -31.95°
52.43 Hz |Z| = 712.46 Ohm phase = -29.60°
41.64 Hz |Z| = 780.46 Ohm phase = -26.50°
33.08 Hz |Z| = 839.13 Ohm phase = -22.95°
26.28 Hz |Z| = 886.66 Ohm phase = -19.45°
20.87 Hz |Z| = 921.47 Ohm phase = -16.12°
16.58 Hz |Z| = 946.97 Ohm phase = -13.21°
13.17 Hz |Z| = 963.84 Ohm phase = -10.73°
10.00 Hz |Z| = 977.46 Ohm phase = -8.24°
Cleanup - Removing Event Handlers and Disconnecting
Before disconnecting, we remove all registered event handlers using clear_event_handler() and clear the connection status callback by passing None.
After disconnecting, you can no longer execute new jobs, but any data already collected (like the EIS result above) remains valid and can still be used.
for handler in handlers:
link.clear_event_handler(handler)
link.set_connection_status_callback(None)
link.disconnect()
print(f"[{elapsed()}] Disconnected")
[ 15.362s] Disconnected