Source code for zhinst.toolkit.driver.modules.impedance_module

"""Impedance Module."""

import logging
import typing as t
import time

from collections.abc import Sequence

from zhinst.core import ImpedanceModule as ZIImpedanceModule

from zhinst.toolkit.driver.modules.base_module import BaseModule

if t.TYPE_CHECKING:  # pragma: no cover
    from zhinst.toolkit.session import Session

logger = logging.getLogger(__name__)


[docs]class CalibrationStatus(int, Sequence): """Wrapper around a Impedance module status. LabOne reports a status for the impedance module as integers. The integer needs to be interpreted in a binary format where each bit represents a stage within the compensation. If the bit is set it means that the step is completed. This class wraps around this by both deriving from an integer and a Sequence. Therefore one can use it like a int but also access the individual steps through items (e.g. module.step[0]). Args: value: Integer value of the status. .. versionadded:: 0.5.1 """ def __new__(cls, value: int): """New method of the CalibrationStatus. Args: value: Integer value of the status. """ new_object = super(CalibrationStatus, cls).__new__(cls, value) new_object._value = value # type: ignore[attr-defined] new_object._binary = new_object._to_binary() # type: ignore[attr-defined] return new_object def __repr__(self): return ", ".join( [f"step {i}: {bool(value)}" for i, value in enumerate(self._binary)] ) def _to_binary(self): binary = [] num = self._value i = 0 while num != 0: bit = int(num % 2) binary.insert(i, bit) i = i + 1 num = int(num / 2) return binary def __getitem__(self, item): return self._binary[item] if len(self._binary) > item else 0 def __len__(self): return len(self._binary)
[docs]class ImpedanceModule(BaseModule): """Implements a base Impedance Module for Lock-In instruments. The Impedance Module corresponds to the Cal sub-tab in the LabOne User Interface Impedance Analyzer tab. It allows the user to perform a compensation that will be applied to impedance measurements. For a complete documentation see the LabOne user manual https://docs.zhinst.com/labone_programming_manual/impedance_module.html Args: impedance_module: Instance of the core Impedance Module. session: Session to the Data Server. .. versionadded:: 0.5.1 """ def __init__(self, impedance_module: ZIImpedanceModule, session: "Session"): super().__init__(impedance_module, session) self.root.update_nodes( { "/expectedstatus": {"GetParser": CalibrationStatus}, "/status": {"GetParser": CalibrationStatus}, }, raise_for_invalid_node=False, )
[docs] def wait_done( self, step: t.Optional[int] = None, *, timeout: float = 20.0, sleep_time: float = 0.5, ) -> None: """Waits until the specified compensation step is complete. Args: step: The compensation step to wait for completion. timeout: The maximum waiting time in seconds for the compensation to complete (default: 20). sleep_time: Time in seconds to wait between requesting the state. (default: 0.5) Raises: TimeoutError: The compensation is not completed before timeout. """ start_time = time.time() while ( start_time + timeout >= time.time() and self.calibrate() and not self.finished(step) ): logger.info(f"Progress: {(self.progress() * 100):.1f}%") time.sleep(sleep_time) if self.progress() < 1: raise TimeoutError("Impedance module timed out.") if not self.finished(step): if step is None: raise RuntimeError( "Impedance module did not reach the status " f"{CalibrationStatus(self.expectedstatus())} that " "corresponds to a full compensation. " f"(current status: {CalibrationStatus(self.status())})" ) raise RuntimeError( f"Impedance module did not finish the requested step {step}. " f"(current status: {CalibrationStatus(self.status())})" )
[docs] def finish(self) -> None: """Stop the module.""" self._raw_module.finish()
[docs] def finished(self, step: t.Optional[int] = None) -> bool: """Check if the calibration or a step of it is finished. Args: step: Calibration step. If not None this function checks if the specified step is finished. Otherwise it checks if the hole calibration is done. Returns: Flag if the calibration or a step is finished. """ if step is None: return self.status() == self.expectedstatus() return self.status() & (1 << step)