Changelog

1.5.0

  • Added:

    • New LCREIS class and LCREISTestParameters, enabling multi-frequency EIS measurement and compensation using an NI PXIe-4190 LCR Meter. This includes new API calls and a new example:

      • lcr_eis_simple.py — a basic EIS measurement with an LCR meter (uses LCREISConfigFile.json).

    • New compensation-focused examples for switching workflows:

      • acir_create_compensation_with_switching.py — create an ACIR compensation file while switching across channels.

      • acir_with_switching_and_compensation_list.py — run ACIR across channels using a per-channel compensation list.

      • eis_create_compensation_with_switching.py — create an EIS compensation file while switching across channels.

      • eis_with_switching_and_compensation_list.py — run EIS across channels using a per-channel compensation list.

  • Fixed:

    • The SMU / electronic load output relays are now reliably disconnected at the end of every ACIR, EIS, and DCIR test (and their parallel variants) for a proper workflow and power safety.

    • ACIR / EIS single-sided spectrum amplitude correction: the reported voltage and current phasor magnitudes now apply the factor-of-two single-sided FFT correction. Impedance results are unaffected, since the factor cancels in the voltage-to-current ratio.

    • Removed an obsolete DCIR current-level range workaround.

    • LCRACIR now inherits from the shared Measurement base class for consistent behavior with the other measurement types.

  • Changed:

    • Internally refactored Parallel Measurement classes. Users should not notice any major difference while interacting with the API.

    • Call Path Deprecation Related to the internal refactor, the EIS and ParallelEIS callback path got flagged as deprecated:

      • measurement_callback is now a constructor parameter and a settable property on EIS and ParallelEIS, instead of being passed to run() and run_with_switching().

      • To signal this, the old call path is still part of the API, but using it causes a DeprecationWarning. To mitigate this, use the new call path.

      • Migration guide: Pass measurement_callback at construction time or via the property before calling run() or run_with_switching(). Both EIS and ParallelEIS are affected.

        # Before (deprecated - raises DeprecationWarning):
        eis.run(compensation, measurement_callback=my_callback)
        eis.run_with_switching(compensation, measurement_callback=my_callback)
        
        # After - option 1: pass at construction time:
        eis = EIS(device, params, measurement_callback=my_callback)
        eis.run(compensation)
        
        # After - option 2: set the property before running:
        eis = EIS(device, params)
        eis.measurement_callback = my_callback
        eis.run(compensation)
        
    • Further consolidated shared ParallelMeasurement internals used by ParallelACIR and ParallelDCIR to reduce duplication while preserving behavior.

    • Breaking change: All public measurement result collections now return immutable tuple instead of mutable list.

      • EIS.run() now returns tuple[SMUResult, ...] (was list[SMUResult])

      • EIS.run_with_switching() now returns tuple[tuple[SMUCellData, tuple[SMUResult, ...]], ...] (was list[tuple[SMUCellData, list[SMUResult]]])

      • EIS.get_plots() switching branch now returns tuple[tuple[PlotSeries, PlotSeries, PlotSeries], ...] (was list[...])

      • ACIR.run_with_switching() now returns tuple[tuple[SMUCellData, SMUResult], ...] (was list[tuple[SMUCellData, SMUResult]])

      • OCV.run_with_switching() now returns tuple[tuple[str, tuple[datetime, datetime, float]], ...] (was list[...])

      • ParallelEIS.run() now returns tuple[SMUResult, ...] (was list[SMUResult])

      • SMUMeasurement.voltage_values is now tuple[float, ...] (was list[float])

      • SMUMeasurement.current_values is now tuple[float, ...] (was list[float])

      • Migration guide: Most user code continues to work without changes. Iteration (for r in results), indexing (results[0]), slicing (results[:3]), length checks len(), and unpacking all work identically on tuples. Only code that incorrectly mutates the returned collection needs updating:

        # Before (no longer works):
        results = eis.run(compensation)
        results.append(extra)   # raises AttributeError
        results[0] = modified   # raises TypeError
        
        # After - copy to a list if mutation is required:
        results = list(eis.run(compensation))
        results.append(extra)   # works
        

