nibcq.EIS

class nibcq.EIS(device: nibcq._device.Device, test_parameters: EISTestParameters)

Bases: nibcq._acir.ACIR

Electrochemical Impedance Spectroscopy (EIS) measurement handler class.

This class extends the ACIR class to provide multi-frequency impedance spectroscopy capabilities. EIS measurements characterize the frequency-dependent impedance behavior of electrochemical systems by sweeping across a range of frequencies and measuring the complex impedance at each point.

EIS is a powerful technique for analyzing electrochemical processes, battery characterization, corrosion studies, and material property investigations. The class manages frequency sweeps, data collection across multiple frequencies, and provides methods for generating common EIS visualization formats like Nyquist and Bode plots.

The class inherits all ACIR functionality for single-frequency measurements and extends it with frequency sweep management, multi-point data storage, and EIS-specific analysis capabilities.

Example

>>> device = Device("PXIe-4139")
>>> eis = EIS(device)
>>>
>>> # Configure frequency sweep
>>> sweep_config = {
...     1000.0: FrequencySet(current_amplitude=0.1, number_of_periods=20),
...     100.0: FrequencySet(current_amplitude=0.1, number_of_periods=50)
... }
>>> params = EISTestParameters(frequency_sweep_characteristics=sweep_config)
>>>
>>> # Run EIS measurement
>>> results = eis.run(params, compensation)
>>> print(f"Measured {len(results)} frequency points")
Parameters:
property test_parameters: EISTestParameters

Get the current EIS test parameters.

Returns the EISTestParameters object containing all configuration settings for the EIS measurement including voltage limits, nominal voltage, compensation method, and frequency sweep characteristics.

Returns:

The current test parameters configuration

Return type:

EISTestParameters

Examples

>>> eis = EIS(device)
>>> params = eis.test_parameters
>>> print(params.voltage_limit_hi)
5.0
property current_frequency: float

Get the current measurement frequency.

Returns the frequency currently being used for measurements. This value changes during frequency sweeps as the EIS measurement progresses through different frequencies.

Returns:

The current frequency in Hz, or None if not set

Return type:

float

Examples

>>> eis.current_frequency = 1000.0
>>> print(eis.current_frequency)
1000.0
property frequency_list

Get the frequency sweep frequencies as a descending sorted list.

Returns all frequencies defined in the frequency sweep characteristics, sorted in descending order (highest to lowest frequency). This order is typically used in EIS measurements to start with high frequencies and sweep down to low frequencies.

Returns:

A list of frequencies in Hz, sorted in descending order

Return type:

list[float]

Raises:

ValueError – If frequency sweep characteristics are not set or empty

Examples

>>> eis.frequency_list
[1000.0, 500.0, 100.0, 50.0, 10.0]
property result: list[nibcq.measurement.SMUResult] | list[tuple[nibcq.switch.SMUCellData, list[nibcq.measurement.SMUResult]]]

Get the result of the last EIS measurement.

Returns the measurement result from the most recent measurement operation. The result type depends on whether switching was used or not.

Returns:

The measurement result(s).

For switching measurements, returns a list of tuples where each tuple contains the cell data and its corresponding results.

Return type:

list[SMUResult] | list[tuple[SMUCellData, list[SMUResult]]]

Raises:

RuntimeError – If no measurement has been performed yet or if the result is not available

get_plots() tuple[PlotSeries, PlotSeries, PlotSeries] | list[tuple[PlotSeries, PlotSeries, PlotSeries]]

Return plotting datasets for Nyquist and Bode plots.

For single device measurements, returns a 3-tuple:
  • (nyquist_x, nyquist_y): Nyquist (Cole) data where nyquist_x is R and nyquist_y is -X (both lists of floats) sorted by ascending frequency.

  • (freqs, magnitudes): Bode magnitude data (frequency ascending, abs(Z)).

  • (freqs, phases): Bode phase data (frequency ascending, theta in degrees).

For switching measurements, returns a list of 3-tuples, one for each cell.

The method reads measurement results and sorts the returned points by frequency (ascending) to make plotting predictable for common plotting conventions.

Raises:

RuntimeError – If no measurement results are available.

Return type:

tuple[PlotSeries, PlotSeries, PlotSeries] | list[tuple[PlotSeries, PlotSeries, PlotSeries]]

run(compensation: nibcq.compensation.Compensation, measurement_callback: Callable[[nibcq.measurement.SMUMeasurement], None] | None = None) list[nibcq.measurement.SMUResult]

Run the EIS process with the passed configuration parameters.

Validates temperature if the compensation specifies a target temperature, and the device supports temperature measurement. Then performs a full frequency sweep as defined in the test parameters, measuring impedance at each frequency point.

