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 ZahnerLinkConnectionStatusEnum

  • on_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 job

  • on_live_data_header_eis - same concept for EIS measurements, providing a LiveDataHeaderEis with impedance and path header information

  • on_live_data_rows - delivers one or more rows of DC live data as a list of lists of floats

  • on_live_data_row_eis - delivers a single EIS data point as a LiveDataRowEis containing impedance values

  • on_live_data_wave - delivers raw waveform data for EIS as a LiveDataWavesEis object

  • on_live_data_finished - signals that a job’s live data stream has ended

  • on_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:

  1. on_live_data_header - once at the start, describing the data columns

  2. on_live_data_rows - repeatedly during the measurement, delivering data rows

  3. on_live_data_finished - once when the measurement is done

  4. on_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:

  1. on_live_data_header_eis - once at the start, describing impedance headers, path headers, and potentiostat headers

  2. on_live_data_row_eis - for each measured frequency point, delivering impedance data

  3. on_live_data_wave - for each frequency point, delivering the raw waveform data

  4. on_live_data_finished - once when the EIS spectrum is complete

  5. on_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