1.4.0

  • Fixed:

    • Calibrator now actually supports DeviceFamily.ELoad. It was missing this in previous release.

  • Added:

    • New ParallelMeasurement base abstract class for parallel measurements.

    • New ParallelDCIR class, helping you create DCIR Parallel Measurements (based on the ParallelMeasurement abstract class). This includes new API calls and a new example:

      • dcir_parallel_simple.py — a basic parallel DCIR measurement.

    • New ParallelACIR class, helping you create ACIR Parallel Measurements (based on the ParallelMeasurement abstract class). This includes new API calls and a new examples:

      • acir_parallel_simple.py — a basic parallel ACIR measurement.

      • acir_parallel_create_compensation_file.py — basic parallel ACIR compensation with thermocouple.

      • acir_parallel_create_compensation_with_kit.py — parallel ACIR SHORT compensation using a KIT file.

    • New ParallelEIS class, helping you create EIS Parallel Measurements (based on the ParallelACIR and EIS classes). This includes new API calls and a new examples:

      • eis_parallel_simple.py — a basic parallel EIS measurement.

      • eis_parallel_create_compensation_file.py — basic parallel EIS compensation with thermocouple.

      • eis_parallel_create_compensation_with_kit.py — parallel EIS SHORT compensation using a KIT file.

    • New Simulated ELoad Example.

    • Checks for DeviceFamily.ELoad in Simulated Device examples.

    • New LCRACIR class and LCRTestParameters, enabling single-frequency ACIR measurement and compensation using an NI PXIe-4190 LCR Meter. This includes new API calls and new examples:

      • lcr_acir_simple.py — a basic ACIR measurement with an LCR meter.

      • lcr_create_compensation.py — create an LCR meter compensation for ACIR.

  • Changed:

    • SwitchAware behaviour is moved from Measurement to a separate SwitchingSupport mixin class.

    • Now only specific measurements using SwitchingSupport have run_with_switching function and complete SwitchAware behaviour.

    • Added type hints to all public API docstrings for improved API Reference documentation.

1.3.0

  • Fixed:

    • Replaced print() warning messages in temperature module with proper Python logging to stderr (issue #56).

  • Added:

    • Custom exception classes for unified error handling in errors.py:

      • BCQError (base class) and specific subclasses for common error scenarios (e.g., EmptySerialNumberError, HardwareIncompatibilityError, etc.):

        • Most of these come from the LabVIEW API.

        • Two are Python specific (DMMParameterError and TemperatureError).

      • These exceptions are now used throughout the codebase for clearer and more maintainable error handling.

  • Changed:

    • Testing is now done with the new Error Handling Framework.

1.2.1

  • Added:

    • TemperatureAware.validate_temperature(target_temperature) - Measures and Validates temperature for measurement classes (ACIR, EIS, etc.).

    • Historical changelog to documentation.

    • New Warnings to temperature validation logic, when delta was overwritten and when target is set but no measurement is available.

    • Two new examples showing error handling with both temperature and switching support is present.

    • New temperature property for TemperatureAware class, containing only the measured temperature value, without the delta limits.

  • Changed:

    • Temperature submodule:

      • Made TemperatureCapability.run_task() public.

      • Made TemperatureCapability.validate_latest_temperature() public.

      • Warning messages now prefixed with [nibcq] for clarity.

      • Renamed TemperatureParameter to a more generic CenteredRange name. The new field names are center and delta.

    • Measurement classes:

      • Now ACIR and EIS run() includes temperature validation when it is necessary and supported.

    • Examples:

      • Examples demonstrating temperature validation workflow in acir_with_temperature.py and eis_with_temperature.py.

      • Error handling in examples with temperature measurement.

    • Updated documentation, including new examples.

    • Renamed temperature_measurement property to temperature_range.

  • Fixed:

    • Temperature validation now correctly uses overridden acceptable_temperature_delta when user sets custom value.

    • Setting temperature delta now actually possible during device creation.

    • Compensation file creation examples set temperature delta correctly.

    • Added None check for target_temperature parameter in validation methods, solving an issue when using No Compensation compensation method.

    • Some typos.

1.2.0

  • Added:

    • Basic functionality for OCV, ACIR, DCIR and EIS measurements.

    • Switching support for multi-channel measurements.

    • Temperature measurement support with thermocouple integration.