Parameters:
  • compensation (nibcq.compensation.Compensation) – The compensation object to use for impedance correction

  • measurement_callback (Optional[Callable[[nibcq.measurement.SMUMeasurement], None]]) –

    Optional callback function to call after each measurement cycle. One measurement cycle is a waveform generation and measurement done on a specific frequency.

    Pass your callback function here what you use to document the raw measurement data. It should have one input parameter, which is a SMUMeasurement object.

Returns:

A list of SMUResults, containing all of the results from the done measurements.

Raises:
  • ValueError – If configuration parameters are invalid or would cause measurement errors. Also raised if temperature validation fails.

  • RuntimeError – If device configuration or measurement fails.

  • AttributeError – If frequency sweep characteristics are missing or improperly formatted.

Return type:

list[nibcq.measurement.SMUResult]

Examples

>>> params = EISTestParameters()
>>> eis = EIS(device, params)
>>> compensation = eis.load_compensation_file()
>>> results = eis.run(compensation)
run_with_switching(compensation: nibcq.compensation.Compensation | list[nibcq.compensation.Compensation], measurement_callback: Callable[[nibcq.measurement.SMUMeasurement], None] | None = None)

Run complete EIS frequency sweeps across multiple DUTs using switch matrix configuration.

This method performs comprehensive Electrochemical Impedance Spectroscopy measurements on multiple devices under test (DUTs) by automatically switching between different channels. For each connected DUT, it executes a complete frequency sweep as defined in the test parameters, collecting impedance data across the entire frequency range.

The switching process ensures proper isolation between measurements, with automatic debounce timing for stable connections and complete disconnection between DUTs. This enables efficient multi-battery characterization, comparative electrochemical analysis, or production testing scenarios where multiple samples need identical frequency sweep measurements.

Returns partial, already processed measurements, even if an error occurs during switching or measurement.

Each DUT receives the same complete EIS treatment: frequency sweep from high to low frequencies, compensation application, and result collection. The method maintains measurement consistency across all DUTs while leveraging hardware switching for efficiency.

Parameters:
  • compensation (Compensation | list[Compensation]) – The compensation object containing frequency-dependent error correction data for impedance accuracy improvement across all measurement frequencies in the sweep. This can be passed as a list of compensations, a different one for each cell.

  • measurement_callback (Optional[Callable[[SMUMeasurement], None]]) – Optional callback function invoked after each individual frequency measurement within each DUT’s sweep. Receives the raw SMUMeasurement data for real-time monitoring, logging, or progress tracking. Called once per frequency per DUT.

Returns:

A list of tuples mapping each cell to its

complete EIS measurement results. Each SMUCellData represents a DUT connection point, and the corresponding list[SMUResult] contains impedance measurements for all frequencies in the sweep, enabling complete frequency-domain analysis for each individual DUT.

Return type:

list[tuple[SMUCellData, list[SMUResult]]]

Raises:
  • RuntimeError – If switching capability is not enabled (call device.with_switching() first) or if no switch channels are configured in the switch matrix.

  • ValueError – If configuration parameters are invalid, would cause measurement errors across the frequency range, or if compensation list length doesn’t match the number of DUTs. Also raised if temperature validation fails for any cell.

  • AttributeError – If frequency sweep characteristics are missing or improperly formatted in the test parameters.

  • Exception – If connection to any DUT fails during switching operations or if any frequency measurement fails during the sweep.

Examples

>>> params = EISTestParameters()
>>> eis = EIS(device, params)
>>> compensation = eis.load_compensation_file()
>>> results = eis.run_with_switching(compensation)

Note

This method performs a complete frequency sweep for each DUT, which can be time-intensive for large frequency ranges or many DUTs. The measurement callback can be used to monitor progress and provide feedback during long measurement sequences. Switch timing includes automatic debounce delays for measurement stability, and proper disconnection is guaranteed even if exceptions occur.

write_compensation_file(compensation_file_path: str | None = None, kit_file_path: str | None = None, comment: str | None = None, measurement_callback: Callable[[nibcq.measurement.SMUMeasurement], None] | None = None) str

Create a compensation file based on measurements at all frequencies in the sweep.

Parameters:
  • compensation_file_path (Optional[str]) – Optional specific file path to write to. If None, generates path automatically.

  • kit_file_path (Optional[str]) – Optional specific file path to the known impedance table. If None, no known impedance table is used.

  • comment (Optional[str]) – Optional comment to include in the compensation file. If None, no comment is included.

  • measurement_callback (Optional[Callable[[nibcq.measurement.SMUMeasurement], None]])

Returns:

The path of the created compensation file.

Return type:

str

Raises:
  • ValueError – If parameters are invalid or compensation method does not support compensation files.

  • FileNotFoundError – If compensation file is required but not found.

  • RuntimeError – If device configuration or measurement fails.

  • NotImplementedError – If unsupported compensation method is specified.

DEVICE_FAMILY: Final[nibcq.enums.DeviceFamily]

Device family for ACIR and similar measurement types.

