From 068e5081851d117bcc87bb928aff549e37ad2f5f Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 16:18:00 +0200 Subject: [PATCH 1/9] api update added wupport for *GET? queries; fixed numerous pylance type errors. --- .../Sentio/CommandGroups/AuxCommandGroup.py | 60 +--- .../CommandGroups/CompensationCommandGroup.py | 4 +- .../Sentio/CommandGroups/ProbeCommandGroup.py | 5 +- .../CommandGroups/QAlibriaCommandGroup.py | 6 +- .../CommandGroups/ServiceCommandGroup.py | 4 +- .../Sentio/CommandGroups/SetupCommandGroup.py | 9 +- .../SetupContactCounterCommandGroup.py | 5 +- .../CommandGroups/SetupRemoteCommandGroup.py | 5 +- .../Sentio/CommandGroups/SiPHCommandGroup.py | 5 +- .../CommandGroups/StatusCommandGroup.py | 7 +- .../CommandGroups/VisionCameraCommandGroup.py | 5 +- .../CommandGroups/VisionCommandGroup.py | 13 +- .../CommandGroups/VisionCompensationGroup.py | 5 +- .../VisionIMagProCommandGroup.py | 4 +- .../VisionPatternCommandGroup.py | 3 +- .../CommandGroups/WafermapCommandGroup.py | 23 +- sentio_prober_control/Sentio/Enumerations.py | 321 ++++++++++++++---- sentio_prober_control/Sentio/ProberSentio.py | 75 ++-- 18 files changed, 369 insertions(+), 190 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py index 1f6c512..ab47852 100644 --- a/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py @@ -2,7 +2,7 @@ from typing import Optional, Tuple, List from dataclasses import dataclass -from sentio_prober_control.Sentio.Enumerations import ChuckSite +from sentio_prober_control.Sentio.Enumerations import ChuckSite, ElementType from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.ProberBase import ProberException from sentio_prober_control.Sentio.CommandGroups.AuxCleaningGroup import AuxCleaningGroup @@ -22,9 +22,10 @@ def __init__(self, raw_response: str) -> None: parts = raw_response.split(",") if len(parts) < 7: raise ProberException("Unexpected response for element info.") + # Parse the parts into an ElementInfo object. self.element_info = ElementInfo( - element_type=ElementType.from_str(parts[0]), + element_type=ElementType.from_string(parts[0]), element_subtype=parts[1], x_position=float(parts[2]), y_position=float(parts[3]), @@ -40,28 +41,8 @@ def get_element_info(self) -> "ElementInfo": """ return self.element_info -# --- New Enumerator for element types --- -class ElementType(Enum): - """Represents the type of a calibration element.""" - Open = 0 - Short = 1 - Thru = 2 - Load = 3 - Align = 4 - Unknown = 99 - - @classmethod - def from_str(cls, s: str) -> "ElementType": - mapping = { - "open": cls.Open, - "short": cls.Short, - "thru": cls.Thru, - "load" : cls.Load, - "align": cls.Align - } - return mapping.get(s.lower(), cls.Unknown) - -# --- New data class for element information --- + + @dataclass class ElementInfo: element_type: ElementType @@ -72,7 +53,7 @@ class ElementInfo: touch_count: int life_time: float -# --- Updated AuxCommandGroup with eleven API methods --- + class AuxCommandGroup(ModuleCommandGroupBase): """This command group contains functions for working with auxiliary sites of the chuck. You are not meant to create instances of this class on your own. Instead, use the aux @@ -82,9 +63,9 @@ class AuxCommandGroup(ModuleCommandGroupBase): cleaning (AuxCleaningGroup): A subgroup to provide logic for probe cleaning. """ - def __init__(self, comm) -> None: - super().__init__(comm, "aux") - self.cleaning: AuxCleaningGroup = AuxCleaningGroup(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober, "aux") + self.cleaning: AuxCleaningGroup = AuxCleaningGroup(prober) # --- Helper method to validate that the given site is an auxiliary site --- def _validate_aux_site(self, site: "ChuckSite") -> None: @@ -93,9 +74,6 @@ def _validate_aux_site(self, site: "ChuckSite") -> None: if site in (ChuckSite.Wafer, ChuckSite.ChuckCamera): raise ProberException(f"Invalid auxiliary site: {site.name}.") - # ------------------------------------------------------------------------- - # 1) retrieve_substrate_data - # ------------------------------------------------------------------------- def retrieve_substrate_data(self, site: Optional["ChuckSite"] = None) -> List["ChuckSite"]: """ Retrieves contact and home information from the configuration file and assigns it @@ -134,9 +112,6 @@ def retrieve_substrate_data(self, site: Optional["ChuckSite"] = None) -> List["C break return sites - # ------------------------------------------------------------------------- - # 2) get_substrate_type - # ------------------------------------------------------------------------- def get_substrate_type(self, site: Optional["ChuckSite"] = None) -> str: """ Retrieves the type of a calibration substrate placed on the chuck. @@ -164,9 +139,6 @@ def get_substrate_type(self, site: Optional["ChuckSite"] = None) -> str: return "" return substrate_type - # ------------------------------------------------------------------------- - # 3) step_to_element - # ------------------------------------------------------------------------- def step_to_element( self, element_standard_id: str, @@ -193,9 +165,6 @@ def step_to_element( self.comm.send(cmd) Response.check_resp(self.comm.read_line()) - # ------------------------------------------------------------------------- - # 4) step_to_dut_element - # ------------------------------------------------------------------------- def step_to_dut_element( self, dut_name: str, @@ -221,9 +190,6 @@ def step_to_dut_element( self.comm.send(cmd) Response.check_resp(self.comm.read_line()) - # ------------------------------------------------------------------------- - # 5) get_element_type - # ------------------------------------------------------------------------- def get_element_type(self, element_standard_id: str, site: Optional["ChuckSite"] = None) -> ElementType: """ Retrieves the type of an element on a calibration substrate placed on the chuck. @@ -248,11 +214,8 @@ def get_element_type(self, element_standard_id: str, site: Optional["ChuckSite"] self.comm.send(cmd) resp = Response.check_resp(self.comm.read_line()) result = resp.message() - return ElementType.from_str(result) + return ElementType.from_string(result) - # ------------------------------------------------------------------------- - # 6) get_substrate_info - # ------------------------------------------------------------------------- def get_substrate_info(self, site: "ChuckSite") -> Tuple[str, str, float]: """ Retrieves information of a calibration substrate or cleaning pad placed on a chuck site. @@ -282,9 +245,6 @@ def get_substrate_info(self, site: "ChuckSite") -> Tuple[str, str, float]: life_time = float(parts[2]) return (substrate_type, substrate_id, life_time) - # ------------------------------------------------------------------------- - # 7) get_element_touch_count - # ------------------------------------------------------------------------- def get_element_touch_count(self, element_standard_id: str, site: Optional["ChuckSite"] = None) -> int: """ Retrieves the touch count of an element on a calibration substrate placed on the chuck. diff --git a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py index f630436..1d4fc80 100644 --- a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py @@ -13,9 +13,9 @@ class CompensationCommandGroup(CommandGroupBase): Use the SentioProber.vis.compensation group instead! """ - def __init__(self, comm) -> None: + def __init__(self, prober : 'SentioProber') -> None: """@private""" - super().__init__(comm) + super().__init__(prober) @deprecated(reason="Use prober.vis.compensation.set_compensation instead.") diff --git a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py index a0c5d3c..6d6ac90 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py @@ -1,6 +1,5 @@ from typing import Tuple -from sentio_prober_control.Communication.CommunicatorBase import CommunicatorBase from sentio_prober_control.Sentio.Enumerations import ProbeSentio, ProbeXYReference, ProbeZReference, ChuckSite from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -21,8 +20,8 @@ class ProbeCommandGroup(CommandGroupBase): ``` """ - def __init__(self, comm: CommunicatorBase) -> None: - super().__init__(comm) + def __init__(self, prober: 'SentioProber') -> None: + super().__init__(prober) def async_step_probe_site(self, probe: ProbeSentio, idx: int) -> int: diff --git a/sentio_prober_control/Sentio/CommandGroups/QAlibriaCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/QAlibriaCommandGroup.py index df9b808..3330f34 100644 --- a/sentio_prober_control/Sentio/CommandGroups/QAlibriaCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/QAlibriaCommandGroup.py @@ -1,7 +1,7 @@ from deprecated import deprecated + from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase -from sentio_prober_control.Sentio.ProberBase import ProberException from sentio_prober_control.Sentio.Enumerations import DriftType from typing import List @@ -10,8 +10,8 @@ class QAlibriaCommandGroup(CommandGroupBase): This command group contains functions for working with QAlibria. """ - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def calibration_execute(self) -> None: diff --git a/sentio_prober_control/Sentio/CommandGroups/ServiceCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ServiceCommandGroup.py index 9f9c781..6f87bed 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ServiceCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ServiceCommandGroup.py @@ -6,8 +6,8 @@ class ServiceCommandGroup(ModuleCommandGroupBase): """A command group for accessing service module functions.""" - def __init__(self, comm) -> None: - super().__init__(comm, "service") + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober, "service") def set_compensation_mode(self, status: bool) -> None: diff --git a/sentio_prober_control/Sentio/CommandGroups/SetupCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/SetupCommandGroup.py index a9c71a3..1a23cb7 100644 --- a/sentio_prober_control/Sentio/CommandGroups/SetupCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/SetupCommandGroup.py @@ -1,3 +1,4 @@ + from sentio_prober_control.Sentio.CommandGroups.SetupContactCounterCommandGroup import SetupContactCounterCommandGroup from sentio_prober_control.Sentio.CommandGroups.SetupRemoteCommandGroup import SetupRemoteCommandGroup from sentio_prober_control.Sentio.CommandGroups.ModuleCommandGroupBase import ModuleCommandGroupBase @@ -5,8 +6,8 @@ class SetupCommandGroup(ModuleCommandGroupBase): """A command group for accessing setup module functions.""" - def __init__(self, comm) -> None: - super().__init__(comm, "setup") + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober, "setup") - self.contact_counter: SetupContactCounterCommandGroup = SetupContactCounterCommandGroup(comm) - self.remote: SetupRemoteCommandGroup = SetupRemoteCommandGroup(comm) \ No newline at end of file + self.contact_counter: SetupContactCounterCommandGroup = SetupContactCounterCommandGroup(prober) + self.remote: SetupRemoteCommandGroup = SetupRemoteCommandGroup(prober) \ No newline at end of file diff --git a/sentio_prober_control/Sentio/CommandGroups/SetupContactCounterCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/SetupContactCounterCommandGroup.py index 7c0c4ea..ffda256 100644 --- a/sentio_prober_control/Sentio/CommandGroups/SetupContactCounterCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/SetupContactCounterCommandGroup.py @@ -1,3 +1,4 @@ + from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -5,8 +6,8 @@ class SetupContactCounterCommandGroup(CommandGroupBase): """This command group bundles functions setting up the contact counter.""" - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def get(self) -> int: """ Retrieves the contact counter value. diff --git a/sentio_prober_control/Sentio/CommandGroups/SetupRemoteCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/SetupRemoteCommandGroup.py index 791860a..71dc5a2 100644 --- a/sentio_prober_control/Sentio/CommandGroups/SetupRemoteCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/SetupRemoteCommandGroup.py @@ -1,10 +1,11 @@ + from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase class SetupRemoteCommandGroup(CommandGroupBase): """ This command group bundles functions setting up the behavior of SENTIO in remote mode. """ - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def light_off_at_contact(self, status: bool) -> None: """Defines whether light is switched off at contact height in remote mode. diff --git a/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py index 8949c02..801863a 100644 --- a/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py @@ -1,5 +1,6 @@ from typing import Tuple + from sentio_prober_control.Sentio.Enumerations import ProbeSentio, UvwAxis, FiberType from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -11,8 +12,8 @@ class SiPHCommandGroup(CommandGroupBase): of the [SentioProber](SentioProber.md) class. """ - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def fast_alignment(self) -> None: diff --git a/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py index c0f1ab5..80a4ead 100644 --- a/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py @@ -4,6 +4,7 @@ ThermoChuckState, DialogButtons ) + from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.ModuleCommandGroupBase import ( ModuleCommandGroupBase, @@ -12,8 +13,8 @@ class StatusCommandGroup(ModuleCommandGroupBase): """A command group for getting the status of the probe station and controlling the dashboard module.""" - def __init__(self, comm) -> None: - super().__init__(comm, "status") + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober, "status") def get_access_level(self) -> AccessLevel: """Retrieves the access level of operation. @@ -85,7 +86,7 @@ def get_chuck_thermo_state(self) -> ThermoChuckState: """ self.comm.send("status:get_chuck_thermo_state") - state : ThermoChuckState = ThermoChuckState.fromSentioAbbr(Response.check_resp(self.comm.read_line()).message()) + state : ThermoChuckState = ThermoChuckState.from_string(Response.check_resp(self.comm.read_line()).message()) return state def get_high_purge_state(self) -> str: diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py index 6bef6cb..5bd4fb9 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py @@ -1,5 +1,6 @@ from typing import Tuple + from sentio_prober_control.Sentio.Enumerations import AutoFocusAlgorithm, CameraMountPoint, DefaultPattern from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -12,8 +13,8 @@ class VisionCameraCommandGroup(CommandGroupBase): of the vision attribute of the [SentioProber](SentioProber.md) class. """ - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def set_light(self, mp: CameraMountPoint, value: int) -> None: """Set intensity of the light. diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py index b2ef23a..0e11987 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py @@ -17,6 +17,7 @@ PtpaType, SnapshotLocation, SnapshotType, MoveAxis,) + from sentio_prober_control.Sentio.ProberBase import ProberException from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.ModuleCommandGroupBase import ModuleCommandGroupBase @@ -37,13 +38,13 @@ class VisionCommandGroup(ModuleCommandGroupBase): compensation (VisionCompensationGroup): A subgroup to provide logic for compensation specific functions. """ - def __init__(self, comm: CommunicatorBase) -> None: - super().__init__(comm, "vis") + def __init__(self, prober: 'SentioProber') -> None: + super().__init__(prober, "vis") - self.camera = VisionCameraCommandGroup(comm) - self.imagpro = VisionIMagProCommandGroup(comm) - self.compensation = VisionCompensationGroup(comm) - self.pattern = VisionPatternCommandGroup(comm) + self.camera = VisionCameraCommandGroup(prober) + self.imagpro = VisionIMagProCommandGroup(prober) + self.compensation = VisionCompensationGroup(prober) + self.pattern = VisionPatternCommandGroup(prober) def align_wafer(self, mode: AutoAlignCmd = AutoAlignCmd.AlignOnly) -> None: """Perform a wafer alignment. diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py index 1c791ab..96ebbd9 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py @@ -1,5 +1,6 @@ from typing import Tuple + from sentio_prober_control.Sentio.Enumerations import CompensationMode, CompensationType from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -14,8 +15,8 @@ class VisionCompensationGroup(CommandGroupBase): of the vision attribute of the [SentioProber](SentioProber.md) class. """ - def __init__(self, comm): - super().__init__(comm) + def __init__(self, prober : 'SentioProber'): + super().__init__(prober) @deprecated("Use vision.compensation.enable() instead") def set_compensation(self, comp: CompensationMode, enable: bool) -> Tuple[str, str]: diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py index 3ae9491..bbd4541 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py @@ -12,8 +12,8 @@ class VisionIMagProCommandGroup(CommandGroupBase): of the vision attribute of the [SentioProber](SentioProber.md) class. """ - def __init__(self, comm) -> None: - super().__init__(comm) + def __init__(self, prober : 'SentioProber') -> None: + super().__init__(prober) def move_z(self, ref: IMagProZReference, pos: float) -> float: diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py index eaef054..d52dec1 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py @@ -1,7 +1,6 @@ from typing import Tuple -from sentio_prober_control.Sentio.Enumerations import BinSelection, BinQuality, FindPatternReference, CameraMountPoint, \ - DefaultPattern +from sentio_prober_control.Sentio.Enumerations import ( FindPatternReference, CameraMountPoint, DefaultPattern ) from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py index 805d123..218b9fc 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py @@ -1,7 +1,8 @@ from typing import Tuple -from deprecated import deprecated + from sentio_prober_control.Sentio.Enumerations import AxisOrient, ColorScheme, DieNumber, StatusBits, RoutingStartPoint, \ RoutingPriority, OrientationMarker + from sentio_prober_control.Sentio.ProberBase import ProberException from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.ModuleCommandGroupBase import ModuleCommandGroupBase @@ -37,18 +38,18 @@ class WafermapCommandGroup(ModuleCommandGroupBase): subsites (WafermapSubsiteGroup): A group to set up subsites. """ - def __init__(self, comm) -> None: - super().__init__(comm, "map") + def __init__(self, sentio : 'SentioProber') -> None: + super().__init__(sentio, "map") self.__end_of_route: bool = False - self.bins: WafermapBinsCommandGroup = WafermapBinsCommandGroup(comm) - self.compensation: WafermapCompensationCommandGroup = WafermapCompensationCommandGroup(comm) - self.die: WafermapDieCommandGroup = WafermapDieCommandGroup(comm) - self.path: WafermapPathCommandGroup = WafermapPathCommandGroup(comm) - self.poi: WafermapPoiCommandGroup = WafermapPoiCommandGroup(comm) - self.subsites: WafermapSubsiteGroup = WafermapSubsiteGroup(comm, self) - self.view: WafermapViewCommandGroup = WafermapViewCommandGroup(comm) + self.bins: WafermapBinsCommandGroup = WafermapBinsCommandGroup(sentio) + self.compensation: WafermapCompensationCommandGroup = WafermapCompensationCommandGroup(sentio) + self.die: WafermapDieCommandGroup = WafermapDieCommandGroup(sentio) + self.path: WafermapPathCommandGroup = WafermapPathCommandGroup(sentio) + self.poi: WafermapPoiCommandGroup = WafermapPoiCommandGroup(sentio) + self.subsites: WafermapSubsiteGroup = WafermapSubsiteGroup(sentio, self) + self.view: WafermapViewCommandGroup = WafermapViewCommandGroup(sentio) def bin_step_next_die(self, bin_value: int, site: int | None = None) -> Tuple[int, int, int]: """Bin the current die and step to the naxt die. @@ -601,7 +602,7 @@ def get_routing(self) -> Tuple[RoutingStartPoint, RoutingPriority]: self.comm.send("map:get_routing") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") - return RoutingStartPoint.fromSentioAbbr(tok[0]), RoutingPriority.fromSentioAbbr(tok[1]) + return RoutingStartPoint.from_string(tok[0]), RoutingPriority.from_string(tok[1]) def open(self, file_path: str) -> None: """Open a wafer map file.""" diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 9aba8ac..80c170e 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -232,6 +232,20 @@ class ChuckPositionHint(Enum): SideLoad = 2 OffAxisCamera = 3 + @staticmethod + def from_string(abbr: str): + mapping = { + "Probing": ChuckPositionHint.Center, + "FrontLoad": ChuckPositionHint.FrontLoad, + "SideLoad": ChuckPositionHint.SideLoad, + "OffAxisCamera": ChuckPositionHint.OffAxisCamera + } + try: + return mapping[abbr] + except KeyError: + raise ValueError(f"Unknown ChuckPositionHint abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str): mapping = { @@ -275,18 +289,36 @@ class ChuckSite(Enum): def toSentioAbbr(self): switcher = { ChuckSite.Wafer: "Wafer", - ChuckSite.AuxLeft: "AuxLeft", - ChuckSite.AuxLeft2: "AuxLeft2", ChuckSite.AuxRight: "AuxRight", + ChuckSite.AuxLeft: "AuxLeft", ChuckSite.AuxRight2: "AuxRight2", + ChuckSite.AuxLeft2: "AuxLeft2", ChuckSite.ChuckCamera: "ChuckCamera", ChuckSite.SiPhSetHoverHeight: "SiPhSetHoverHeight", - ChuckSite.SiPhFiberPowerMeasure: "SiPhFiberPowerMeasure", + ChuckSite.SiPhFiberPowerMeasure: "SiPhFiberPowerMeasure" } return switcher.get(self, "Invalid chuck site") @staticmethod - def fromSentioAbbr(abbr: str) -> "ChuckSite": + def from_string(abbr: str): + mapping = { + "Wafer": ChuckSite.Wafer, + "AuxRight": ChuckSite.AuxRight, + "AuxLeft": ChuckSite.AuxLeft, + "AuxRight2": ChuckSite.AuxRight2, + "AuxLeft2": ChuckSite.AuxLeft2, + "ChuckCamera": ChuckSite.ChuckCamera, + "SiPhSetHoverHeight": ChuckSite.SiPhSetHoverHeight, + "SiPhFiberPowerMeasure": ChuckSite.SiPhFiberPowerMeasure, + } + try: + return mapping[abbr] + except KeyError: + raise ValueError(f"Unknown ChuckSite abbreviation: {abbr}") + + @deprecated("Use from_string instead.") + @staticmethod + def fromSentioAbbr(abbr: str): mapping = { "Wafer": ChuckSite.Wafer, "AuxRight": ChuckSite.AuxRight, @@ -310,6 +342,21 @@ class ChuckSpeed(Enum): Jog = 3 Index = 4 + @staticmethod + def from_string(abbr: str): + mapping = { + "Fast": ChuckSpeed.Fast, + "Normal": ChuckSpeed.Normal, + "Slow": ChuckSpeed.Slow, + "Jog": ChuckSpeed.Jog, + "Index": ChuckSpeed.Index, + } + try: + return mapping[abbr] + except KeyError: + raise ValueError(f"Unknown ChuckSpeed abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str): mapping = { @@ -499,10 +546,10 @@ class CompensationMode(Enum): def toSentioAbbr(self): switcher = { - CompensationMode.Lateral: "Lateral", - CompensationMode.Vertical: "Vertical", - CompensationMode.Both: "Both", - CompensationMode.ProbeCard: "ProbeCard", + CompensationMode.Lateral: "lateral", + CompensationMode.Vertical: "vertical", + CompensationMode.Both: "both", + CompensationMode.ProbeCard: "probecard", CompensationMode.MapScan: "mapscan", CompensationMode.Thermal: "thermal", CompensationMode.Topography: "topography", @@ -541,31 +588,6 @@ def toSentioAbbr(self): } return switcher.get(self, "Invalid CompensationType") - -class ZCompensationType(Enum): - """A list of Z compensation types. - - Attributes: - Disable (0): None - Topography (1): Vertical (Z) compensation. - MapScan (2): Both lateral and vertical compensation. - AlignDie (3): Probe card compensation. - SkateDetection (4): MapScan compensation. - """ - - Disable = 0 - OnTheFly = 1 - Topography = 2 - - def toSentioAbbr(self): - switcher = { - ZCompensationType.Disable: "None", - ZCompensationType.OnTheFly: "OnTheFly", - ZCompensationType.Topography: "Topography", - } - return switcher.get(self, "Invalid XyCompensationType") - - class DefaultPattern(Enum): """A list of slots for visual patterns used by SENTIO. @@ -656,6 +678,25 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid DetectionCoordindates") +class DevicePosition(Enum): + """Control swap bridge move to up or down side. + + Attributes: + Up (0): Move device to up position. + Down (1): Move device to down position. + """ + + Up = 0 + Down = 1 + + def toSentioAbbr(self): + switcher = { + DevicePosition.Up: "Up", + DevicePosition.Down: "Down", + } + return switcher.get(self, "Invalid device position.") + + class DialogButtons(Enum): """A list of buttons that can be used in SENTIO's dialogs. @@ -691,7 +732,25 @@ def toSentioAbbr(self): DialogButtons.YesNoCancel: "YesNoCancel", } return switcher.get(self, "Invalid button id") - + + @staticmethod + def from_string(abbr: str) -> "DialogButtons": + mapping = { + "Ok": DialogButtons.Ok, + "Cancel": DialogButtons.Cancel, + "OkCancel": DialogButtons.OkCancel, + "Yes": DialogButtons.Yes, + "No": DialogButtons.No, + "YesNo": DialogButtons.YesNo, + "YesCancel": DialogButtons.YesCancel, + "YesNoCancel": DialogButtons.YesNoCancel, + } + try: + return mapping[abbr] + except KeyError: + raise ValueError(f"Unknown button abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str) -> "DialogButtons": mapping = { @@ -788,6 +847,46 @@ class DriftType(Enum): DriftRef = "DriftRef" Drift = "Drift" + +class ElementType(Enum): + """Represents the type of a calibration element.""" + Open = 0 + Short = 1 + Thru = 2 + Load = 3 + Align = 4 + Unknown = 99 + + @staticmethod + def from_string(abbr: str): + mapping = { + "open": ElementType.Open, + "short": ElementType.Short, + "thru": ElementType.Thru, + "load" : ElementType.Load, + "align": ElementType.Align + } + try: + return mapping[abbr.lower()] + except KeyError: + raise ValueError(f"Unknown ElementType string: {abbr}") + + @deprecated("Use from_string instead.") + @staticmethod + def fromSentioAbbr(abbr: str): + mapping = { + "open": ElementType.Open, + "short": ElementType.Short, + "thru": ElementType.Thru, + "load" : ElementType.Load, + "align": ElementType.Align + } + try: + return mapping[abbr.lower()] + except KeyError: + raise ValueError(f"Unknown RoutingPriority abbreviation: {abbr}") + + @deprecated("ExecuteAction is deprecated.") class ExecuteAction(Enum): Execute = 0 @@ -1609,6 +1708,20 @@ def toSentioAbbr(self): } return switcher.get(self, "Invalid RoutingPriority enumerator") + @staticmethod + def from_string(abbr: str): + mapping = { + "R": RoutingPriority.RowUniDir, + "C": RoutingPriority.ColUniDir, + "WR": RoutingPriority.RowBiDir, + "WC": RoutingPriority.ColBiDir, + } + try: + return mapping[abbr.upper()] + except KeyError: + raise ValueError(f"Unknown RoutingPriority abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str): mapping = { @@ -1647,6 +1760,20 @@ def toSentioAbbr(self): } return switcher.get(self, "Invalid RoutingStartPoint enumerator") + @staticmethod + def from_string(abbr: str): + mapping = { + "UL": RoutingStartPoint.UpperLeft, + "UR": RoutingStartPoint.UpperRight, + "LL": RoutingStartPoint.LowerLeft, + "LR": RoutingStartPoint.LowerRight, + } + try: + return mapping[abbr.upper()] + except KeyError: + raise ValueError(f"Unknown RoutingStartPoint abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str): mapping = { @@ -1732,6 +1859,28 @@ def toSentioAbbr(self) -> str: return switcher.get(self, "Invalid subsite group identifier") +class SwapBridgeSide(Enum): + """Control swap bridge move to right or left side. + + Attributes: + Right (0): Move swap bridge to right side. + Left (1): Move swap bridge to left side. + Current (2): Keep bridge at current side. + """ + + Right = 0 + Left = 1 + Current = 2 + + def toSentioAbbr(self): + switcher = { + SwapBridgeSide.Right: "Right", + SwapBridgeSide.Left: "Left", + SwapBridgeSide.Current: "Current", + } + return switcher.get(self, "Invalid swap bridge side.") + + class ThermoChuckState(Enum): """The state of a thermo chuck. @@ -1754,6 +1903,34 @@ class ThermoChuckState(Enum): Controlling = 6 Unknown = 7 + @staticmethod + def from_string(abbr: str) -> "ThermoChuckState": + """Convert a SENTIO abbreviation to a ThermoChuckState. + + Args: + abbr (str): The SENTIO abbreviation. + + Returns: + ThermoChuckState: The corresponding ThermoChuckState. + + Raises: + ValueError: If the abbreviation is not recognized. + """ + mapping = { + "soaking": ThermoChuckState.Soaking, + "cooling": ThermoChuckState.Cooling, + "heating": ThermoChuckState.Heating, + "uncontrolled": ThermoChuckState.Uncontrolled, + "standby": ThermoChuckState.Standby, + "error": ThermoChuckState.Error, + "controlling": ThermoChuckState.Controlling, + } + try: + return mapping[abbr.lower()] + except KeyError: + raise ValueError(f"Unknown ThermoChuckState abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str) -> "ThermoChuckState": """Convert a SENTIO abbreviation to a ThermoChuckState. @@ -1825,6 +2002,18 @@ def toSentioAbbr(self) -> str: VacuumState.On: "On", }.get(self, "Invalid VacuumState") + @staticmethod + def from_string(abbr: str): + mapping = { + "0": VacuumState.Off, + "1": VacuumState.On + } + try: + return mapping[abbr] + except KeyError: + raise ValueError(f"Unknown VacuumState abbreviation: {abbr}") + + @deprecated("Use from_string instead.") @staticmethod def fromSentioAbbr(abbr: str): mapping = { @@ -2010,41 +2199,43 @@ def toSentioAbbr(self): } return switcher.get(self, "Invalid ZPositionHint") -class SwapBridgeSide(Enum): - """Control swap bridge move to right or left side. - - Attributes: - Right (0): Move swap bridge to right side. - Left (1): Move swap bridge to left side. - Current (2): Keep bridge at current side. - """ - - Right = 0 - Left = 1 - Current = 2 - - def toSentioAbbr(self): - switcher = { - SwapBridgeSide.Right: "Right", - SwapBridgeSide.Left: "Left", - SwapBridgeSide.Current: "Current", + @staticmethod + def from_string(abbr: str) -> "ZPositionHint": + """Convert a string to a ZPositionHint. """ + mapping = { + "default":ZPositionHint.Default, + "contact":ZPositionHint.Contact, + "hover":ZPositionHint.Hover, + "separation":ZPositionHint.Separation, + "lift":ZPositionHint.Lift, + "transfer":ZPositionHint.Transfer, } - return switcher.get(self, "Invalid swap bridge side.") - -class DevicePosition(Enum): - """Control swap bridge move to up or down side. + try: + return mapping[abbr.lower()] + except KeyError: + raise ValueError(f"Unknown ChuckPositionHint abbreviation: {abbr}") + + +class ZCompensationType(Enum): + """A list of Z compensation types. Attributes: - Up (0): Move device to up position. - Down (1): Move device to down position. + Disable (0): None + Topography (1): Vertical (Z) compensation. + MapScan (2): Both lateral and vertical compensation. + AlignDie (3): Probe card compensation. + SkateDetection (4): MapScan compensation. """ - - Up = 0 - Down = 1 - + + Disable = 0 + OnTheFly = 1 + Topography = 2 + def toSentioAbbr(self): switcher = { - DevicePosition.Up: "Up", - DevicePosition.Down: "Down", + ZCompensationType.Disable: "None", + ZCompensationType.OnTheFly: "OnTheFly", + ZCompensationType.Topography: "Topography", } - return switcher.get(self, "Invalid device position.") \ No newline at end of file + return switcher.get(self, "Invalid XyCompensationType") + diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index f505817..1b0a126 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -1,33 +1,33 @@ import base64 import os -from typing import Tuple +from typing import Tuple, Optional, Callable, TypeVar from enum import Enum from deprecated import deprecated from sentio_prober_control.Sentio.Enumerations import ( + ChuckPositionHint, ChuckSite, - ChuckXYReference, + ChuckSpeed, ChuckThetaReference, + ChuckXYReference, ChuckZReference, DialogButtons, LoadPosition, - ProjectFileInfo, Module, + ProjectFileInfo, ScopeXYReference, ScopeZReference, + SoftContactState, Stage, SteppingContactMode, - VceZReference, - WorkArea, - ChuckPositionHint, - ChuckSpeed, - VacuumState, HighPowerAirState, - SoftContactState, UserCoordState, SwapBridgeSide, - DevicePosition + DevicePosition, + VacuumState, + VceZReference, + WorkArea ) from sentio_prober_control.Sentio.ProberBase import ProberBase, ProberException @@ -93,7 +93,6 @@ def __init__(self, comm: CommunicatorBase): self.comm.send("*RCS 1") # switch to the native SENTIO remote command set self.aux: AuxCommandGroup = AuxCommandGroup(self) - self.compensation: CompensationCommandGroup = CompensationCommandGroup(self) self.loader: LoaderCommandGroup = LoaderCommandGroup(self) self.map: WafermapCommandGroup = WafermapCommandGroup(self) self.probe: ProbeCommandGroup = ProbeCommandGroup(self) @@ -104,6 +103,12 @@ def __init__(self, comm: CommunicatorBase): self.vision: VisionCommandGroup = VisionCommandGroup(self) self.setup: SetupCommandGroup = SetupCommandGroup(self) + # Command groups for stages; Only available for Sentio > 25.2 + #self.scope: ScopeCommandGroup = ScopeCommandGroup(self) + + # deprecated command groups; may be removed at any time. + # DO NOT USE THEM IN NEW CODE! + self.compensation: CompensationCommandGroup = CompensationCommandGroup(self) def abort_command(self, cmd_id: int) -> Response: """Stop an ongoing asynchronous remote command. @@ -118,20 +123,20 @@ def abort_command(self, cmd_id: int) -> Response: return Response.check_resp(self.comm.read_line()) - def clear_contact(self, site: ChuckSite | None = None) -> None: + def clear_contact(self, chuckSite: Optional[ChuckSite] = None) -> None: """Clear contact positions. Args: - site (ChuckSite): The chuck site to clear. If None is given all sites will be cleared. + chuckSite (ChuckSite): The chuck site to clear. If None is given all sites will be cleared. Returns: - A response object with the result of the command. + None """ - if site is None: + if chuckSite is None: self.comm.send("clear_contact") else: - self.comm.send(f"clear_contact {site.toSentioAbbr()}") + self.comm.send(f"clear_contact {chuckSite.toSentioAbbr()}") Response.check_resp(self.comm.read_line()) @@ -548,6 +553,24 @@ def local_mode(self): """ self.comm.send("*LOCAL") + T = TypeVar("T") + def get(self, variable : str, stype: Callable[[str], T] = str) -> T: + """Get a variable from the prober. + + This function wraps SENTIO's "*GET?" remote command. + This command can query the value of any internal SENTIO variable that is accessible via the + SENTIO's internal environment object. + + Args: + variable (str): The full name of the global variable to get. + + Returns: + value (str): The value of the variable. + """ + self.comm.send(f"*GET? {variable}") + resp : str = self.comm.read_line() + return stype(resp) + def move_chuck_contact(self) -> float: """Move the chuck to contact height. @@ -1118,7 +1141,7 @@ def get_scope_home(self) -> tuple[float, float]: return home_x, home_y - def set_scope_home(self, home_x: float = None, home_y: float = None) -> None: + def set_scope_home(self, home_x: Optional[float] = None, home_y: Optional[float] = None) -> None: """Sets the home position for the scope stage. @@ -1217,8 +1240,8 @@ def get_chuck_position_hint(self) -> tuple[ChuckPositionHint, ChuckSite]: pos_hint_str = tok[0] site_str = tok[1] - pos_hint = ChuckPositionHint.fromSentioAbbr(pos_hint_str) - site = ChuckSite.fromSentioAbbr(site_str) + pos_hint = ChuckPositionHint.from_string(pos_hint_str) + site = ChuckSite.from_string(site_str) return pos_hint, site @@ -1239,7 +1262,7 @@ def get_chuck_site_count(self) -> int: return count - def get_chuck_site_index(self, name: str | None = None) -> int: + def get_chuck_site_index(self, name: Optional[str] = None) -> int: """Retrieve the index of a chuck site by name. If no name is provided, returns the index of the current site. Args: @@ -1261,7 +1284,7 @@ def get_chuck_site_index(self, name: str | None = None) -> int: return index - def get_chuck_site_name(self, index: int | None = None) -> ChuckSite: + def get_chuck_site_name(self, index: Optional[int] = None) -> ChuckSite: """Retrieve the name of a chuck site. If no index is given, returns the current site's name. Args: @@ -1276,11 +1299,11 @@ def get_chuck_site_name(self, index: int | None = None) -> ChuckSite: self.comm.send(f"get_chuck_site_name {index}") resp = Response.check_resp(self.comm.read_line()) - site : ChuckSite = ChuckSite.fromSentioAbbr(resp.message()) + site : ChuckSite = ChuckSite.from_string(resp.message()) return site - def get_chuck_site_pos(self, site: ChuckSite | None = None) -> tuple[float, float, float]: + def get_chuck_site_pos(self, site: Optional[ChuckSite] = None) -> tuple[float, float, float]: """Retrieve position information of a chuck site. Args: @@ -1312,12 +1335,10 @@ def get_chuck_speed(self) -> ChuckSpeed: resp = Response.check_resp(self.comm.read_line()) speed_str = resp.message().split(",")[0] - speed = ChuckSpeed.fromSentioAbbr(speed_str) + speed = ChuckSpeed.from_string(speed_str) return speed - from sentio_prober_control.Sentio.Enumerations import ChuckSite - def get_vacuum_status(self, site: ChuckSite | None = None) -> VacuumState: """Get the vacuum status of a chuck site. @@ -1336,7 +1357,7 @@ def get_vacuum_status(self, site: ChuckSite | None = None) -> VacuumState: resp = Response.check_resp(self.comm.read_line()) status = resp.message().split(",")[0] - return VacuumState.fromSentioAbbr(status) + return VacuumState.from_string(status) def get_wafer_diameter(self) -> float: """Get the diameter of wafer on chuck. From 6a4b8bad6924519ca217d9a3aed5b764a818d879 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 18:19:48 +0200 Subject: [PATCH 2/9] Removed ChuckXYReference, ScopeXYReference, ProbeZReference The python API must mirror the SENTIO API. We must use XyReference and ZReference instead consistently --- .../Sentio/CommandGroups/ProbeCommandGroup.py | 12 +- sentio_prober_control/Sentio/Enumerations.py | 227 +++++++----------- sentio_prober_control/Sentio/ProberSentio.py | 32 ++- 3 files changed, 107 insertions(+), 164 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py index 6d6ac90..84c1221 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py @@ -1,6 +1,6 @@ from typing import Tuple -from sentio_prober_control.Sentio.Enumerations import ProbeSentio, ProbeXYReference, ProbeZReference, ChuckSite +from sentio_prober_control.Sentio.Enumerations import ProbeSentio, XyReference, ZReference, ChuckSite from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -16,7 +16,7 @@ class ProbeCommandGroup(CommandGroupBase): from sentio_prober_control.Sentio.ProberSentio import SentioProber prober = SentioProber.create_prober("tcpip", "127.0.0.1:35555") - prober.probe.move_probe_xy(ProbeSentio.East, ProbeXYReference.Current, 1000, 2000) + prober.probe.move_probe_xy(ProbeSentio.East, XyReference.Current, 1000, 2000) ``` """ @@ -116,7 +116,7 @@ def get_probe_site_number(self, probe: ProbeSentio) -> int: return int(resp.message()) - def get_probe_xy(self, probe: ProbeSentio, ref: ProbeXYReference) -> Tuple[float, float]: + def get_probe_xy(self, probe: ProbeSentio, ref: XyReference) -> Tuple[float, float]: """Get probe xy position in micrometer. Args: @@ -133,7 +133,7 @@ def get_probe_xy(self, probe: ProbeSentio, ref: ProbeXYReference) -> Tuple[float return float(tok[0]), float(tok[1]) - def get_probe_z(self, probe: ProbeSentio, ref: ProbeZReference) -> float: + def get_probe_z(self, probe: ProbeSentio, ref: ZReference) -> float: """Get probe z position in micrometer. Args: @@ -194,7 +194,7 @@ def move_probe_home(self, probe: ProbeSentio) -> Tuple[float, float]: return float(tok[0]), float(tok[1]) - def move_probe_xy(self, probe: ProbeSentio, ref: ProbeXYReference, x: float, y: float) -> Tuple[float, float]: + def move_probe_xy(self, probe: ProbeSentio, ref: XyReference, x: float, y: float) -> Tuple[float, float]: """Move probe to a given position. Args: @@ -213,7 +213,7 @@ def move_probe_xy(self, probe: ProbeSentio, ref: ProbeXYReference, x: float, y: return float(tok[0]), float(tok[1]) - def move_probe_z(self, probe: ProbeSentio, ref: ProbeZReference, z: float) -> float: + def move_probe_z(self, probe: ProbeSentio, ref: ZReference, z: float) -> float: """Move probe to a given z position. Args: diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 80c170e..694d6ba 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -429,62 +429,6 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid chuck theta reference") -class ChuckXYReference(Enum): - """Defines a reference for chuck xy motions. - - Attributes: - Zero (0): Use absolute chuck coordinates. - Home (1): Use home position as reference. - Relative (2): Use curent chuck position as reference. - Center (3): Use chuck center position as reference. - User (4): Use user defined coordinate system. - """ - - Zero = 0 - Home = 1 - Relative = 2 - Center = 3 - User = 4 - - def toSentioAbbr(self): - switcher = { - ChuckXYReference.Zero: "Z", - ChuckXYReference.Home: "H", - ChuckXYReference.Relative: "R", - ChuckXYReference.Center: "C", - ChuckXYReference.User: "U", - } - return switcher.get(self, "Invalid chuck xy reference") - - -class ChuckZReference(Enum): - """Defines a position reference for chuck z-motions. - - Attributes: - Zero (0): Use absolute chuck z coordinates with respect the the physical axis zero positon. - Relative (1): Use relative chuck z coordinated with respect to the current position. - Contact (2): Use relative chuck z coordinated with respect to the chucks contact height. - Hover (3): Use relative chuck z coordinated with respect to the chucks hover height. - Separation (4): Use relative chuck z coordinated with respect to the chucks separation height. - """ - - Zero = 0 - Relative = 1 - Contact = 2 - Hover = 3 - Separation = 4 - - def toSentioAbbr(self): - switcher = { - ChuckZReference.Zero: "Z", - ChuckZReference.Relative: "R", - ChuckZReference.Contact: "C", - ChuckZReference.Hover: "H", - ChuckZReference.Separation: "S", - } - return switcher.get(self, "Invalid chuck z reference") - - class ColorScheme(Enum): """The color scheme used by the wafer map. @@ -1371,44 +1315,6 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid TestSelection") -class ScopeXYReference(Enum): - """Position reference for scope motions. - - Attributes: - Zero (0): Use absolute scope coordinates. - Home (1): Use coordinates with respect to the scope home position. - Relative (2): Use coordinates with respect to the current scope position. - """ - - Zero = 0 - Home = 1 - Relative = 2 - - def toSentioAbbr(self): - switcher = { - ScopeXYReference.Zero: "Z", - ScopeXYReference.Home: "H", - ScopeXYReference.Relative: "R", - } - return switcher.get(self, "Invalid scope xy reference") - - -class ScopeZReference(Enum): - """Scope z reference for scoep motions. - - Attributes: - Zero (0): Use absolute scope coordinates. - Relative (1): Use coordinates with respect to the current scope position. - """ - - Zero = 0 - Relative = 1 - - def toSentioAbbr(self): - switcher = {ScopeZReference.Zero: "Z", ScopeZReference.Relative: "R"} - return switcher.get(self, "Invalid scope z reference") - - class ProbeSentio(Enum): """An enumeration containing a list of position for motorized probes. @@ -1434,53 +1340,6 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid ProbeSentio enumerator") -class ProbeXYReference(Enum): - """Position reference for mororized probe movements. - - Attributes: - Zero (0): Use absolute probe coordinates. - Home (1): Use coordinates with respect to the probe home position. - Current (2): Use coordinates with respect to the current probe position. - """ - - Zero = 0 - Home = 1 - Current = 2 - - def toSentioAbbr(self): - switcher = { - ProbeXYReference.Zero: "Zero", - ProbeXYReference.Home: "Home", - ProbeXYReference.Current: "Current", - } - return switcher.get(self, "Invalid probe xy reference") - - -class ProbeZReference(Enum): - """Position reference for probe z motions. - - Attributes: - Zero (0): Use absolute probe coordinates. - Current (1): Use coordinates with respect to the current probe position. - Contact (2): Use coordinates with respect to the contact height. - Separation (3): Use coordinates with respect to the separation height. - """ - - Zero = 0 - Current = 1 - Contact = 2 - Separation = 3 - - def toSentioAbbr(self): - switcher = { - ProbeZReference.Zero: "Zero", - ProbeZReference.Current: "Current", - ProbeZReference.Contact: "Contact", - ProbeZReference.Separation: "Separation", - } - return switcher.get(self, "Invalid probe z reference") - - class PtpaFindTipsMode(Enum): """Specifies the mode used by ptpa tip finding. @@ -2166,6 +2025,65 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid XyCompensationType") +class XyReference(Enum): + """Defines a reference for stage xy motions. + + Attributes: + Machine (0): Use absolute stage coordinates without considering stage work positions. + Home (1): Use home position as reference. + Center (2): Use center position as reference. + Zero (3): Use absolute stage coordinates for the current work position. + UserDefined (4): Use user defined coordinate system. + Current (5): Use curent position as reference. + RealPos (6): for internal use only. + """ + + Machine = 0 + Home = 1 + Center = 2 + Zero = 3 + UserDefined = 4 + Current = 5 + RealPos = 6 + + def toSentioAbbr(self): + switcher = { + XyReference.Machine: "M", + XyReference.Home: "H", + XyReference.Center: "C", + XyReference.Zero: "Z", + XyReference.UserDefined: "U", + XyReference.Current: "R", + XyReference.RealPos: "A", + } + return switcher.get(self, "Invalid xy reference") + + @staticmethod + def from_string(abbr: str) -> "XyReference": + """Convert a string to a XyReference. """ + mapping = { + "M" : XyReference.Machine, + "Machine" : XyReference.Machine, + "H" : XyReference.Home, + "Home" : XyReference.Home, + "C": XyReference.Center, + "Center": XyReference.Center, + "Z": XyReference.Zero, + "Zero": XyReference.Zero, + "U": XyReference.UserDefined, + "UserDefined": XyReference.UserDefined, + "R": XyReference.Current, + "Relative": XyReference.Current, + "Current": XyReference.Current, + "A": XyReference.RealPos, + "RealPos": XyReference.RealPos, + } + try: + return mapping[abbr.lower()] + except KeyError: + raise ValueError(f"Unknown XyReference abbreviation: {abbr}") + + class ZPositionHint(Enum): """Represents a hint for the z position of a stage. @@ -2239,3 +2157,30 @@ def toSentioAbbr(self): } return switcher.get(self, "Invalid XyCompensationType") + +class ZReference(Enum): + """Defines a position reference for stage z-motions. + + Attributes: + Contact (0): Use relative chuck z coordinated with respect to the chucks contact height. + Separation (1): Use relative chuck z coordinated with respect to the chucks separation height. + Hover (2): Use relative chuck z coordinated with respect to the chucks hover height. + Zero (3): Use absolute chuck z coordinates with respect the the physical axis zero positon. + Current (4): Use relative chuck z coordinated with respect to the current position. + """ + + Contact = 0 + Separation = 1 + Hover = 2 + Zero = 3 + Current = 4 + + def toSentioAbbr(self): + switcher = { + ZReference.Contact: "Contact", + ZReference.Separation: "Separation", + ZReference.Hover: "Hover", + ZReference.Zero: "Zero", + ZReference.Current: "Current" + } + return switcher.get(self, "Invalid chuck z reference") diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index 1b0a126..a6b0aac 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -10,14 +10,10 @@ ChuckSite, ChuckSpeed, ChuckThetaReference, - ChuckXYReference, - ChuckZReference, DialogButtons, LoadPosition, Module, ProjectFileInfo, - ScopeXYReference, - ScopeZReference, SoftContactState, Stage, SteppingContactMode, @@ -27,7 +23,9 @@ DevicePosition, VacuumState, VceZReference, - WorkArea + WorkArea, + XyReference, + ZReference ) from sentio_prober_control.Sentio.ProberBase import ProberBase, ProberException @@ -358,12 +356,12 @@ def get_chuck_theta(self, site: ChuckSite) -> float: return float(resp.message()) - def get_chuck_xy(self, site: ChuckSite, ref: ChuckXYReference) -> Tuple[float, float]: + def get_chuck_xy(self, site: ChuckSite, ref: XyReference) -> Tuple[float, float]: """Get current chuck xy position with respect to a given reference. Args: site (ChuckSite): The chuck site to query. - ref (ChuckXYReference): The reference to use for the query. + ref (XyReference): The reference to use for the query. Returns: x (float): x position in micrometer. @@ -390,11 +388,11 @@ def get_chuck_xy_pos(self) -> Tuple[float, float]: return curX, curY - def get_chuck_z(self, ref: ChuckZReference) -> float: + def get_chuck_z(self, ref: ZReference) -> float: """Get chuck z position. Args: - ref (ChuckZReference): The reference to use for the query. + ref (ZReference): The reference to use for the query. Returns: height (float): The actual z position of the chuck in micrometer (from axis zero). @@ -652,12 +650,12 @@ def move_chuck_theta(self, ref: ChuckThetaReference, angle: float) -> float: ref: The reference to use for the move. angle: The angle to move to in degrees. """ - self.comm.send("move_chuck_theta {0}, {1}".format(ref.toSentioAbbr(), angle)) + self.comm.send(f"move_chuck_theta {ref.toSentioAbbr()}, {angle}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) - def move_chuck_xy(self, ref: ChuckXYReference, x: float, y: float) -> Tuple[float, float]: + def move_chuck_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float]: """Move chuck to a given xy position. Wraps SENTIO's "move_chuck_xy" remote command. @@ -671,13 +669,13 @@ def move_chuck_xy(self, ref: ChuckXYReference, x: float, y: float) -> Tuple[floa x: The chuck x position after the move in micrometer (from zero) y: The chuck y position after the move in micrometer (from zero) """ - self.comm.send("move_chuck_xy {0}, {1}, {2}".format(ref.toSentioAbbr(), x, y)) + self.comm.send(f"move_chuck_xy {ref.toSentioAbbr()}, {x}, {y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) - def move_chuck_z(self, ref: ChuckZReference, z: float) -> float: + def move_chuck_z(self, ref: ZReference, z: float) -> float: """Move chuck to a given z position. Wraps SENTIO's "move_chuck_z" remote command. @@ -689,7 +687,7 @@ def move_chuck_z(self, ref: ChuckZReference, z: float) -> float: Returns: The actual z position in micrometer after the move. """ - self.comm.send("move_chuck_z {0}, {1}".format(ref.toSentioAbbr(), z)) + self.comm.send(f"move_chuck_z {ref.toSentioAbbr()}, {z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -715,7 +713,7 @@ def move_chuck_work_area(self, area: WorkArea) -> None: Response.check_resp(self.comm.read_line()) def move_scope_xy( - self, ref: ScopeXYReference, x: float, y: float + self, ref: XyReference, x: float, y: float ) -> Tuple[float, float]: """Move scope to a given xy position. @@ -749,7 +747,7 @@ def move_scope_lift(self, state: bool): self.comm.send(f"move_scope_lift {state}") Response.check_resp(self.comm.read_line()) - def move_scope_z(self, ref: ScopeZReference, z: float) -> float: + def move_scope_z(self, ref: ZReference, z: float) -> float: """Move scope to a given z position. Args: @@ -759,7 +757,7 @@ def move_scope_z(self, ref: ScopeZReference, z: float) -> float: Returns: The actual z position in micrometer after the move. """ - self.comm.send("move_scope_z {0}, {1}".format(ref.toSentioAbbr(), z)) + self.comm.send(f"move_scope_z {ref.toSentioAbbr()}, {z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) From 8954970040ea0b0c818693d36129ce1757b40679 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 18:27:06 +0200 Subject: [PATCH 3/9] ChuckThetaReference renamed to ThetaReference Enum names must match SENTIO --- sentio_prober_control/Sentio/Enumerations.py | 46 ++++++++++---------- sentio_prober_control/Sentio/ProberSentio.py | 4 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 694d6ba..194326f 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -407,28 +407,6 @@ def toSentioAbbr(self): return switcher.get(self, "Invalid ChuckThermoHoldMode") -class ChuckThetaReference(Enum): - """Reference to use for chuck theat motions. - - Attributes: - Zero (0): Use zero of the theta axis. - Site (1): Use the trained site of "home" angle as the reference. - Relative (2): Use the current theta position as reference. - """ - - Zero = 0 - Site = 1 - Relative = 2 - - def toSentioAbbr(self): - switcher = { - ChuckThetaReference.Zero: "Z", - ChuckThetaReference.Site: "S", - ChuckThetaReference.Relative: "R", - } - return switcher.get(self, "Invalid chuck theta reference") - - class ColorScheme(Enum): """The color scheme used by the wafer map. @@ -1818,6 +1796,28 @@ def fromSentioAbbr(abbr: str) -> "ThermoChuckState": raise ValueError(f"Unknown ThermoChuckState abbreviation: {abbr}") +class ThetaReference(Enum): + """Reference to use for chuck theat motions. + + Attributes: + Zero (0): Use zero of the theta axis. + Align (1): Use the trained site of "home" angle as the reference. + Current (2): Use the current theta position as reference. + """ + + Zero = 0 + Align = 1 + Current = 2 + + def toSentioAbbr(self): + switcher = { + ThetaReference.Zero: "Z", + ThetaReference.Align: "S", + ThetaReference.Current: "R", + } + return switcher.get(self, "Invalid chuck theta reference") + + class UserCoordState(Enum): Chuck = 0 Scope = 1 @@ -2060,7 +2060,7 @@ def toSentioAbbr(self): @staticmethod def from_string(abbr: str) -> "XyReference": - """Convert a string to a XyReference. """ + """ Convert a string to a XyReference. """ mapping = { "M" : XyReference.Machine, "Machine" : XyReference.Machine, diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index a6b0aac..d846c3a 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -9,7 +9,7 @@ ChuckPositionHint, ChuckSite, ChuckSpeed, - ChuckThetaReference, + ThetaReference, DialogButtons, LoadPosition, Module, @@ -641,7 +641,7 @@ def move_chuck_site(self, site: ChuckSite) -> Tuple[float, float, float, float]: return float(tok[0]), float(tok[1]), float(tok[2]), float(tok[3]) - def move_chuck_theta(self, ref: ChuckThetaReference, angle: float) -> float: + def move_chuck_theta(self, ref: ThetaReference, angle: float) -> float: """Move chuck theta axis to a given angle. Wraps SENTIO's "move_chuck_theta" remote command. From afe44072d3fbe1786085bdcbc9cdafbda9b2a1c0 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 18:39:16 +0200 Subject: [PATCH 4/9] VceZReference removed; Use ZReference instead --- sentio_prober_control/Sentio/Enumerations.py | 26 ++++---------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 194326f..b19ef0c 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -1885,22 +1885,6 @@ def fromSentioAbbr(abbr: str): raise ValueError(f"Unknown VacuumState abbreviation: {abbr}") -class VceZReference(Enum): - """Reference for Vce z motions. - - Attributes: - Zero (0): Use absolute Vce coordinates. - Relative (1): Use coordinates with respect to the current Vce position. - """ - - Zero = 0 - Relative = 1 - - def toSentioAbbr(self): - switcher = {VceZReference.Zero: "Z", VceZReference.Relative: "R"} - return switcher.get(self, "Invalid vce z reference") - - class VirtualCarrierInitFlags(Enum): """Flags for initializing a virtual carrier measurement. @@ -2177,10 +2161,10 @@ class ZReference(Enum): def toSentioAbbr(self): switcher = { - ZReference.Contact: "Contact", - ZReference.Separation: "Separation", - ZReference.Hover: "Hover", - ZReference.Zero: "Zero", - ZReference.Current: "Current" + ZReference.Contact: "C", + ZReference.Separation: "S", + ZReference.Hover: "H", + ZReference.Zero: "Z", + ZReference.Current: "R" } return switcher.get(self, "Invalid chuck z reference") From a0afe4adbc683b1c2a07501f6deab79c98b54cde Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 18:54:32 +0200 Subject: [PATCH 5/9] enum to string conversions refactured removed fromSentioAbbr -> use from_string instead toSentioAbbr() renamed to to_string() --- .../Sentio/CommandGroups/AuxCommandGroup.py | 20 +- .../CommandGroups/CompensationCommandGroup.py | 4 +- .../CommandGroups/LoaderCommandGroup.py | 36 +-- .../LoaderVirtualCarrierCommandGroup.py | 2 +- .../Sentio/CommandGroups/ProbeCommandGroup.py | 44 +-- .../Sentio/CommandGroups/SiPHCommandGroup.py | 24 +- .../CommandGroups/StatusCommandGroup.py | 4 +- .../CommandGroups/VisionCameraCommandGroup.py | 22 +- .../CommandGroups/VisionCommandGroup.py | 26 +- .../CommandGroups/VisionCompensationGroup.py | 6 +- .../VisionIMagProCommandGroup.py | 4 +- .../VisionPatternCommandGroup.py | 6 +- .../CommandGroups/WafermapBinsCommandGroup.py | 4 +- .../CommandGroups/WafermapCommandGroup.py | 4 +- .../WafermapCompensationCommandGroup.py | 6 +- .../CommandGroups/WafermapPathCommandGroup.py | 6 +- .../CommandGroups/WafermapPoiCommandGroup.py | 2 +- .../WafermapSubsiteCommandGroup.py | 6 +- sentio_prober_control/Sentio/Enumerations.py | 274 ++++-------------- sentio_prober_control/Sentio/ProberSentio.py | 66 ++--- .../UnitTest/TestAuxCommandGroup.py | 18 +- 21 files changed, 218 insertions(+), 366 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py index ab47852..c232c02 100644 --- a/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/AuxCommandGroup.py @@ -93,7 +93,7 @@ def retrieve_substrate_data(self, site: Optional["ChuckSite"] = None) -> List["C cmd = "aux:retrieve_substrate_data" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()}" + cmd += f" {site.to_string()}" self.comm.send(cmd) resp = Response.check_resp(self.comm.read_line()) @@ -107,7 +107,7 @@ def retrieve_substrate_data(self, site: Optional["ChuckSite"] = None) -> List["C for token in parts[1:]: token = token.strip() for aux_site in ChuckSite: - if token.lower() == aux_site.toSentioAbbr().lower(): + if token.lower() == aux_site.to_string().lower(): sites.append(aux_site) break return sites @@ -130,7 +130,7 @@ def get_substrate_type(self, site: Optional["ChuckSite"] = None) -> str: cmd = "aux:get_substrate_type" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()}" + cmd += f" {site.to_string()}" self.comm.send(cmd) resp = Response.check_resp(self.comm.read_line()) @@ -207,7 +207,7 @@ def get_element_type(self, element_standard_id: str, site: Optional["ChuckSite"] cmd = "aux:get_element_type" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: cmd += f" {element_standard_id}" @@ -232,7 +232,7 @@ def get_substrate_info(self, site: "ChuckSite") -> Tuple[str, str, float]: - life_time (float) in % """ self._validate_aux_site(site) - cmd = f"aux:get_substrate_info {site.toSentioAbbr()}" + cmd = f"aux:get_substrate_info {site.to_string()}" self.comm.send(cmd) resp = Response.check_resp(self.comm.read_line()) parts = resp.message().split(",") @@ -262,7 +262,7 @@ def get_element_touch_count(self, element_standard_id: str, site: Optional["Chuc cmd = "aux:get_element_touch_count" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: cmd += f" {element_standard_id}" @@ -290,7 +290,7 @@ def get_element_spacing(self, element_standard_id: str, site: Optional["ChuckSit cmd = "aux:get_element_spacing" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: cmd += f" {element_standard_id}" @@ -318,7 +318,7 @@ def get_element_pos(self, element_standard_id: str, site: Optional["ChuckSite"] cmd = "aux:get_element_pos" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: cmd += f" {element_standard_id}" @@ -351,7 +351,7 @@ def get_element_life_time(self, element_standard_id: str, site: Optional["ChuckS cmd = "aux:get_element_life_time" if site: self._validate_aux_site(site) - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: cmd += f" {element_standard_id}" @@ -394,7 +394,7 @@ def get_element_info(self, element_standard_id: str, site: Optional["ChuckSite"] if site is not None: self._validate_aux_site(site) # First parameter is the optional chuck site, second is the element ID - cmd += f" {site.toSentioAbbr()},{element_standard_id}" + cmd += f" {site.to_string()},{element_standard_id}" else: # Only the element ID is passed if the site is omitted cmd += f" {element_standard_id}" diff --git a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py index 1d4fc80..201df7f 100644 --- a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py @@ -28,7 +28,7 @@ def set_compensation(self, comp: Compensation, enable: bool): >>> prober.vis.compensation.set_compensation(comp, enable) """ - self.comm.send(f"vis:compensation:enable {comp.toSentioAbbr()}, {enable}") + self.comm.send(f"vis:compensation:enable {comp.to_string()}, {enable}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return tok[0], tok[1] @@ -44,7 +44,7 @@ def execute_compensation(self, comp: ExecuteCompensation, mode: OnTheFlyMode): """ self.comm.send( "vis:compensation:start_execute {},{}".format( - comp.toSentioAbbr(), mode.toSentioAbbr() + comp.to_string(), mode.to_string() ) ) resp = Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/LoaderCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/LoaderCommandGroup.py index e1cc434..7317075 100644 --- a/sentio_prober_control/Sentio/CommandGroups/LoaderCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/LoaderCommandGroup.py @@ -43,7 +43,7 @@ def has_station(self, station: LoaderStation) -> bool: has_station (bool): True if the station is present, False otherwise. """ - self.comm.send(f"loader:has_station {station.toSentioAbbr()}") + self.comm.send(f"loader:has_station {station.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message() == "1" @@ -62,9 +62,9 @@ def load_wafer(self, src_station: LoaderStation, src_slot: int, angle: int | Non """ if angle is None: - self.comm.send(f"loader:load_wafer {src_station.toSentioAbbr()}, {src_slot}") + self.comm.send(f"loader:load_wafer {src_station.to_string()}, {src_slot}") else: - self.comm.send(f"loader:load_wafer {src_station.toSentioAbbr()}, {src_slot}, {angle}") + self.comm.send(f"loader:load_wafer {src_station.to_string()}, {src_slot}, {angle}") resp = Response.check_resp(self.comm.read_line()) if resp.message().lower() == "ok": @@ -85,7 +85,7 @@ def prealign(self, marker: OrientationMarker, angle: int) -> None: angle (float): The prealignment angle. """ - self.comm.send(f"loader:prealign {marker.toSentioAbbr()}, {angle}") + self.comm.send(f"loader:prealign {marker.to_string()}, {angle}") Response.check_resp(self.comm.read_line()) def query_wafer_status(self, station : LoaderStation, slot : int) -> Tuple[LoaderStation, int, int, int, float] | None: @@ -102,7 +102,7 @@ def query_wafer_status(self, station : LoaderStation, slot : int) -> Tuple[Loade status (Tuple[LoaderStation, int, int, int, float]): A tuple with the following elements: OriginStation, OriginSlot, Wafer Size, Wafer Orientation, Progress Value. """ - self.comm.send(f"loader:query_wafer_status {station.toSentioAbbr()}, {slot}") + self.comm.send(f"loader:query_wafer_status {station.to_string()}, {slot}") try: resp = Response.check_resp(self.comm.read_line()) @@ -140,7 +140,7 @@ def scan_station(self, station: LoaderStation) -> str: result (str): A string with the scan result. """ - self.comm.send(f"loader:scan_station {station.toSentioAbbr()}") + self.comm.send(f"loader:scan_station {station.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -157,7 +157,7 @@ def set_wafer_status(self, station: LoaderStation, slot : int, what : WaferStatu value (float): The value to set. """ - self.comm.send(f"loader:set_wafer_status {station.toSentioAbbr()},{slot},{what.toSentioAbbr()},{value}") + self.comm.send(f"loader:set_wafer_status {station.to_string()},{slot},{what.to_string()},{value}") Response.check_resp(self.comm.read_line()) @@ -179,9 +179,9 @@ def start_prepare_station(self, station: LoaderStation, angle: float | None = No """ if angle == None: - self.comm.send(f"loader:start_prepare_station {station.toSentioAbbr()}") + self.comm.send(f"loader:start_prepare_station {station.to_string()}") else: - self.comm.send(f"loader:start_prepare_station {station.toSentioAbbr()}, {angle}") + self.comm.send(f"loader:start_prepare_station {station.to_string()}, {angle}") return Response.check_resp(self.comm.read_line()) @@ -206,7 +206,7 @@ def transfer_wafer( dst_slot (int): The destination slot. """ - self.comm.send(f"loader:transfer_wafer {src_station.toSentioAbbr()}, {src_slot}, {dst_station.toSentioAbbr()}, {dst_slot}") + self.comm.send(f"loader:transfer_wafer {src_station.to_string()}, {src_slot}, {dst_station.to_string()}, {dst_slot}") Response.check_resp(self.comm.read_line()) @@ -222,7 +222,7 @@ def unload_wafer(self, station : LoaderStation | None = None, slot : int = 1) -> """ if station is not None: - self.comm.send(f"loader:unload_wafer {station.toSentioAbbr()}, {slot}") + self.comm.send(f"loader:unload_wafer {station.to_string()}, {slot}") else: self.comm.send("loader:unload_wafer") @@ -241,7 +241,7 @@ def has_cassette(self,station : LoaderStation) -> Tuple[bool, int]: cassette_size (int): The size of the cassette in mm. 0 if no cassette is present. """ - self.comm.send(f"loader:has_cassette {station.toSentioAbbr()}") + self.comm.send(f"loader:has_cassette {station.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(',') has_cassette = tok[0] == "1" @@ -259,7 +259,7 @@ def set_wafer_id(self,station : LoaderStation, slot : int, waferid : str) -> str """ - self.comm.send(f"loader:set_wafer_id {station.toSentioAbbr()}, {slot}, {waferid}") + self.comm.send(f"loader:set_wafer_id {station.to_string()}, {slot}, {waferid}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -272,7 +272,7 @@ def query_wafer_id(self,station : LoaderStation, slot : int) -> str: slot(int):The slot to query waferid """ - self.comm.send(f"loader:query_wafer_id {station.toSentioAbbr()}, {slot}") + self.comm.send(f"loader:query_wafer_id {station.to_string()}, {slot}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -292,7 +292,7 @@ def read_wafer_id(self, angle : int | None = None, side : WaferIdSide | None = N if angle is None and side is None: self.comm.send(f"loader:read_wafer_id") elif angle is not None and side is not None: - self.comm.send(f"loader:read_wafer_id {angle}, {side.toSentioAbbr()}") + self.comm.send(f"loader:read_wafer_id {angle}, {side.to_string()}") else: raise ValueError("Both angle or side must be given or neither of those.") @@ -319,7 +319,7 @@ def start_prepare_wafer(self, station : LoaderStation, slot : int, angle : int, for the command to finish. """ - self.comm.send(f"loader:start_prepare_wafer {station.toSentioAbbr()}, {slot}, {angle}, {1 if read_id else 0}, {unloadstation.toSentioAbbr()}, {unloadslot}") + self.comm.send(f"loader:start_prepare_wafer {station.to_string()}, {slot}, {angle}, {1 if read_id else 0}, {unloadstation.to_string()}, {unloadslot}") return Response.check_resp(self.comm.read_line()) @@ -352,7 +352,7 @@ def query_station_status(self, station : LoaderStation) -> str: status (str): A string consisting of "0" and "1" indicating the presence of a wafer in a slot of the station. """ - self.comm.send(f"loader:query_station_status {station.toSentioAbbr()}") + self.comm.send(f"loader:query_station_status {station.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -372,5 +372,5 @@ def start_read_wafer_id(self, angle : int, side : WaferIdSide) -> Response: for the command to finish. """ - self.comm.send(f"loader:start_read_wafer_id {angle}, {side.toSentioAbbr()}") + self.comm.send(f"loader:start_read_wafer_id {angle}, {side.to_string()}") return Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/LoaderVirtualCarrierCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/LoaderVirtualCarrierCommandGroup.py index 73506c9..85091ea 100644 --- a/sentio_prober_control/Sentio/CommandGroups/LoaderVirtualCarrierCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/LoaderVirtualCarrierCommandGroup.py @@ -67,7 +67,7 @@ def initialize(self, carrier_name : str, mode : VirtualCarrierInitFlags = Virtua A List of steps to execute. """ - resp : Response = self.prober.send_cmd(f"loader:vc:start_initialize {carrier_name},{mode.toSentioAbbr()},{forceDataSync}") + resp : Response = self.prober.send_cmd(f"loader:vc:start_initialize {carrier_name},{mode.to_string()},{forceDataSync}") resp = self.prober.wait_complete(resp.cmd_id()) # parse processing steps into a list of tuples diff --git a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py index 84c1221..7d21f40 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py @@ -39,7 +39,7 @@ def async_step_probe_site(self, probe: ProbeSentio, idx: int) -> int: The async command id of the command. """ - self.comm.send(f"start_step_positioner_site {probe.toSentioAbbr()},{idx}") + self.comm.send(f"start_step_positioner_site {probe.to_string()},{idx}") resp = Response.check_resp(self.comm.read_line()) return resp.cmd_id() @@ -58,7 +58,7 @@ def async_step_probe_site_next(self, probe: ProbeSentio) -> int: The async command id of the command. """ - self.comm.send(f"start_step_positioner_site_next {probe.toSentioAbbr()}") + self.comm.send(f"start_step_positioner_site_next {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.cmd_id() @@ -77,7 +77,7 @@ def async_step_probe_site_first(self, probe: ProbeSentio) -> int: The async command id of the command. """ - self.comm.send(f"start_step_positioner_site_first {probe.toSentioAbbr()}") + self.comm.send(f"start_step_positioner_site_first {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.cmd_id() @@ -94,7 +94,7 @@ def get_probe_site(self, probe: ProbeSentio, idx: int) -> Tuple[str, float, floa Returns: A tuple containing the site index, position x, the position y in micrometer and the reference. """ - self.comm.send(f"get_positioner_site {probe.toSentioAbbr()},{idx}") + self.comm.send(f"get_positioner_site {probe.to_string()},{idx}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -111,7 +111,7 @@ def get_probe_site_number(self, probe: ProbeSentio) -> int: The total number of sites. """ - self.comm.send(f"get_positioner_site_num {probe.toSentioAbbr()}") + self.comm.send(f"get_positioner_site_num {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return int(resp.message()) @@ -127,7 +127,7 @@ def get_probe_xy(self, probe: ProbeSentio, ref: XyReference) -> Tuple[float, flo A tuple containing the x and y position in micrometer. """ - self.comm.send(f"get_positioner_xy {probe.toSentioAbbr()},{ref.toSentioAbbr()}") + self.comm.send(f"get_positioner_xy {probe.to_string()},{ref.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -143,7 +143,7 @@ def get_probe_z(self, probe: ProbeSentio, ref: ZReference) -> float: Returns: The z position in micrometer. """ - self.comm.send(f"get_positioner_z {probe.toSentioAbbr()},{ref.toSentioAbbr()}") + self.comm.send(f"get_positioner_z {probe.to_string()},{ref.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -158,7 +158,7 @@ def move_probe_contact(self, probe: ProbeSentio) -> float: The z position after the move in micrometer (from zero). """ - self.comm.send(f"move_positioner_contact {probe.toSentioAbbr()}") + self.comm.send(f"move_positioner_contact {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -173,7 +173,7 @@ def move_probe_separation(self, probe: ProbeSentio) -> float: The z position after the move in micrometer (from zero). """ - self.comm.send(f"move_positioner_separation {probe.toSentioAbbr()}") + self.comm.send(f"move_positioner_separation {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -188,7 +188,7 @@ def move_probe_home(self, probe: ProbeSentio) -> Tuple[float, float]: A tuple containing the x and y position after the move. """ - self.comm.send(f"move_positioner_home {probe.toSentioAbbr()}") + self.comm.send(f"move_positioner_home {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -207,7 +207,7 @@ def move_probe_xy(self, probe: ProbeSentio, ref: XyReference, x: float, y: float A tuple containing the x and y position after the move. """ - self.comm.send(f"move_positioner_xy {probe.toSentioAbbr()},{ref.toSentioAbbr()},{x},{y}") + self.comm.send(f"move_positioner_xy {probe.to_string()},{ref.to_string()},{x},{y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -225,7 +225,7 @@ def move_probe_z(self, probe: ProbeSentio, ref: ZReference, z: float) -> float: The z position after the move in micrometer (from zero). """ - self.comm.send(f"move_positioner_z {probe.toSentioAbbr()},{ref.toSentioAbbr()},{z}") + self.comm.send(f"move_positioner_z {probe.to_string()},{ref.to_string()},{z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -239,9 +239,9 @@ def set_probe_contact(self, probe: ProbeSentio, z: float | None = None) -> None: """ if z == None: - self.comm.send(f"set_positioner_contact {probe.toSentioAbbr()}") + self.comm.send(f"set_positioner_contact {probe.to_string()}") else: - self.comm.send(f"set_positioner_contact {probe.toSentioAbbr()},{z}") + self.comm.send(f"set_positioner_contact {probe.to_string()},{z}") Response.check_resp(self.comm.read_line()) @@ -256,9 +256,9 @@ def set_probe_home(self, probe: ProbeSentio, site: ChuckSite | None = None, x: f y: The y position in micrometer. If not specified, the current y position is used. """ if site is None: - self.comm.send(f"set_positioner_home {probe.toSentioAbbr()}") + self.comm.send(f"set_positioner_home {probe.to_string()}") else: - self.comm.send(f"set_positioner_home {probe.toSentioAbbr()},{site.toSentioAbbr()},{x},{y}") + self.comm.send(f"set_positioner_home {probe.to_string()},{site.to_string()},{x},{y}") Response.check_resp(self.comm.read_line()) @@ -277,7 +277,7 @@ def step_probe_site(self, probe: ProbeSentio, idx: int) -> Tuple[str, float, flo A tuple containing the site id, the x position in micrometer and the y position in micrometer. """ - self.comm.send(f"step_positioner_site {probe.toSentioAbbr()},{idx}") + self.comm.send(f"step_positioner_site {probe.to_string()},{idx}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -297,7 +297,7 @@ def step_probe_site_first(self, probe: ProbeSentio) -> Tuple[str, float, float]: A tuple containing the site id, the x position in micrometer and the y position in micrometer. """ - self.comm.send(f"step_positioner_site_first {probe.toSentioAbbr()}") + self.comm.send(f"step_positioner_site_first {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return tok[0], float(tok[1]), float(tok[2]) @@ -316,7 +316,7 @@ def step_probe_site_next(self, probe: ProbeSentio) -> Tuple[str, float, float]: A tuple containing the site id, the x position in micrometer and the y position in micrometer. """ - self.comm.send(f"step_positioner_site_next {probe.toSentioAbbr()}") + self.comm.send(f"step_positioner_site_next {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return tok[0], float(tok[1]), float(tok[2]) @@ -331,7 +331,7 @@ def enable_probe_motor(self, probe: ProbeSentio, status: bool) -> None: status: Enable or disable status """ - self.comm.send(f"enable_positioner_motor {probe.toSentioAbbr()},{status}") + self.comm.send(f"enable_positioner_motor {probe.to_string()},{status}") Response.check_resp(self.comm.read_line()) def get_probe_status(self, probe: ProbeSentio) -> str: @@ -347,7 +347,7 @@ def get_probe_status(self, probe: ProbeSentio) -> str: 3rd digit indicates the North Positioner, 4rd digit indicates the South Positioner. """ - self.comm.send(f"get_positioner_status {probe.toSentioAbbr()}") + self.comm.send(f"get_positioner_status {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -361,6 +361,6 @@ def set_probe_status(self, probe: ProbeSentio, status: bool) -> None: status: Enable or disable status """ - self.comm.send(f"set_positioner_status {probe.toSentioAbbr()},{status}") + self.comm.send(f"set_positioner_status {probe.to_string()},{status}") Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py index 801863a..a58cf39 100644 --- a/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/SiPHCommandGroup.py @@ -65,7 +65,7 @@ def move_hover(self, probe: ProbeSentio) -> None: :raises: ProberException if an error occured. """ - self.comm.send(f"siph:move_hover {probe.toSentioAbbr()}") + self.comm.send(f"siph:move_hover {probe.to_string()}") Response.check_resp(self.comm.read_line()) @@ -76,7 +76,7 @@ def move_separation(self, probe: ProbeSentio) -> None: :raises: ProberException if an error occured. """ - self.comm.send(f"siph:move_separation {probe.toSentioAbbr()}") + self.comm.send(f"siph:move_separation {probe.to_string()}") Response.check_resp(self.comm.read_line()) def coupling(self, probe: ProbeSentio, axis: UvwAxis) -> None: @@ -87,7 +87,7 @@ def coupling(self, probe: ProbeSentio, axis: UvwAxis) -> None: axis: Execute axis """ - self.comm.send(f"siph:coupling {probe.toSentioAbbr()},{axis.toSentioAbbr()}") + self.comm.send(f"siph:coupling {probe.to_string()},{axis.to_string()}") Response.check_resp(self.comm.read_line()) def get_alignment(self, probe: ProbeSentio, fiber_type: FiberType) -> Tuple[bool, bool, bool, bool]: @@ -100,7 +100,7 @@ def get_alignment(self, probe: ProbeSentio, fiber_type: FiberType) -> Tuple[bool Returns: A tuple containing the status of Coarse, Fine, Gradient, and Rotary/Focal searching (True/False). """ - self.comm.send(f"siph:get_alignment {probe.toSentioAbbr()},{fiber_type.toSentioAbbr()}") + self.comm.send(f"siph:get_alignment {probe.to_string()},{fiber_type.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -120,7 +120,7 @@ def set_origin(self, probe: ProbeSentio) -> None: Returns: A Response object containing the command execution status. """ - self.comm.send(f"siph:set_origin {probe.toSentioAbbr()}") + self.comm.send(f"siph:set_origin {probe.to_string()}") Response.check_resp(self.comm.read_line()) def move_origin(self, probe: ProbeSentio) -> None: @@ -137,7 +137,7 @@ def move_origin(self, probe: ProbeSentio) -> None: Returns: A Response object containing the command execution status. """ - self.comm.send(f"siph:move_origin {probe.toSentioAbbr()}") + self.comm.send(f"siph:move_origin {probe.to_string()}") Response.check_resp(self.comm.read_line()) def move_position_uvw(self, probe: ProbeSentio, axis: UvwAxis, degree: float) -> float: @@ -151,7 +151,7 @@ def move_position_uvw(self, probe: ProbeSentio, axis: UvwAxis, degree: float) -> Returns: The current position of the axis after movement. """ - self.comm.send(f"siph:move_position_uvw {probe.toSentioAbbr()},{axis.toSentioAbbr()},{degree}") + self.comm.send(f"siph:move_position_uvw {probe.to_string()},{axis.to_string()},{degree}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -165,7 +165,7 @@ def pivot_point(self, probe: ProbeSentio) -> None: Returns: A Response object containing the command execution status. """ - self.comm.send(f"siph:pivot_point {probe.toSentioAbbr()}") + self.comm.send(f"siph:pivot_point {probe.to_string()}") Response.check_resp(self.comm.read_line()) def set_alignment(self, probe: ProbeSentio, fiber_type: FiberType, coarse: bool, fine: bool, gradient: bool, @@ -189,7 +189,7 @@ def set_alignment(self, probe: ProbeSentio, fiber_type: FiberType, coarse: bool, rotary_str = "ON" if rotary else "OFF" self.comm.send( - f"siph:set_alignment {probe.toSentioAbbr()},{fiber_type},{coarse_str},{fine_str},{gradient_str},{rotary_str}") + f"siph:set_alignment {probe.to_string()},{fiber_type},{coarse_str},{fine_str},{gradient_str},{rotary_str}") Response.check_resp(self.comm.read_line()) def set_pivot_point(self, rotary_angle_1: float, rotary_angle_2: float, leveling_angle: float, repeats: int) -> None: @@ -252,7 +252,7 @@ def move_nanocube_xy(self, probe: ProbeSentio, x: float, y: float) -> tuple[floa if not (0 <= x <= 100 and 0 <= y <= 100): raise ValueError("X and Y values must be between 0 and 100 μm.") - self.comm.send(f"siph:move_nanocube_xy {probe.toSentioAbbr()},{x},{y}") + self.comm.send(f"siph:move_nanocube_xy {probe.to_string()},{x},{y}") resp = Response.check_resp(self.comm.read_line()) # Parse response message @@ -270,7 +270,7 @@ def get_nanocube_xy(self, probe: ProbeSentio) -> tuple[float, float]: Returns: A tuple containing the current X and Y positions. """ - self.comm.send(f"siph:get_nanocube_xy {probe.toSentioAbbr()}") + self.comm.send(f"siph:get_nanocube_xy {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) # Parse response message @@ -288,7 +288,7 @@ def get_nanocube_z(self, probe: ProbeSentio) -> float: Returns: The current Z position. """ - self.comm.send(f"siph:get_nanocube_z {probe.toSentioAbbr()}") + self.comm.send(f"siph:get_nanocube_z {probe.to_string()}") resp = Response.check_resp(self.comm.read_line()) # Parse response message diff --git a/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py index 80a4ead..9aab1e1 100644 --- a/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/StatusCommandGroup.py @@ -243,7 +243,7 @@ def show_message(self, message: str, button: DialogButtons = DialogButtons.Ok, c Returns: The button that was pressed. """ - self.comm.send(f"status:show_message {message},{button.toSentioAbbr()},{caption},{level}") + self.comm.send(f"status:show_message {message},{button.to_string()},{caption},{level}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -260,5 +260,5 @@ def start_show_message(self, message: str, button: DialogButtons = DialogButtons Returns: A string containing Command ID and button pressed info. """ - self.comm.send(f"status:start_show_message {message},{button.toSentioAbbr()},{caption},{level}") + self.comm.send(f"status:start_show_message {message},{button.to_string()},{caption},{level}") return Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py index 5bd4fb9..bbeb180 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCameraCommandGroup.py @@ -24,7 +24,7 @@ def set_light(self, mp: CameraMountPoint, value: int) -> None: value: The intensity of the light. """ - self.comm.send(f"vis:set_prop light, {mp.toSentioAbbr()}, {value}") + self.comm.send(f"vis:set_prop light, {mp.to_string()}, {value}") Response.check_resp(self.comm.read_line()) def set_exposure(self, mp: CameraMountPoint, value: int) -> None: @@ -38,7 +38,7 @@ def set_exposure(self, mp: CameraMountPoint, value: int) -> None: A Response object. """ - self.comm.send(f"vis:set_prop exposure, {mp.toSentioAbbr()}, {value}") + self.comm.send(f"vis:set_prop exposure, {mp.to_string()}, {value}") Response.check_resp(self.comm.read_line()) def set_gain(self, mp: CameraMountPoint, value: float) -> None: @@ -49,7 +49,7 @@ def set_gain(self, mp: CameraMountPoint, value: float) -> None: value: The gain value. """ - self.comm.send(f"vis:set_prop gain, {mp.toSentioAbbr()}, {value}") + self.comm.send(f"vis:set_prop gain, {mp.to_string()}, {value}") Response.check_resp(self.comm.read_line()) def get_light(self, mp: CameraMountPoint) -> float: @@ -59,7 +59,7 @@ def get_light(self, mp: CameraMountPoint) -> float: mp: The mount point of the camera. """ - self.comm.send(f"vis:get_prop light, {mp.toSentioAbbr()}") + self.comm.send(f"vis:get_prop light, {mp.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -73,7 +73,7 @@ def get_exposure(self, mp: CameraMountPoint) -> float: The exposure time in microseconds. """ - self.comm.send(f"vis:get_prop exposure, {mp.toSentioAbbr()}") + self.comm.send(f"vis:get_prop exposure, {mp.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -91,7 +91,7 @@ def get_focus_value(self, mp: CameraMountPoint, alg: AutoFocusAlgorithm) -> floa """ self.comm.send( - f"vis:get_focus_value {mp.toSentioAbbr()}, {alg.toSentioAbbr()}" + f"vis:get_focus_value {mp.to_string()}, {alg.to_string()}" ) resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -106,7 +106,7 @@ def get_gain(self, mp: CameraMountPoint) -> float: The gain value. """ - self.comm.send(f"vis:get_prop gain, {mp.toSentioAbbr()}") + self.comm.send(f"vis:get_prop gain, {mp.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -124,7 +124,7 @@ def get_calib(self, mp: CameraMountPoint) -> Tuple[float, float]: height: Get height of a camera pixel in micrometers. """ - self.comm.send(f"vis:get_prop calib, {mp.toSentioAbbr()}") + self.comm.send(f"vis:get_prop calib, {mp.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -140,7 +140,7 @@ def get_image_size(self, mp: CameraMountPoint) -> Tuple[int, int]: height: The height of the image in pixels. """ - self.comm.send(f"vis:get_prop image_size, {mp.toSentioAbbr()}") + self.comm.send(f"vis:get_prop image_size, {mp.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return int(tok[0]), int(tok[1]) @@ -158,11 +158,11 @@ def is_pattern_trained(self, mp: CameraMountPoint, pat) -> bool: """ if isinstance(pat, DefaultPattern): - pattern_name = pat.toSentioAbbr() + pattern_name = pat.to_string() else: pattern_name = pat - self.comm.send(f"vis:pattern:is_trained {mp.toSentioAbbr()}, {pattern_name}") + self.comm.send(f"vis:pattern:is_trained {mp.to_string()}, {pattern_name}") resp = Response.check_resp(self.comm.read_line()) is_trained = resp.message() == "1" return is_trained diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py index 0e11987..8a22fbd 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCommandGroup.py @@ -62,7 +62,7 @@ def align_wafer(self, mode: AutoAlignCmd = AutoAlignCmd.AlignOnly) -> None: if mode==AutoAlignCmd.AlignOnly: self.comm.send(f"vis:align_wafer") else: - self.comm.send(f"vis:align_wafer {mode.toSentioAbbr()}") + self.comm.send(f"vis:align_wafer {mode.to_string()}") Response.check_resp(self.comm.read_line()) @@ -93,7 +93,7 @@ def auto_focus(self, af_cmd: AutoFocusCmd = AutoFocusCmd.Focus) -> tuple[float, Returns: The focus height in micrometer """ - resp = self.prober.send_cmd(f"vis:auto_focus {af_cmd.toSentioAbbr()}") + resp = self.prober.send_cmd(f"vis:auto_focus {af_cmd.to_string()}") tok = resp.message().split(",") return float(tok[0]), MoveAxis[tok[1].capitalize()] @@ -115,7 +115,7 @@ def detect_probetips(self, camera: CameraMountPoint, detector: DetectionAlgorith A list of detected tips. Each detection result is a tuply of 6 values: x, y, width, height, score, class_id. """ - self.comm.send(f"vis:detect_probetips {camera.toSentioAbbr()}, {detector.toSentioAbbr()}, {coords.toSentioAbbr()}") + self.comm.send(f"vis:detect_probetips {camera.to_string()}, {detector.to_string()}, {coords.to_string()}") resp = Response.check_resp(self.comm.read_line()) str_tips = resp.message().split(",") @@ -172,7 +172,7 @@ def find_pattern(self, name: str, threshold: float = 70, pattern_index: int = 0, reference: The reference point to use for the pattern detection. """ - self.comm.send(f"vis:find_pattern {name}, {threshold}, {pattern_index}, {reference.toSentioAbbr()}") + self.comm.send(f"vis:find_pattern {name}, {threshold}, {pattern_index}, {reference.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), float(tok[2]), float(tok[3]) @@ -189,7 +189,7 @@ def has_camera(self, camera: CameraMountPoint) -> bool: True if the camera is present, False otherwise. """ - self.comm.send(f"vis:has_camera {camera.toSentioAbbr()}") + self.comm.send(f"vis:has_camera {camera.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message().upper() == "1" @@ -222,7 +222,7 @@ def match_tips(self, ptpa_type: PtpaType) -> Tuple[float, float]: This function is subject to change without any prior warning. MPI will not maintain backwards compatibility or provide support.""" - self.comm.send("vis:match_tips {0}".format(ptpa_type.toSentioAbbr())) + self.comm.send("vis:match_tips {0}".format(ptpa_type.to_string())) resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -241,7 +241,7 @@ def snap_image(self, file: str, what: SnapshotType = SnapshotType.CameraRaw, whe """ if where == SnapshotLocation.Local: - self.comm.send(f"vis:snap_image **download**, {what.toSentioAbbr()}") + self.comm.send(f"vis:snap_image **download**, {what.to_string()}") resp = Response.check_resp(self.comm.read_line()) jpeg_data = base64.b64decode(resp.message()) @@ -249,7 +249,7 @@ def snap_image(self, file: str, what: SnapshotType = SnapshotType.CameraRaw, whe with open(file, "wb") as f: f.write(jpeg_data) else: - self.comm.send(f"vis:snap_image {file}, {what.toSentioAbbr()}") + self.comm.send(f"vis:snap_image {file}, {what.to_string()}") Response.check_resp(self.comm.read_line()) def switch_light(self, camera: CameraMountPoint, stat: bool): @@ -262,7 +262,7 @@ def switch_light(self, camera: CameraMountPoint, stat: bool): Returns: A Response object. """ - self.comm.send(f"vis:switch_light {camera.toSentioAbbr()}, {stat}") + self.comm.send(f"vis:switch_light {camera.to_string()}, {stat}") Response.check_resp(self.comm.read_line()) def switch_camera(self, camera: CameraMountPoint): @@ -275,7 +275,7 @@ def switch_camera(self, camera: CameraMountPoint): A Response object. """ - self.comm.send(f"vis:switch_camera {camera.toSentioAbbr()}") + self.comm.send(f"vis:switch_camera {camera.to_string()}") def ptpa_find_pads(self, row: int = 0, column: int = 0): self.comm.send("vis:execute_ptpa_find_pads {0},{1}".format(row, column)) @@ -284,7 +284,7 @@ def ptpa_find_pads(self, row: int = 0, column: int = 0): return float(tok[0]), float(tok[1]), float(tok[2]) def ptpa_find_tips(self, ptpa_mode: PtpaFindTipsMode): - self.comm.send("vis:ptpa_find_tips {0}".format(ptpa_mode.toSentioAbbr())) + self.comm.send("vis:ptpa_find_tips {0}".format(ptpa_mode.to_string())) resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), float(tok[2]) @@ -304,7 +304,7 @@ def start_fast_track(self) -> Response: @deprecated("use vision.compensation.start_execute(...) instead!") def start_execute_compensation(self, comp_type: DieCompensationType, comp_mode: DieCompensationMode) -> Response: - self.comm.send("vis:compensation:start_execute {0},{1}".format(comp_type.toSentioAbbr(), comp_mode.toSentioAbbr())) + self.comm.send("vis:compensation:start_execute {0},{1}".format(comp_type.to_string(), comp_mode.to_string())) resp = Response.check_resp(self.comm.read_line()) if not resp.ok(): @@ -354,6 +354,6 @@ def get_light_status(self, camera: CameraMountPoint) -> bool: Returns: True if light is ON """ - self.comm.send(f"vis:get_light_status {camera.toSentioAbbr()}") + self.comm.send(f"vis:get_light_status {camera.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message().strip().lower() == "1" diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py index 96ebbd9..da39028 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionCompensationGroup.py @@ -20,7 +20,7 @@ def __init__(self, prober : 'SentioProber'): @deprecated("Use vision.compensation.enable() instead") def set_compensation(self, comp: CompensationMode, enable: bool) -> Tuple[str, str]: - self.comm.send(f"vis:compensation:enable {comp.toSentioAbbr()}, {enable}") + self.comm.send(f"vis:compensation:enable {comp.to_string()}, {enable}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return tok[0], tok[1] @@ -39,7 +39,7 @@ def enable(self, comp: CompensationMode, enable: bool) -> Tuple[str, str]: Z-Mode: State of the Z compensation. """ - self.comm.send(f"vis:compensation:enable {comp.toSentioAbbr()}, {enable}") + self.comm.send(f"vis:compensation:enable {comp.to_string()}, {enable}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return tok[0], tok[1] @@ -57,5 +57,5 @@ def start_execute(self, type: CompensationType, mode: CompensationMode) -> Respo A Response object. """ - self.comm.send(f"vis:compensation:start_execute {type.toSentioAbbr()}, {mode.toSentioAbbr()}") + self.comm.send(f"vis:compensation:start_execute {type.to_string()}, {mode.to_string()}") return Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py index bbd4541..b7938ea 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionIMagProCommandGroup.py @@ -36,7 +36,7 @@ def move_z(self, ref: IMagProZReference, pos: float) -> float: # Response.check_resp(self.comm.read_line()) # time.sleep(0.5) - self.comm.send("vis:imagpro:move_z {0}, {1}".format(ref.toSentioAbbr(), pos)) + self.comm.send("vis:imagpro:move_z {0}, {1}".format(ref.to_string(), pos)) resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -51,7 +51,7 @@ def get_z(self, ref: IMagProZReference) -> float: The position of the z-axis. """ - par: str = ref.toSentioAbbr() + par: str = ref.to_string() self.comm.send(f"vis:imagpro:get_z {par}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) diff --git a/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py index d52dec1..31f3208 100644 --- a/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/VisionPatternCommandGroup.py @@ -18,7 +18,7 @@ def find(self, name: str, threshold: float = 70, pattern_index: int = 0, referen reference: The reference point to use for the pattern detection. """ - self.comm.send(f"vis:find_pattern {name}, {threshold}, {pattern_index}, {reference.toSentioAbbr()}") + self.comm.send(f"vis:find_pattern {name}, {threshold}, {pattern_index}, {reference.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), float(tok[2]), float(tok[3]) @@ -33,7 +33,7 @@ def get_chuck_pos(self, camera: CameraMountPoint, pattern: DefaultPattern) -> Tu Returns: A tuple with the X and Y coordinates in micrometers. """ - self.comm.send(f"vis:pattern:get_chuck_pos {camera.toSentioAbbr()}, {pattern.toSentioAbbr()}") + self.comm.send(f"vis:pattern:get_chuck_pos {camera.to_string()}, {pattern.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) @@ -50,7 +50,7 @@ def set_chuck_pos(self, camera: CameraMountPoint, pattern: DefaultPattern, x: fl Returns: A tuple with the confirmed X and Y coordinates. """ - self.comm.send(f"vis:pattern:set_chuck_pos {camera.toSentioAbbr()}, {pattern.toSentioAbbr()}, {x}, {y}") + self.comm.send(f"vis:pattern:set_chuck_pos {camera.to_string()}, {pattern.to_string()}, {x}, {y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]) diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapBinsCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapBinsCommandGroup.py index 7c45dd3..b3b78e1 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapBinsCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapBinsCommandGroup.py @@ -92,7 +92,7 @@ def set_all(self, bin_val: int, selection: BinSelection) -> None: bin_val: The bin value to set. selection: The selection of dies to set the bin value for. """ - self.comm.send(f"map:bins:set_all {bin_val}, {selection.toSentioAbbr()}") + self.comm.send(f"map:bins:set_all {bin_val}, {selection.to_string()}") Response.check_resp(self.comm.read_line()) def set_bin(self, bin_value: int, col: int | None = None, row: int | None = None, site: int | None = None) -> None: @@ -139,7 +139,7 @@ def set_bin_info(self, index: int, description: str, bin_quality: BinQuality, co bin_quality: Pass/Fail/Undefined. color: The color of the bin. """ - self.comm.send(f"map:bins:set_bin_info {index}, {description}, {bin_quality.toSentioAbbr()}, {color}") + self.comm.send(f"map:bins:set_bin_info {index}, {description}, {bin_quality.to_string()}, {color}") Response.check_resp(self.comm.read_line()) def resize(self, bin_table_size: int) -> None: diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py index 218b9fc..5e0c4ab 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapCommandGroup.py @@ -359,7 +359,7 @@ def set_axis_orient(self, orient: AxisOrient) -> None: Args: orient: The axis orientation. """ - self.comm.send(f"map:set_axis_orient {orient.toSentioAbbr()}") + self.comm.send(f"map:set_axis_orient {orient.to_string()}") Response.check_resp(self.comm.read_line()) def set_color_scheme(self, scheme: ColorScheme) -> None: @@ -377,7 +377,7 @@ def set_color_scheme(self, scheme: ColorScheme) -> None: Args: scheme: The color scheme. """ - self.comm.send(f"map:set_color_scheme {scheme.toSentioAbbr()}") + self.comm.send(f"map:set_color_scheme {scheme.to_string()}") Response.check_resp(self.comm.read_line()) def set_flat_params(self, angle: int, width: int) -> None: diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapCompensationCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapCompensationCommandGroup.py index f07a25f..1dabfb2 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapCompensationCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapCompensationCommandGroup.py @@ -19,7 +19,7 @@ def topography(self, execute: ExecuteAction) -> Response: Returns: The command ID of the asynchronous operation. """ - self.comm.send(f"map:compensation:topography {execute.toSentioAbbr()}") + self.comm.send(f"map:compensation:topography {execute.to_string()}") resp = Response.check_resp(self.comm.read_line()) if not resp.ok(): @@ -33,7 +33,7 @@ def set_xy(self, comp_type: XyCompensationType) -> None: Args: comp_type: The type of XY Stepping Compensation. """ - self.comm.send(f"map:compensation:set_xy {comp_type.toSentioAbbr()}") + self.comm.send(f"map:compensation:set_xy {comp_type.to_string()}") Response.check_resp(self.comm.read_line()) def set_z(self, comp_type: ZCompensationType) -> None: @@ -42,5 +42,5 @@ def set_z(self, comp_type: ZCompensationType) -> None: Args: comp_type: The type of Z Stepping Compensation. """ - self.comm.send(f"map:compensation:set_z {comp_type.toSentioAbbr()}") + self.comm.send(f"map:compensation:set_z {comp_type.to_string()}") Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapPathCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapPathCommandGroup.py index 96d2d54..df883ca 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapPathCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapPathCommandGroup.py @@ -20,7 +20,7 @@ def create_from_bin(self, bin_val: int | str | PathSelection) -> int: bin_val: The bin value to use. Can be an int or PathSelection enum. """ if isinstance(bin_val, PathSelection): - bin_val_str = bin_val.toSentioAbbr() + bin_val_str = bin_val.to_string() else: bin_val_str = str(bin_val) @@ -53,7 +53,7 @@ def select_dies(self, selection: TestSelection) -> None: Args: selection: The selection of dies to select. """ - self.comm.send(f"map:path:select_dies {selection.toSentioAbbr()}") + self.comm.send(f"map:path:select_dies {selection.to_string()}") Response.check_resp(self.comm.read_line()) def set_routing(self, sp: RoutingStartPoint, pri: RoutingPriority) -> None: @@ -66,7 +66,7 @@ def set_routing(self, sp: RoutingStartPoint, pri: RoutingPriority) -> None: sp: The start point of the routing. pri: The priority of the routing (rows first, columns first). """ - self.comm.send(f"map:set_routing {sp.toSentioAbbr()}, {pri.toSentioAbbr()}") + self.comm.send(f"map:set_routing {sp.to_string()}, {pri.to_string()}") Response.check_resp(self.comm.read_line()) def add_bins(self, selection: int | list[int] | range | list[range]) -> int: diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapPoiCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapPoiCommandGroup.py index cb4b025..8740eee 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapPoiCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapPoiCommandGroup.py @@ -58,7 +58,7 @@ def reset(self, stage: Stage, refXy: PoiReferenceXy) -> None: stage: The stage to reset the POIs for. refXy: The reference point for the POIs. """ - self.comm.send("map:poi:reset {0}, {1}".format(stage.toSentioAbbr(), refXy.toSentioAbbr())) + self.comm.send("map:poi:reset {0}, {1}".format(stage.to_string(), refXy.to_string())) Response.check_resp(self.comm.read_line()) def step(self, target: str | int) -> tuple[int, int, int]: diff --git a/sentio_prober_control/Sentio/CommandGroups/WafermapSubsiteCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/WafermapSubsiteCommandGroup.py index 1b3e844..fddac27 100644 --- a/sentio_prober_control/Sentio/CommandGroups/WafermapSubsiteCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/WafermapSubsiteCommandGroup.py @@ -33,7 +33,7 @@ def add(self, id: str, x: float, y: float, orient: AxisOrient = AxisOrient.UpRig y: The y position of the subsite in micrometer as an offset to the die home position. orient: The axis orientation used fot the submitted values """ - self.comm.send("map:subsite:add {}, {}, {}, {}".format(id, x, y, orient.toSentioAbbr())) + self.comm.send("map:subsite:add {}, {}, {}, {}".format(id, x, y, orient.to_string())) resp = Response.check_resp(self.comm.read_line()) return int(resp.message()) @@ -75,7 +75,7 @@ def get(self, idx: int, orient: AxisOrient | None = None) -> Tuple[str, float, f if orient is None: orient_str = "MAP" else: - orient_str = orient.toSentioAbbr() + orient_str = orient.to_string() self.comm.send(f"map:subsite:get {idx}, {orient_str}") resp = Response.check_resp(self.comm.read_line()) @@ -94,7 +94,7 @@ def get_num(self, group: SubsiteGroup | None = None) -> int: if group is None: group_str = "" else: - group_str = group.toSentioAbbr() + group_str = group.to_string() self.comm.send(f"map:subsite:get_num {group_str}") resp = Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index b19ef0c..507aa4e 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -18,7 +18,7 @@ class AccessLevel(Enum): Service = 1 << 3, Debug = 1 << 4 - def toSentioAbbr(self): + def to_string(self): switcher = { AccessLevel.Operator: "Operator", AccessLevel.Admin: "Admin", @@ -44,7 +44,7 @@ class AutoAlignCmd(Enum): UpdateDieSize = 2 TwoPt = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { AutoAlignCmd.AlignOnly: "alignonly", AutoAlignCmd.AutoDieSize: "auto", @@ -71,7 +71,7 @@ class AutoFocusAlgorithm(Enum): LaplaceStdDev = 4 Harris = 5 - def toSentioAbbr(self): + def to_string(self): switcher = { AutoFocusAlgorithm.Gradient: "Gradient", AutoFocusAlgorithm.Bandpass: "Bandpass", @@ -96,7 +96,7 @@ class AutoFocusCmd(Enum): Focus = 1 GoTo = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { AutoFocusCmd.Calibration: "C", AutoFocusCmd.Focus: "F", @@ -124,7 +124,7 @@ class AxisOrient(Enum): UpRight = 2 UpLeft = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { AxisOrient.DownRight: "DR", AxisOrient.DownLeft: "DL", @@ -147,7 +147,7 @@ class BinSelection(Enum): DiesOnly = 1 SubsitesOnly = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { BinSelection.All: "a", BinSelection.DiesOnly: "d", @@ -169,7 +169,7 @@ class BinQuality(Enum): Fail = 1 Undefined = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { BinQuality.Pass: "pass", BinQuality.Fail: "fail", @@ -203,7 +203,7 @@ class CameraMountPoint(Enum): Angled = 7 BottomScope = 8 - def toSentioAbbr(self): + def to_string(self): switcher = { CameraMountPoint.Scope: "scope", CameraMountPoint.Scope2: "scope2", @@ -245,20 +245,6 @@ def from_string(abbr: str): except KeyError: raise ValueError(f"Unknown ChuckPositionHint abbreviation: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "Probing": ChuckPositionHint.Center, - "FrontLoad": ChuckPositionHint.FrontLoad, - "SideLoad": ChuckPositionHint.SideLoad, - "OffAxisCamera": ChuckPositionHint.OffAxisCamera - } - try: - return mapping[abbr] - except KeyError: - raise ValueError(f"Unknown ChuckPositionHint abbreviation: {abbr}") - class ChuckSite(Enum): """An enumeration containing chuck sites. @@ -286,7 +272,7 @@ class ChuckSite(Enum): SiPhSetHoverHeight = 6 SiPhFiberPowerMeasure = 7 - def toSentioAbbr(self): + def to_string(self): switcher = { ChuckSite.Wafer: "Wafer", ChuckSite.AuxRight: "AuxRight", @@ -316,24 +302,6 @@ def from_string(abbr: str): except KeyError: raise ValueError(f"Unknown ChuckSite abbreviation: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "Wafer": ChuckSite.Wafer, - "AuxRight": ChuckSite.AuxRight, - "AuxLeft": ChuckSite.AuxLeft, - "AuxRight2": ChuckSite.AuxRight2, - "AuxLeft2": ChuckSite.AuxLeft2, - "ChuckCamera": ChuckSite.ChuckCamera, - "SiPhSetHoverHeight": ChuckSite.SiPhSetHoverHeight, - "SiPhFiberPowerMeasure": ChuckSite.SiPhFiberPowerMeasure, - } - try: - return mapping[abbr] - except KeyError: - raise ValueError(f"Unknown ChuckSite abbreviation: {abbr}") - class ChuckSpeed(Enum): Fast = 0 @@ -356,21 +324,6 @@ def from_string(abbr: str): except KeyError: raise ValueError(f"Unknown ChuckSpeed abbreviation: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "Fast": ChuckSpeed.Fast, - "Normal": ChuckSpeed.Normal, - "Slow": ChuckSpeed.Slow, - "Jog": ChuckSpeed.Jog, - "Index": ChuckSpeed.Index, - } - try: - return mapping[abbr] - except KeyError: - raise ValueError(f"Unknown ChuckSpeed abbreviation: {abbr}") - class ChuckThermoEnergyMode(Enum): Fast = 0 @@ -378,7 +331,7 @@ class ChuckThermoEnergyMode(Enum): HighPower = 2 Customized = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { ChuckThermoEnergyMode.Fast: "Fast", ChuckThermoEnergyMode.Optimal: "Optimal", @@ -399,7 +352,7 @@ class ChuckThermoHoldMode(Enum): Active = 0 Nonactive = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { ChuckThermoHoldMode.Active: "Active", ChuckThermoHoldMode.Nonactive: "Nonactive", @@ -418,7 +371,7 @@ class ColorScheme(Enum): ColorFromBin = 0 ColorFromValue = 1 - def toSentioAbbr(self): + def to_string(self): switcher = {ColorScheme.ColorFromBin: 0, ColorScheme.ColorFromValue: 1} return switcher.get(self, "Invalid ColorScheme") @@ -433,7 +386,7 @@ class Compensation(Enum): Thermal = 5 Topography = 6 - def toSentioAbbr(self): + def to_string(self): switcher = { Compensation.Lateral: "lateral", Compensation.Vertical: "vertical", @@ -466,7 +419,7 @@ class CompensationMode(Enum): Thermal = 5 Topography = 6 - def toSentioAbbr(self): + def to_string(self): switcher = { CompensationMode.Lateral: "lateral", CompensationMode.Vertical: "vertical", @@ -498,7 +451,7 @@ class CompensationType(Enum): OnTheFly = 5 OffAxis = 6 - def toSentioAbbr(self): + def to_string(self): switcher = { CompensationType.DieAlign: "DieAlign", CompensationType.Topography: "Topography", @@ -533,7 +486,7 @@ class DefaultPattern(Enum): Vce = 6 Ptpa = 7 - def toSentioAbbr(self): + def to_string(self): switcher = { DefaultPattern.Align: "align", DefaultPattern.Home: "home", @@ -567,7 +520,7 @@ class DetectionAlgorithm(Enum): ProbeDetector = 1 WaferDetector = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { DetectionAlgorithm.Keypoint: "Keypoint", DetectionAlgorithm.ProbeDetector: "ProbeDetector", @@ -591,7 +544,7 @@ class DetectionCoordindates(Enum): Fov = 1 Roi = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { DetectionCoordindates.Image: "Image", DetectionCoordindates.Fov: "Fov", @@ -611,7 +564,7 @@ class DevicePosition(Enum): Up = 0 Down = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { DevicePosition.Up: "Up", DevicePosition.Down: "Down", @@ -642,7 +595,7 @@ class DialogButtons(Enum): YesCancel = 7 YesNoCancel = 8 - def toSentioAbbr(self): + def to_string(self): switcher = { DialogButtons.Ok: "Ok", DialogButtons.Cancel: "Cancel", @@ -672,24 +625,6 @@ def from_string(abbr: str) -> "DialogButtons": except KeyError: raise ValueError(f"Unknown button abbreviation: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str) -> "DialogButtons": - mapping = { - "Ok": DialogButtons.Ok, - "Cancel": DialogButtons.Cancel, - "OkCancel": DialogButtons.OkCancel, - "Yes": DialogButtons.Yes, - "No": DialogButtons.No, - "YesNo": DialogButtons.YesNo, - "YesCancel": DialogButtons.YesCancel, - "YesNoCancel": DialogButtons.YesNoCancel, - } - try: - return mapping[abbr] - except KeyError: - raise ValueError(f"Unknown button abbreviation: {abbr}") - @deprecated("Use CompensationMode instead") class DieCompensationMode(Enum): @@ -711,7 +646,7 @@ class DieCompensationMode(Enum): ProbeCard = 3 SkateDetection = 4 - def toSentioAbbr(self): + def to_string(self): switcher = { DieCompensationMode.Lateral: "Lateral", DieCompensationMode.Vertical: "Vertical", @@ -739,7 +674,7 @@ class DieCompensationType(Enum): OnTheFly = 5 Offaxis = 6 - def toSentioAbbr(self): + def to_string(self): switcher = { DieCompensationType.DieAlign: "DieAlign", DieCompensationType.MapScan: "MapScan", @@ -793,28 +728,13 @@ def from_string(abbr: str): except KeyError: raise ValueError(f"Unknown ElementType string: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "open": ElementType.Open, - "short": ElementType.Short, - "thru": ElementType.Thru, - "load" : ElementType.Load, - "align": ElementType.Align - } - try: - return mapping[abbr.lower()] - except KeyError: - raise ValueError(f"Unknown RoutingPriority abbreviation: {abbr}") - @deprecated("ExecuteAction is deprecated.") class ExecuteAction(Enum): Execute = 0 Abort = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { ExecuteAction.Execute: "execute", ExecuteAction.Abort: "abort", @@ -828,7 +748,7 @@ class ExecuteCompensation(Enum): MapScan = 1 Topography = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { ExecuteCompensation.AlignDie: "AlignDie", ExecuteCompensation.MapScan: "MapScan", @@ -850,7 +770,7 @@ class FiberType(Enum): Array = 1 Lensed = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { FiberType.Single: "Single", FiberType.Array: "Array", @@ -870,7 +790,7 @@ class FindPatternReference(Enum): DieHome = 0 CenterOfRoi = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { FindPatternReference.DieHome: "DieHome", FindPatternReference.CenterOfRoi: "CenterOfRoi", @@ -882,7 +802,7 @@ class HighPowerAirState(Enum): Off = 0 On = 1 - def toSentioAbbr(self) -> str: + def to_string(self) -> str: return { HighPowerAirState.Off: "0", HighPowerAirState.On: "1", @@ -914,7 +834,7 @@ class IMagProZReference(Enum): Relative = 1 Center = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { IMagProZReference.Zero: "Zero", IMagProZReference.Relative: "Relative", @@ -946,7 +866,7 @@ class LoaderStation(Enum): WaferWallet = 6 IdReader = 7 - def toSentioAbbr(self): + def to_string(self): switcher = { LoaderStation.Cassette1: "cas1", LoaderStation.Cassette2: "cas2", @@ -974,7 +894,7 @@ class LoadPosition(Enum): Side = 1 Center = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { LoadPosition.Front: "front", LoadPosition.Side: "side", @@ -1011,7 +931,7 @@ class Module(Enum): Loader = 6 Dashboard = 7 - def toSentioAbbr(self): + def to_string(self): switcher = { Module.Wafermap: "Wafermap", Module.Vision: "Vision", @@ -1032,7 +952,7 @@ class MoveAxis(Enum): Imagpro = 1 Chuck = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { MoveAxis.Scope: "scope", MoveAxis.Imagpro: "imagpro", @@ -1047,7 +967,7 @@ class OnTheFlyMode(Enum): Both = 2 ProbeCard = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { OnTheFlyMode.Lateral: "AlignDie", OnTheFlyMode.Vertical: "MapScan", @@ -1075,7 +995,7 @@ class OrientationMarker(Enum): Notch = 0 Flat = 1 - def toSentioAbbr(self): + def to_string(self): switcher = {OrientationMarker.Notch: "Notch", OrientationMarker.Flat: "Flat"} return switcher.get(self, "Invalid orientation marker") @@ -1095,7 +1015,7 @@ class PathSelection(Enum): Undefined = 2 Unbinned = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { PathSelection.Pass: "pass", PathSelection.Fail: "fail", @@ -1119,7 +1039,7 @@ class PoiReferenceXy(Enum): DieCenter = 0 StageCenter = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { PoiReferenceXy.DieCenter: "DieCenter", PoiReferenceXy.StageCenter: "StageCenter", @@ -1138,7 +1058,7 @@ class ProjectFileInfo(Enum): NameOnly = 0 FullPath = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { ProjectFileInfo.NameOnly: "Name", ProjectFileInfo.FullPath: "FullPath", @@ -1157,7 +1077,7 @@ class PtpaType(Enum): OffAxis = 0 OnAxis = 1 - def toSentioAbbr(self): + def to_string(self): switcher = {PtpaType.OffAxis: "offaxis", PtpaType.OnAxis: "onaxis"} return switcher.get(self, "Invalid ptpa type") @@ -1173,7 +1093,7 @@ class SnapshotType(Enum): will also contain the overlays displayed by the vision module but the image resolution will be whatever the current resolution of SENTIO's vision module is. """ - def toSentioAbbr(self): + def to_string(self): """Turn the SnapshotType into a string that can be used as a parameter for SENTIO's snap_image command.""" switcher = {SnapshotType.CameraRaw: "0", SnapshotType.WithOverlays: "1"} return switcher.get(self, "Invalid SnapshotType type") @@ -1194,7 +1114,7 @@ class SoftContactState(Enum): Disable = 0 Enable = 1 - def toSentioAbbr(self) -> str: + def to_string(self) -> str: return { SoftContactState.Disable: "0", SoftContactState.Enable: "1", @@ -1227,7 +1147,7 @@ class Stage(Enum): Probe3 = 6 Probe4 = 7 - def toSentioAbbr(self): + def to_string(self): switcher = { Stage.Chuck: "chuck", Stage.Scope: "scope", @@ -1254,7 +1174,7 @@ class SteppingContactMode(Enum): StepToSeparation = 1 LockContact = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { SteppingContactMode.BackToContact: "BackToContact", SteppingContactMode.StepToSeparation: "StepToSeparation", @@ -1282,7 +1202,7 @@ class TestSelection(Enum): GoodUglyAndEdge = 3 All = 4 - def toSentioAbbr(self): + def to_string(self): switcher = { TestSelection.Nothing: "n", TestSelection.Good: "g", @@ -1308,7 +1228,7 @@ class ProbeSentio(Enum): North = 2 South = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { ProbeSentio.East: "East", ProbeSentio.West: "West", @@ -1329,7 +1249,7 @@ class PtpaFindTipsMode(Enum): OnAxis = 0 OffAxis = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { PtpaFindTipsMode.OnAxis: "OnAxis", PtpaFindTipsMode.OffAxis: "OffAxis", @@ -1536,7 +1456,7 @@ class RoutingPriority(Enum): RowBiDir = 2 ColBiDir = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { RoutingPriority.RowUniDir: "r", RoutingPriority.ColUniDir: "c", @@ -1558,20 +1478,6 @@ def from_string(abbr: str): except KeyError: raise ValueError(f"Unknown RoutingPriority abbreviation: {abbr}") - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "R": RoutingPriority.RowUniDir, - "C": RoutingPriority.ColUniDir, - "WR": RoutingPriority.RowBiDir, - "WC": RoutingPriority.ColBiDir, - } - try: - return mapping[abbr.upper()] - except KeyError: - raise ValueError(f"Unknown RoutingPriority abbreviation: {abbr}") - class RoutingStartPoint(Enum): """Defines the starting point for routing (stepping commands). @@ -1588,7 +1494,7 @@ class RoutingStartPoint(Enum): LowerLeft = 2 LowerRight = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { RoutingStartPoint.UpperLeft: "ul", RoutingStartPoint.UpperRight: "ur", @@ -1609,20 +1515,6 @@ def from_string(abbr: str): return mapping[abbr.upper()] except KeyError: raise ValueError(f"Unknown RoutingStartPoint abbreviation: {abbr}") - - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "UL": RoutingStartPoint.UpperLeft, - "UR": RoutingStartPoint.UpperRight, - "LL": RoutingStartPoint.LowerLeft, - "LR": RoutingStartPoint.LowerRight, - } - try: - return mapping[abbr.upper()] - except KeyError: - raise ValueError(f"Unknown RoutingStartPoint abbreviation: {abbr}") class StatusBits: @@ -1684,7 +1576,7 @@ class SubsiteGroup(Enum): WaferPresent = 4 WaferSelected = 5 - def toSentioAbbr(self) -> str: + def to_string(self) -> str: switcher = { SubsiteGroup.Present: "P", SubsiteGroup.Selected: "S", @@ -1709,7 +1601,7 @@ class SwapBridgeSide(Enum): Left = 1 Current = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { SwapBridgeSide.Right: "Right", SwapBridgeSide.Left: "Left", @@ -1766,34 +1658,6 @@ def from_string(abbr: str) -> "ThermoChuckState": return mapping[abbr.lower()] except KeyError: raise ValueError(f"Unknown ThermoChuckState abbreviation: {abbr}") - - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str) -> "ThermoChuckState": - """Convert a SENTIO abbreviation to a ThermoChuckState. - - Args: - abbr (str): The SENTIO abbreviation. - - Returns: - ThermoChuckState: The corresponding ThermoChuckState. - - Raises: - ValueError: If the abbreviation is not recognized. - """ - mapping = { - "soaking": ThermoChuckState.Soaking, - "cooling": ThermoChuckState.Cooling, - "heating": ThermoChuckState.Heating, - "uncontrolled": ThermoChuckState.Uncontrolled, - "standby": ThermoChuckState.Standby, - "error": ThermoChuckState.Error, - "controlling": ThermoChuckState.Controlling, - } - try: - return mapping[abbr.lower()] - except KeyError: - raise ValueError(f"Unknown ThermoChuckState abbreviation: {abbr}") class ThetaReference(Enum): @@ -1809,7 +1673,7 @@ class ThetaReference(Enum): Align = 1 Current = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { ThetaReference.Zero: "Z", ThetaReference.Align: "S", @@ -1822,7 +1686,7 @@ class UserCoordState(Enum): Chuck = 0 Scope = 1 - def toSentioAbbr(self) -> str: + def to_string(self) -> str: return { UserCoordState.Chuck: "chuck", UserCoordState.Scope: "scope" @@ -1842,7 +1706,7 @@ class UvwAxis(Enum): V = 1 W = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { UvwAxis.U: "U", UvwAxis.V: "V", @@ -1855,7 +1719,7 @@ class VacuumState(Enum): Off = 0 On = 1 - def toSentioAbbr(self) -> str: + def to_string(self) -> str: return { VacuumState.Off: "Off", VacuumState.On: "On", @@ -1871,18 +1735,6 @@ def from_string(abbr: str): return mapping[abbr] except KeyError: raise ValueError(f"Unknown VacuumState abbreviation: {abbr}") - - @deprecated("Use from_string instead.") - @staticmethod - def fromSentioAbbr(abbr: str): - mapping = { - "0": VacuumState.Off, - "1": VacuumState.On - } - try: - return mapping[abbr] - except KeyError: - raise ValueError(f"Unknown VacuumState abbreviation: {abbr}") class VirtualCarrierInitFlags(Enum): @@ -1896,7 +1748,7 @@ class VirtualCarrierInitFlags(Enum): Start = 0 Continue = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { VirtualCarrierInitFlags.Start: "Start", VirtualCarrierInitFlags.Continue: "Continue", @@ -1916,7 +1768,7 @@ class VirtualCarrierStepProcessingState(Enum): Done = 1 Ready = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { VirtualCarrierStepProcessingState.Skip: "Skip", VirtualCarrierStepProcessingState.Done: "Done", @@ -1937,7 +1789,7 @@ class WaferIdSide(Enum): Top = 0 Bottom = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { WaferIdSide.Top: "T", WaferIdSide.Bottom: "B", @@ -1956,7 +1808,7 @@ class WaferStatusItem(Enum): Progress = 0 Orientation = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { WaferStatusItem.Progress: "Progress", WaferStatusItem.Orientation: "Orientation", @@ -1975,7 +1827,7 @@ class WorkArea(Enum): Probing = 0 Offaxis = 1 - def toSentioAbbr(self): + def to_string(self): switcher = { WorkArea.Probing: "Probing", WorkArea.Offaxis: "Offaxis", @@ -1999,7 +1851,7 @@ class XyCompensationType(Enum): MapScan = 2 Thermal = 3 - def toSentioAbbr(self): + def to_string(self): switcher = { XyCompensationType.Disable: "None", XyCompensationType.OnTheFly: "OnTheFly", @@ -2030,7 +1882,7 @@ class XyReference(Enum): Current = 5 RealPos = 6 - def toSentioAbbr(self): + def to_string(self): switcher = { XyReference.Machine: "M", XyReference.Home: "H", @@ -2090,7 +1942,7 @@ class ZPositionHint(Enum): Lift = 4 Transfer = 5 - def toSentioAbbr(self): + def to_string(self): switcher = { ZPositionHint.Default: "Default", ZPositionHint.Contact: "Contact", @@ -2133,7 +1985,7 @@ class ZCompensationType(Enum): OnTheFly = 1 Topography = 2 - def toSentioAbbr(self): + def to_string(self): switcher = { ZCompensationType.Disable: "None", ZCompensationType.OnTheFly: "OnTheFly", @@ -2159,7 +2011,7 @@ class ZReference(Enum): Zero = 3 Current = 4 - def toSentioAbbr(self): + def to_string(self): switcher = { ZReference.Contact: "C", ZReference.Separation: "S", diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index d846c3a..1266378 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -134,7 +134,7 @@ def clear_contact(self, chuckSite: Optional[ChuckSite] = None) -> None: if chuckSite is None: self.comm.send("clear_contact") else: - self.comm.send(f"clear_contact {chuckSite.toSentioAbbr()}") + self.comm.send(f"clear_contact {chuckSite.to_string()}") Response.check_resp(self.comm.read_line()) @@ -225,7 +225,7 @@ def enable_chuck_site_hover(self, site: ChuckSite, stat: bool) -> None: None """ - self.comm.send(f"enable_chuck_site_hover {site.toSentioAbbr()}, {stat}") + self.comm.send(f"enable_chuck_site_hover {site.to_string()}, {stat}") Response.check_resp(self.comm.read_line()) @@ -241,7 +241,7 @@ def enable_chuck_site_overtravel(self, site: ChuckSite, stat: bool) -> None: None """ - self.comm.send(f"enable_chuck_site_hover {site.toSentioAbbr()}, {stat}") + self.comm.send(f"enable_chuck_site_hover {site.to_string()}, {stat}") Response.check_resp(self.comm.read_line()) @@ -288,7 +288,7 @@ def get_chuck_site_height(self, site: ChuckSite) -> Tuple[float, float, float, f hover_gap (float): hover gap """ - self.comm.send("get_chuck_site_heights {0}".format(site.toSentioAbbr())) + self.comm.send("get_chuck_site_heights {0}".format(site.to_string())) resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -315,7 +315,7 @@ def get_chuck_site_status(self, site: ChuckSite) -> Tuple[bool, bool, bool, bool overtravelActive (bool): True if the overtravel is active. vacuumOn (bool): True if the vacuum is on. """ - self.comm.send("get_chuck_site_status {0}".format(site.toSentioAbbr())) + self.comm.send("get_chuck_site_status {0}".format(site.to_string())) resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -351,7 +351,7 @@ def get_chuck_theta(self, site: ChuckSite) -> float: angle (float): The current angle of the chuck site in degrees. """ - self.comm.send("get_chuck_theta {0}".format(site.toSentioAbbr())) + self.comm.send("get_chuck_theta {0}".format(site.to_string())) resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -369,9 +369,9 @@ def get_chuck_xy(self, site: ChuckSite, ref: XyReference) -> Tuple[float, float] """ if site is None: - self.comm.send(f"get_chuck_xy {site.toSentioAbbr()}") + self.comm.send(f"get_chuck_xy {site.to_string()}") else: - self.comm.send(f"get_chuck_xy {site.toSentioAbbr()}, {ref.toSentioAbbr()}") + self.comm.send(f"get_chuck_xy {site.to_string()}, {ref.to_string()}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -398,7 +398,7 @@ def get_chuck_z(self, ref: ZReference) -> float: height (float): The actual z position of the chuck in micrometer (from axis zero). """ - self.comm.send(f"get_chuck_z {ref.toSentioAbbr()}") + self.comm.send(f"get_chuck_z {ref.to_string()}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -412,7 +412,7 @@ def get_project(self, pfi: ProjectFileInfo = ProjectFileInfo.FullPath) -> str: project_name (str): The name of the current project. """ - self.comm.send(f"get_project {pfi.toSentioAbbr()}") + self.comm.send(f"get_project {pfi.to_string()}") resp = Response.check_resp(self.comm.read_line()) return resp.message() @@ -609,7 +609,7 @@ def move_chuck_load(self, pos: LoadPosition) -> None: Returns: None """ - self.comm.send(f"move_chuck_load {pos.toSentioAbbr()}") + self.comm.send(f"move_chuck_load {pos.to_string()}") Response.check_resp(self.comm.read_line()) @@ -635,7 +635,7 @@ def move_chuck_site(self, site: ChuckSite) -> Tuple[float, float, float, float]: z (float): The z height in micrometer. theta (float): The theta angle in degrees. """ - self.comm.send("move_chuck_site {0}".format(site.toSentioAbbr())) + self.comm.send("move_chuck_site {0}".format(site.to_string())) resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), float(tok[2]), float(tok[3]) @@ -650,7 +650,7 @@ def move_chuck_theta(self, ref: ThetaReference, angle: float) -> float: ref: The reference to use for the move. angle: The angle to move to in degrees. """ - self.comm.send(f"move_chuck_theta {ref.toSentioAbbr()}, {angle}") + self.comm.send(f"move_chuck_theta {ref.to_string()}, {angle}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -669,7 +669,7 @@ def move_chuck_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, fl x: The chuck x position after the move in micrometer (from zero) y: The chuck y position after the move in micrometer (from zero) """ - self.comm.send(f"move_chuck_xy {ref.toSentioAbbr()}, {x}, {y}") + self.comm.send(f"move_chuck_xy {ref.to_string()}, {x}, {y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -687,7 +687,7 @@ def move_chuck_z(self, ref: ZReference, z: float) -> float: Returns: The actual z position in micrometer after the move. """ - self.comm.send(f"move_chuck_z {ref.toSentioAbbr()}, {z}") + self.comm.send(f"move_chuck_z {ref.to_string()}, {z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -709,7 +709,7 @@ def move_chuck_work_area(self, area: WorkArea) -> None: Returns: None """ - self.comm.send(f"move_chuck_work_area {area.toSentioAbbr()}") + self.comm.send(f"move_chuck_work_area {area.to_string()}") Response.check_resp(self.comm.read_line()) def move_scope_xy( @@ -727,7 +727,7 @@ def move_scope_xy( y: Scope x position after the move in micrometers (from zero) """ - self.comm.send(f"move_scope_xy {ref.toSentioAbbr()}, {x}, {y}") + self.comm.send(f"move_scope_xy {ref.to_string()}, {x}, {y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") @@ -757,7 +757,7 @@ def move_scope_z(self, ref: ZReference, z: float) -> float: Returns: The actual z position in micrometer after the move. """ - self.comm.send(f"move_scope_z {ref.toSentioAbbr()}, {z}") + self.comm.send(f"move_scope_z {ref.to_string()}, {z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -776,7 +776,7 @@ def move_vce_z(self, stage: Stage, ref: VceZReference, z: float) -> float: f"This command can only be applied to vce stages! (stage={0})" ) - self.comm.send(f"move_vce_z {stage.toSentioAbbr()}, {ref.toSentioAbbr()}, {z}") + self.comm.send(f"move_vce_z {stage.to_string()}, {ref.to_string()}, {z}") resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) @@ -865,9 +865,9 @@ def select_module(self, module: Module, tabSheet: str | None = None) -> None: tabSheet: The name of the module tab to activate. If None is given the default tab will be activated. """ if tabSheet is not None: - self.comm.send(f"select_module {module.toSentioAbbr()}, {tabSheet}") + self.comm.send(f"select_module {module.to_string()}, {tabSheet}") else: - self.comm.send(f"select_module {module.toSentioAbbr()}") + self.comm.send(f"select_module {module.to_string()}") Response.check_resp(self.comm.read_line()) @@ -930,7 +930,7 @@ def set_chuck_site_height( hover_gap: The new hover gap in micrometer. """ - self.comm.send(f"set_chuck_site_heights {site.toSentioAbbr()},{contact},{separation},{overtravel_dist},{hover_gap}") + self.comm.send(f"set_chuck_site_heights {site.to_string()},{contact},{separation},{overtravel_dist},{hover_gap}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") site = ChuckSite[tok[0]] @@ -969,7 +969,7 @@ def set_stepping_contact_mode(self, mode: SteppingContactMode) -> None: mode: The stepping contact mode to set. """ - self.comm.send(f"set_stepping_contact_mode {mode.toSentioAbbr()}") + self.comm.send(f"set_stepping_contact_mode {mode.to_string()}") Response.check_resp(self.comm.read_line()) @@ -984,7 +984,7 @@ def set_vacuum(self, site: ChuckSite, stat: bool) -> None: None """ - self.comm.send(f"set_vacuum {site.toSentioAbbr()}, {stat}") + self.comm.send(f"set_vacuum {site.to_string()}, {stat}") Response.check_resp(self.comm.read_line()) @@ -1053,7 +1053,7 @@ def show_message( """ self.comm.send( "status:start_show_message {0}, {1}, {2}".format( - msg, buttons.toSentioAbbr(), caption + msg, buttons.to_string(), caption ) ) resp = Response.check_resp(self.comm.read_line()) @@ -1311,7 +1311,7 @@ def get_chuck_site_pos(self, site: Optional[ChuckSite] = None) -> tuple[float, f tuple[float, float, float]: (home_x, home_y, angle) in µm and degrees. """ if site is not None: - site_arg = site.toSentioAbbr() + site_arg = site.to_string() self.comm.send(f"get_chuck_site_pos {site_arg}") else: self.comm.send("get_chuck_site_pos") @@ -1347,7 +1347,7 @@ def get_vacuum_status(self, site: ChuckSite | None = None) -> VacuumState: VacuumState: Enum indicating On or Off. """ if site is not None: - site_arg = site.toSentioAbbr() + site_arg = site.to_string() self.comm.send(f"get_vacuum_status {site_arg}") else: self.comm.send("get_vacuum_status") @@ -1478,7 +1478,7 @@ def set_chuck_site_overtravel_gap(self, site: ChuckSite, gap: float) -> None: if site is None: raise ValueError("site is required and cannot be None") - site_arg = site.toSentioAbbr() + site_arg = site.to_string() self.comm.send(f"set_chuck_site_overtravel_gap {site_arg}, {gap}") Response.check_resp(self.comm.read_line()) @@ -1501,7 +1501,7 @@ def set_chuck_site_pos( None """ if x is not None and y is not None and theta is not None: - site_arg = site.toSentioAbbr() if site is not None else None + site_arg = site.to_string() if site is not None else None if site_arg: self.comm.send(f"set_chuck_site_pos {site_arg},{x},{y},{theta}") @@ -1525,7 +1525,7 @@ def set_chuck_site_separation_gap(self, site: ChuckSite, gap: float) -> None: if site is None: raise ValueError("site is required and cannot be None") - site_arg = site.toSentioAbbr() + site_arg = site.to_string() self.comm.send(f"set_chuck_site_separation_gap {site_arg}, {gap}") Response.check_resp(self.comm.read_line()) @@ -1541,7 +1541,7 @@ def set_high_power_air(self, state: HighPowerAirState) -> None: if state is None: raise ValueError("state is required and must be a valid HighPowerAirState enum") - self.comm.send(f"set_high_power_air {state.toSentioAbbr()}") + self.comm.send(f"set_high_power_air {state.to_string()}") Response.check_resp(self.comm.read_line()) def set_soft_contact(self, state: SoftContactState) -> None: @@ -1556,7 +1556,7 @@ def set_soft_contact(self, state: SoftContactState) -> None: if state is None: raise ValueError("state is required and must be a valid SoftContactState enum") - self.comm.send(f"set_soft_contact {state.toSentioAbbr()}") + self.comm.send(f"set_soft_contact {state.to_string()}") Response.check_resp(self.comm.read_line()) def set_user_coordinate_origin(self, state: UserCoordState, x: float, y: float) -> None: @@ -1573,7 +1573,7 @@ def set_user_coordinate_origin(self, state: UserCoordState, x: float, y: float) if state is None: raise ValueError("state is required and must be a valid UserCoordState") - cmd = f"set_user_coordinate_origin {state.toSentioAbbr()},{x},{y}" + cmd = f"set_user_coordinate_origin {state.to_string()},{x},{y}" self.comm.send(cmd) Response.check_resp(self.comm.read_line()) diff --git a/sentio_prober_control/UnitTest/TestAuxCommandGroup.py b/sentio_prober_control/UnitTest/TestAuxCommandGroup.py index 459c733..90901ee 100644 --- a/sentio_prober_control/UnitTest/TestAuxCommandGroup.py +++ b/sentio_prober_control/UnitTest/TestAuxCommandGroup.py @@ -53,7 +53,7 @@ def test_retrieve_substrate_data_no_site(self): def test_retrieve_substrate_data_with_site(self): self.mock_comm.read_line.return_value = "0,0,1,AuxRight" sites = self.aux.retrieve_substrate_data(ChuckSite.AuxRight) - expected_command = "aux:retrieve_substrate_data " + ChuckSite.AuxRight.toSentioAbbr() + expected_command = "aux:retrieve_substrate_data " + ChuckSite.AuxRight.to_string() self.mock_comm.send.assert_called_with(expected_command) expected_sites = [ChuckSite.AuxRight] self.assertEqual(sites, expected_sites) @@ -68,7 +68,7 @@ def test_get_substrate_type_no_site(self): def test_get_substrate_type_with_site(self): self.mock_comm.read_line.return_value = "0,0,AC-2" result = self.aux.get_substrate_type(ChuckSite.AuxLeft) - expected_command = "aux:get_substrate_type " + ChuckSite.AuxLeft.toSentioAbbr() + expected_command = "aux:get_substrate_type " + ChuckSite.AuxLeft.to_string() self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, "AC-2") @@ -103,7 +103,7 @@ def test_get_element_type_without_site(self): def test_get_element_type_with_site(self): self.mock_comm.read_line.return_value = "0,0,Thru" result = self.aux.get_element_type("0102", ChuckSite.AuxRight) - expected_command = "aux:get_element_type " + ChuckSite.AuxRight.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_type " + ChuckSite.AuxRight.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, ElementType.Thru) @@ -111,7 +111,7 @@ def test_get_element_type_with_site(self): def test_get_substrate_info(self): self.mock_comm.read_line.return_value = "0,0,AC-2,ac2,4.48" result = self.aux.get_substrate_info(ChuckSite.AuxLeft) - expected_command = "aux:get_substrate_info " + ChuckSite.AuxLeft.toSentioAbbr() + expected_command = "aux:get_substrate_info " + ChuckSite.AuxLeft.to_string() self.mock_comm.send.assert_called_with(expected_command) expected = ("AC-2", "ac2", 4.48) self.assertEqual(result, expected) @@ -135,7 +135,7 @@ def test_get_element_touch_count_without_site(self): def test_get_element_touch_count_with_site(self): self.mock_comm.read_line.return_value = "0,0,7" result = self.aux.get_element_touch_count("0102", ChuckSite.AuxRight) - expected_command = "aux:get_element_touch_count " + ChuckSite.AuxRight.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_touch_count " + ChuckSite.AuxRight.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, 7) @@ -150,7 +150,7 @@ def test_get_element_spacing_without_site(self): def test_get_element_spacing_with_site(self): self.mock_comm.read_line.return_value = "0,0,200.5" result = self.aux.get_element_spacing("0102", ChuckSite.AuxLeft) - expected_command = "aux:get_element_spacing " + ChuckSite.AuxLeft.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_spacing " + ChuckSite.AuxLeft.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, 200.5) @@ -165,7 +165,7 @@ def test_get_element_pos_without_site(self): def test_get_element_pos_with_site(self): self.mock_comm.read_line.return_value = "0,0,100.0,200.0" result = self.aux.get_element_pos("0102", ChuckSite.AuxRight) - expected_command = "aux:get_element_pos " + ChuckSite.AuxRight.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_pos " + ChuckSite.AuxRight.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, (100.0, 200.0)) @@ -180,7 +180,7 @@ def test_get_element_life_time_without_site(self): def test_get_element_life_time_with_site(self): self.mock_comm.read_line.return_value = "0,0,85.5" result = self.aux.get_element_life_time("0102", ChuckSite.AuxLeft) - expected_command = "aux:get_element_life_time " + ChuckSite.AuxLeft.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_life_time " + ChuckSite.AuxLeft.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) self.assertEqual(result, 85.5) @@ -205,7 +205,7 @@ def test_get_element_info_without_site(self): def test_get_element_info_with_site(self): self.mock_comm.read_line.return_value = "0,0,Open,NonGSG,100.0,200.0,30.0,1,99.0" result = self.aux.get_element_info("0102", ChuckSite.AuxRight) - expected_command = "aux:get_element_info " + ChuckSite.AuxRight.toSentioAbbr() + ",0102" + expected_command = "aux:get_element_info " + ChuckSite.AuxRight.to_string() + ",0102" self.mock_comm.send.assert_called_with(expected_command) expected = ElementInfo( element_type=ElementType.Open, From f065fb55586ad4c2d052558c424ef6e152b00e72 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 19:25:01 +0200 Subject: [PATCH 6/9] added stub for scope command group --- .../CommandGroups/CompensationCommandGroup.py | 2 +- .../Sentio/CommandGroups/ScopeCommandGroup.py | 41 +++++++++++++++++++ sentio_prober_control/Sentio/Enumerations.py | 30 +++++++------- sentio_prober_control/Sentio/ProberSentio.py | 7 ++-- 4 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py diff --git a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py index 201df7f..83665cb 100644 --- a/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/CompensationCommandGroup.py @@ -13,7 +13,7 @@ class CompensationCommandGroup(CommandGroupBase): Use the SentioProber.vis.compensation group instead! """ - def __init__(self, prober : 'SentioProber') -> None: + def __init__(self, prober : 'SentioProber') -> None: # type: ignore """@private""" super().__init__(prober) diff --git a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py new file mode 100644 index 0000000..ab51952 --- /dev/null +++ b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py @@ -0,0 +1,41 @@ +from typing import Tuple + +from sentio_prober_control.Sentio.Enumerations import ProbeSentio, XyReference, ZReference, ChuckSite +from sentio_prober_control.Sentio.Response import Response +from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase + + +class ScopeCommandGroup(CommandGroupBase): + """This command group contains functions for working with motorized scopes. + You are not meant to instantiate this class directly. Access it via the probe attribute + of the [SentioProber](SentioProber.md) class. + + Example: + + ```py + from sentio_prober_control.Sentio.ProberSentio import SentioProber + + prober = SentioProber.create_prober("tcpip", "127.0.0.1:35555") + prober.scope.move_probe_xy(XyReference.Current, 1000, 2000) + ``` + """ + + def __init__(self, prober: 'SentioProber') -> None: + super().__init__(prober) + + def move_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float, XyReference]: + """Move scope to a given position. + + Args: + ref: The position reference for the submitted values. + x: The x position in micrometer. + y: The y position in micrometer. + + Returns: + A tuple containing the x and y position after the move. + """ + + self.comm.send(f"scope:move_xy {ref.to_string()},{x},{y}") + resp = Response.check_resp(self.comm.read_line()) + tok = resp.message().split(",") + return float(tok[0]), float(tok[1]), XyReference.from_string(tok[2]) \ No newline at end of file diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 507aa4e..5116beb 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -1898,21 +1898,21 @@ def to_string(self): def from_string(abbr: str) -> "XyReference": """ Convert a string to a XyReference. """ mapping = { - "M" : XyReference.Machine, - "Machine" : XyReference.Machine, - "H" : XyReference.Home, - "Home" : XyReference.Home, - "C": XyReference.Center, - "Center": XyReference.Center, - "Z": XyReference.Zero, - "Zero": XyReference.Zero, - "U": XyReference.UserDefined, - "UserDefined": XyReference.UserDefined, - "R": XyReference.Current, - "Relative": XyReference.Current, - "Current": XyReference.Current, - "A": XyReference.RealPos, - "RealPos": XyReference.RealPos, + "m" : XyReference.Machine, + "machine" : XyReference.Machine, + "h" : XyReference.Home, + "home" : XyReference.Home, + "c": XyReference.Center, + "center": XyReference.Center, + "z": XyReference.Zero, + "zero": XyReference.Zero, + "u": XyReference.UserDefined, + "userdefined": XyReference.UserDefined, + "r": XyReference.Current, + "relative": XyReference.Current, + "current": XyReference.Current, + "a": XyReference.RealPos, + "realpos": XyReference.RealPos, } try: return mapping[abbr.lower()] diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index 1266378..5467d32 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -22,7 +22,6 @@ SwapBridgeSide, DevicePosition, VacuumState, - VceZReference, WorkArea, XyReference, ZReference @@ -45,6 +44,7 @@ from sentio_prober_control.Sentio.CommandGroups.VisionCommandGroup import VisionCommandGroup from sentio_prober_control.Sentio.CommandGroups.WafermapCommandGroup import WafermapCommandGroup from sentio_prober_control.Sentio.CommandGroups.SetupCommandGroup import SetupCommandGroup +from sentio_prober_control.Sentio.CommandGroups.ScopeCommandGroup import ScopeCommandGroup class SentioCommunicationType(Enum): """This enum defines different types of prober communication. @@ -102,7 +102,7 @@ def __init__(self, comm: CommunicatorBase): self.setup: SetupCommandGroup = SetupCommandGroup(self) # Command groups for stages; Only available for Sentio > 25.2 - #self.scope: ScopeCommandGroup = ScopeCommandGroup(self) + self.scope: ScopeCommandGroup = ScopeCommandGroup(self) # deprecated command groups; may be removed at any time. # DO NOT USE THEM IN NEW CODE! @@ -761,7 +761,8 @@ def move_scope_z(self, ref: ZReference, z: float) -> float: resp = Response.check_resp(self.comm.read_line()) return float(resp.message()) - def move_vce_z(self, stage: Stage, ref: VceZReference, z: float) -> float: + + def move_vce_z(self, stage: Stage, ref: ZReference, z: float) -> float: """Move VCE stage to a given z position. Args: From 26e7d92aa003eed7cc95f6d8118b8fdd9e33b457 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 19:53:33 +0200 Subject: [PATCH 7/9] Proof of concept for scope command group similar to remote command structure --- .../Sentio/CommandGroups/ScopeCommandGroup.py | 21 ++++++++++++++++--- sentio_prober_control/Sentio/Enumerations.py | 14 +++++++++++++ sentio_prober_control/Sentio/ProberSentio.py | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py index ab51952..78c56b7 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py @@ -1,6 +1,6 @@ from typing import Tuple -from sentio_prober_control.Sentio.Enumerations import ProbeSentio, XyReference, ZReference, ChuckSite +from sentio_prober_control.Sentio.Enumerations import XyReference, Stage from sentio_prober_control.Sentio.Response import Response from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase @@ -20,9 +20,24 @@ class ScopeCommandGroup(CommandGroupBase): ``` """ - def __init__(self, prober: 'SentioProber') -> None: + def __init__(self, prober: 'SentioProber', stage : Stage, has_subgroups = False) -> None: super().__init__(prober) + if stage==Stage.Scope: + self.__scope_selector: str = "top" + elif stage==Stage.BottomScope: + self.__scope_selector: str = "bottom" + elif stage==Stage.AuxiliaryScope: + self.__scope_selector: str = "aux" + else: + raise ValueError(f"Invalid stage {stage} for ScopeCommandGroup") + + if has_subgroups: + self.top: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.Scope) + self.bottom: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.BottomScope) + self.aux: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.AuxiliaryScope) + + def move_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float, XyReference]: """Move scope to a given position. @@ -35,7 +50,7 @@ def move_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float, X A tuple containing the x and y position after the move. """ - self.comm.send(f"scope:move_xy {ref.to_string()},{x},{y}") + self.comm.send(f"scope:{self.__scope_selector}:move_xy {ref.to_string()},{x},{y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), XyReference.from_string(tok[2]) \ No newline at end of file diff --git a/sentio_prober_control/Sentio/Enumerations.py b/sentio_prober_control/Sentio/Enumerations.py index 5116beb..aebfec6 100644 --- a/sentio_prober_control/Sentio/Enumerations.py +++ b/sentio_prober_control/Sentio/Enumerations.py @@ -1136,6 +1136,10 @@ class Stage(Enum): Probe2 (5): Second motorized probe. Probe3 (6): Third motorized probe. Probe4 (7): Fourth motorized probe. + BottomPlaten (8): The bottom platen stage. + BottomScope (9): The bottom scope stage. This is an optional stage. + TopProbe (10): Not a specific stage but a reference to a top probe. + BottomProbe (11): Not a specific stage but a reference to a bottom probe. """ Chuck = 0 @@ -1146,6 +1150,11 @@ class Stage(Enum): Probe2 = 5 Probe3 = 6 Probe4 = 7 + BottomPlaten = 8 + BottomScope = 9 + TopProbe = 10 + BottomProbe = 11 + AuxiliaryScope = 12 def to_string(self): switcher = { @@ -1157,6 +1166,11 @@ def to_string(self): Stage.Probe2: "Probe02", Stage.Probe3: "Probe03", Stage.Probe4: "Probe04", + Stage.BottomPlaten: "bottomplaten", + Stage.BottomScope: "bottomscope", + Stage.TopProbe: "topprobe", + Stage.BottomProbe: "bottomprobe", + Stage.AuxiliaryScope: "auxscope", } return switcher.get(self, "Invalid stage") diff --git a/sentio_prober_control/Sentio/ProberSentio.py b/sentio_prober_control/Sentio/ProberSentio.py index 5467d32..0131566 100644 --- a/sentio_prober_control/Sentio/ProberSentio.py +++ b/sentio_prober_control/Sentio/ProberSentio.py @@ -102,7 +102,7 @@ def __init__(self, comm: CommunicatorBase): self.setup: SetupCommandGroup = SetupCommandGroup(self) # Command groups for stages; Only available for Sentio > 25.2 - self.scope: ScopeCommandGroup = ScopeCommandGroup(self) + self.scope: ScopeCommandGroup = ScopeCommandGroup(self, Stage.Scope, True) # deprecated command groups; may be removed at any time. # DO NOT USE THEM IN NEW CODE! From 2667bfca54c4bd34b8ffad581567cce4f5f8104f Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 19:57:22 +0200 Subject: [PATCH 8/9] Update ScopeCommandGroup.py --- .../Sentio/CommandGroups/ScopeCommandGroup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py index 78c56b7..6304437 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py @@ -32,11 +32,11 @@ def __init__(self, prober: 'SentioProber', stage : Stage, has_subgroups = False) else: raise ValueError(f"Invalid stage {stage} for ScopeCommandGroup") - if has_subgroups: + if stage==Stage.Scope and has_subgroups: self.top: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.Scope) self.bottom: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.BottomScope) self.aux: ScopeCommandGroup = ScopeCommandGroup(prober, Stage.AuxiliaryScope) - + def move_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float, XyReference]: """Move scope to a given position. From 8a43cdebbe3e911e5523d5f94586e174980a73d5 Mon Sep 17 00:00:00 2001 From: Ingo Berg Date: Thu, 5 Jun 2025 19:58:51 +0200 Subject: [PATCH 9/9] Update ScopeCommandGroup.py --- .../Sentio/CommandGroups/ScopeCommandGroup.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py index 6304437..b827813 100644 --- a/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py +++ b/sentio_prober_control/Sentio/CommandGroups/ScopeCommandGroup.py @@ -20,15 +20,17 @@ class ScopeCommandGroup(CommandGroupBase): ``` """ - def __init__(self, prober: 'SentioProber', stage : Stage, has_subgroups = False) -> None: + def __init__(self, prober: 'SentioProber', stage : Stage, has_subgroups = False) -> None: # type: ignore super().__init__(prober) + self.__stage_selector: str = "" + if stage==Stage.Scope: - self.__scope_selector: str = "top" + self.__stage_selector = "top" elif stage==Stage.BottomScope: - self.__scope_selector: str = "bottom" + self.__stage_selector = "bottom" elif stage==Stage.AuxiliaryScope: - self.__scope_selector: str = "aux" + self.__stage_selector = "aux" else: raise ValueError(f"Invalid stage {stage} for ScopeCommandGroup") @@ -50,7 +52,7 @@ def move_xy(self, ref: XyReference, x: float, y: float) -> Tuple[float, float, X A tuple containing the x and y position after the move. """ - self.comm.send(f"scope:{self.__scope_selector}:move_xy {ref.to_string()},{x},{y}") + self.comm.send(f"scope:{self.__stage_selector}:move_xy {ref.to_string()},{x},{y}") resp = Response.check_resp(self.comm.read_line()) tok = resp.message().split(",") return float(tok[0]), float(tok[1]), XyReference.from_string(tok[2]) \ No newline at end of file