Type:

DeviceFamily

FREQUENCY_LIMIT: Final[float] = 10000.0

Frequency limit for ACIR and similar measurement types.

Type:

float

CURRENT_LIMIT: Final[float] = 2.0

Current limit for ACIR and similar measurement types.

Type:

float

generate_compensation_file_path() str

Generate compensation file path using current compensation method setting.

Returns:

The generated file path for compensation data, or None if no compensation

is needed

Return type:

str

Raises:
property measurement_data: nibcq.measurement.SMUMeasurement

Get the processed measurement data used for impedance calculations.

Only allows measurement to be read, not access it directly. For frequencies > 60 Hz, sanitizes data by removing edge effects. Applies DC offset removal to ensure measurements start and end near zero.

Returns:

Sanitized measurement data containing tone frequency, voltage

values, and current values

Return type:

SMUMeasurement

Raises:

ValueError – If no measurement data is available or measurement is incomplete

property raw_data: nibcq.measurement.SMUMeasurement

Get the raw measurement data read from the device.

Only allows measurement to be read, not access it directly. Returns unprocessed data as captured from the device.

Returns:

Raw measurement data containing tone frequency, voltage values,

and current values

Return type:

SMUMeasurement

Raises:

ValueError – If no measurement data is available or measurement is incomplete

static validate_current_amplitude(current_amplitude: float) bool

Validate that the current amplitude is within acceptable limits.

Parameters:

current_amplitude (float)

Return type:

bool

load_compensation_file(file_path: str | None = None) nibcq.compensation.Compensation

Load compensation file based on compensation method and device serial number.

Creates and returns a compensation object with the appropriate compensation data. For NO_COMPENSATION, creates a default compensation object. For other methods, loads compensation data from file.

Parameters:

file_path (Optional[str]) – Optional specific file path to read from. If None, generates path automatically

Returns:

The loaded compensation object

Return type:

Compensation

Raises:
  • FileNotFoundError – If compensation file is not found and compensation is required

  • ValueError – If compensation file is invalid and compensation is required

  • NotImplementedError – If compensation method is not supported by the nibcq Python API

property has_switch_capability: bool

Check if the device has switch capability.

Returns:

True if switch capability is available, False otherwise

Return type:

bool

connect_channel(channel: SMUCellData) None

Connect to a specific DUT channel using the device’s switch capability.

Parameters:

channel (SMUCellData) – SwitchChannel containing connection information

Raises:

RuntimeError – If no switch capability is available

Return type:

None

disconnect_all() None

Disconnect all channels using the device’s switch capability.

Raises:

RuntimeError – If no switch capability is available

Return type:

None

wait_for_debounce() None

Wait for switch relays to settle using the device’s switch capability.

Raises:

RuntimeError – If no switch capability is available

Return type:

None

property switch_cells: List[str] | List[SMUCellData]

Get the configured switch cells from the device.

Returns:

A list of DUT channel names or SMUCellData objects, which contain the DUT and switch channel information.

Return type:

List[str] | List[SMUCellData]

property acceptable_temperature_delta: float

Get the acceptable temperature delta for compensation validation.

Returns the maximum allowed temperature difference from the device’s temperature capability. This is a pass-through property that delegates to the underlying TemperatureCapability.

Returns:

The acceptable temperature delta in degrees, or NaN if no temperature capability

Return type:

float

Examples

>>> measurement = EIS(device)
>>> measurement.acceptable_temperature_delta = 2.5
>>> delta = measurement.acceptable_temperature_delta
property temperature: float

Get the latest temperature reading from the device.

Returns:

The most recent temperature measurement, or NaN if no temperature capability

Return type:

float

property temperature_range: CenteredRange

Get the latest temperature reading from the device, coupled with the user-set delta.

Returns:

A CenteredRange representing the most recent temperature measurement (NaN if not available), along with the acceptable temperature delta (NaN if not set).

Return type:

CenteredRange

measure_temperature() CenteredRange

Get a new temperature reading from the device.

Returns:

Current temperature reading, or NaN if no temperature capability

Return type:

CenteredRange

validate_temperature(target_temperature: CenteredRange) bool

Validate the current temperature against the compensation file’s target.

Delegates to the device’s temperature capability for validation. The capability handles all validation logic including checking if thermocouple is configured, using overridden delta values if set, and printing appropriate warnings.

Parameters:

target_temperature (CenteredRange) – The target temperature parameters for validation

Returns:

True if thermocouple is configured and temperature is within range.

False if thermocouple is not configured (capability missing or not set up), or if target temperature/delta is NaN.

Return type:

bool

Raises:

ValueError – If the current temperature exceeds the target ± delta range (only raised when capability is configured)

Examples

>>> measurement = EIS(device)
>>> measurement.measure_temperature()
>>> target = compensation.temperature_parameter
>>> is_valid = measurement.validate_temperature(target)