diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2605fb84392a054428d4f4579b752d169ecd2876 --- /dev/null +++ b/.gitignore @@ -0,0 +1,192 @@ +## MATLAB ## +# Windows default autosave extension +*.asv + +# OSX / *nix default autosave extension +*.m~ + +# Compiled MEX binaries (all platforms) +*.mex* + +# Packaged app and toolbox files +*.mlappinstall +*.mltbx + +# Generated helpsearch folders +helpsearch*/ + +# Simulink code generation folders +slprj/ +sccprj/ + +# Matlab code generation folders +codegen/ + +# Simulink autosave extension +*.autosave + +# Simulink cache files +*.slxc + +# Octave session info +octave-workspace + +## PYTHON ## +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +Sacher_Lasertechnik/ + +measurements/ +flexsensorpy/measurements/ +.venv-waffel-untersucher/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/flexsensor.iml b/.idea/flexsensor.iml new file mode 100644 index 0000000000000000000000000000000000000000..8a05c6ed5f0c89c2998d9aee8978f53136f7649a --- /dev/null +++ b/.idea/flexsensor.iml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="PyDocumentationSettings"> + <option name="format" value="GOOGLE" /> + <option name="myDocStringFormat" value="Google" /> + </component> +</module> \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..1030d7352b2f9c4feee0960cd1f81183a0144165 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredPackages"> + <value> + <list size="1"> + <item index="0" class="java.lang.String" itemvalue="PySide6" /> + </list> + </value> + </option> + </inspection_tool> + </profile> +</component> \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..67388a2ac340ca6c17e649492b707758f6f04016 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="Black"> + <option name="sdkName" value="Python 3.11 (pythonProject1)" /> + </component> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (pythonProject1)" project-jdk-type="Python SDK" /> +</project> \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..706538a9e64a579a2518d6b4f085ca54bd24db07 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/flexsensor.iml" filepath="$PROJECT_DIR$/.idea/flexsensor.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6323e499d2e6d7a5807f773ef99ea0cc72c8dc7b --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +## Still under construction + + +*This repository is under construction*. It will be restructured after all individual parts are updated. +You can find the dependencies in the gitlab parent folder of this repo. + +# Flexsensor + + +An automation software for [FormFactor Cascade Summit200](https://www.formfactor.com/product/probe-systems/200-mm-systems/summit200/) Probe Stations. +*FlexSensor* is a software that allows to automate measurements using the FormFactor Wafer Prober. + +*FlexSensor* is a standalone Python application. Its versatility allows for immediate deployment, without prior programming knowledge. Particularly noteworthy are its post-processing capabilities, however, the software's core functionality is the use of the automated measurement routine to acquire the resonant spectra of photonic devices, integrated within a specialized measurement system, as detailed in Section + +# Installation +Create a virtual environment (highly recommended) +```python +python -m venv .venv +source .venv/Scripts/Activate +``` +Prior to using the software, these packages need to be installed. +``` +pip install rich PySide6 pyyaml matplotlib pyqtgraph pandas scipy numpy +``` + +# Measuring using Flexsensor +## Input Structure File +The measuring process relies on a ```vas```-File that store the positions to the structures. in priciple +this file os a list of python dictionary in a predefined format, that allows the easy definiton +on how to measure the structures. +The file allows python-style line comments using the ```#```-sign +### Comments and Bookmarks +```python +# First structure to measure +# group="mrr1" +``` +Sometimes it is useful to have the Klayout-positions bookmarked. Using the Klayout-Coordinates, the +software creates a readable Bookmark file that can be used in Klayout. +```python +# Bookmark this view +mrr1_bookmark = { 'x_left': 19012, 'x_right' : 20708, 'y_bottom' : 20185, 'y_top': 21866 } +``` +### Defining a measurement point +Defining a measurement point requires the input position (`x_in`, `y_in`) and the output +position (`x_out`, `y_out`). The keyword `repetitions` allows to define the number of repeated measurements of the same +structure (e.g., for statistical evaluation, etc.) +<br> +**These positions are relative and measured from a predefined point (See Sec ...) on how +to select this point which can be chosen arbitrarily.** +```python +mrr1_ref = {'y_in' : -2120, 'x_in' : 960, 'y_out' : -2120, 'x_out' : -155, 'repetitions': 2} +``` +Sometimes it is useful to define a group of measurement points that are equally spaced in x-direction. For this, the +`spacing` and `num`-keyword can be used. Using these values, the software will automatically generate a list of +`num` structures, equally spaced in x-direction using the `spacing` value. +```python +mrr1 = {'y_in' : -1845, 'x_in' : 960, 'y_out' : -2015, 'x_out' : -155, 'num' : 6, 'spacing' : 100, 'repetitons': 200} +``` + +## Setup bevore measuring +1. Open the correct wafer map. +Open the wafer Map under **Velox** -> **WaferMap**. Load the correct wafer file and select or deselect dies you do not +want to capture. + + **Note**: Make sure that the die and wafer size is correct. +2. Auto-Align the Wafer + For this open the "AutoAlign" Wizard and find a suitable alignment structure. + +3. Place at "your" origin +The structure file relies on "relative" positions to a point you +find a suitable structur which is defined as the "die" origin. This is used to measure the distance to the to/be measured strcutures. Use the same mark in zour Klayout file and on the wafer. + +If you have not yet created a list for measuring your structure, you can use +- the wafer prober find the right coordinates. +- the KLayout-File for measuring the structures +5. Set contact height +Set our fiber to the correct height. Then use the "Set Contact height". Otherwise the measurement routine will fail! +6. Train the Home Positions +This step is crucial and needed to train the output positions. + + +# Lincence and usage +This software is licenced under the [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.de.html). +If you use this software for your work or in your papers please cite me the following: + + + + +# FAQ&Issues +This section should cover the issues that may occure during usage or development. +## Installation issues and running +There are some combinations of pyside6 and pyqtgraph that may lead to incompatibility +issues. Especially `PySide 6.5.0` and `pyqtgraph 0.13.2` installation lead to +```python +TypeError: GraphicsWidgetAnchor.__init__() takes 1 positional argument but 2 were given +``` +[Solution](https://stackoverflow.com/questions/76005506/pyqtgraphs-graphicswidgetanchor-class-incomplatible-with-pyside6?noredirect=1#comment134055507_76005506): +Remove your current installed pyqtgraph and install the latest version: +```python +pip install git+https://github.com/pyqtgraph/pyqtgraph@master +``` \ No newline at end of file diff --git a/src/FlexSensor/BackgroundHandlers/UncertaintyControl/UncertaintyControlWidget.ui b/src/FlexSensor/BackgroundHandlers/UncertaintyControl/UncertaintyControlWidget.ui new file mode 100644 index 0000000000000000000000000000000000000000..67df7de70e1f9c87f604ef83675bca77306071db --- /dev/null +++ b/src/FlexSensor/BackgroundHandlers/UncertaintyControl/UncertaintyControlWidget.ui @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>569</width> + <height>573</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <property name="text"> + <string>Quantity Data</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QFrame" name="horizontalFrame"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label_2"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <property name="text"> + <string>Type</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_2"/> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QFrame" name="horizontalFrame_2"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_3"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <property name="text"> + <string>Uncertainty Distribution</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_3"/> + </item> + </layout> + </widget> + </item> + <item row="3" column="0"> + <layout class="QGridLayout" name="gridLayout_2"/> + </item> + <item row="4" column="0"> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QTabWidget" name="tabWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Unit</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_6"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEdit"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Unit</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Definition</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lineEdit_2"/> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2"> + <attribute name="title"> + <string>Description</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_8"> + <item row="1" column="0"> + <widget class="QPlainTextEdit" name="plainTextEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/FlexSensor/BackgroundHandlers/UncertaintyControl/UncertainyControlWidget.py b/src/FlexSensor/BackgroundHandlers/UncertaintyControl/UncertainyControlWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py b/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py new file mode 100644 index 0000000000000000000000000000000000000000..d7ae53e34c048b54a25fe902a7093a87342bc401 --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py @@ -0,0 +1,40 @@ +import sys + +from PySide6.QtWidgets import QWizard, QApplication + +import Prober as Prober +from InitialSetupWizard.pages.FifthPage import FifthWizardPage +from InitialSetupWizard.pages.ForthPage import ForthWizardPage +from InitialSetupWizard.pages.ThirdPage import ThirdWizardPage +from InitialSetupWizard.pages.SecondPage import SecondWizardPage +from InitialSetupWizard.pages.FirstPage import FirstWizardPage +from generics.logger import setup_logging + + +class InitialSetupWizard(QWizard): + + def __init__(self, prober: Prober.Controller, parent=None): + super().__init__(parent) + self.prober = prober + self.addPage(FirstWizardPage(self.prober, self)) + self.addPage(SecondWizardPage(self.prober, self)) + p3 = ThirdWizardPage(self.prober, self) + self.addPage(p3) + p4 = ForthWizardPage(self.prober, p3, parent=self) + self.addPage(p4) + self.addPage(FifthWizardPage(self.prober, p4, self)) + + self.setWindowTitle("Wizard Example") + + +if __name__ == "__main__": + setup_logging() + + app = QApplication() + prober = Prober.Controller() + wizard = InitialSetupWizard(prober) + + wizard.show() + + sys.exit(app.exec()) + diff --git a/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py b/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py new file mode 100644 index 0000000000000000000000000000000000000000..69a77e60cdb79f970e9786da1b4072fb3e040af3 --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py @@ -0,0 +1,112 @@ +from PySide6.QtWidgets import QWizard, QGridLayout, QLabel, QPushButton + +import Prober as Prober +from InitialSetupWizard.pages.ForthPage import ForthWizardPage +from InitialSetupWizard.pages.WizardPage import WizardPage + + +class FifthWizardPage(WizardPage): + def __init__(self, prober: Prober.Controller, page_input_distance: ForthWizardPage, parent: QWizard = None): + super().__init__(prober, parent) + self.setMaximumHeight(450) + self.setMinimumHeight(450) + + self.setTitle("Train Output Home Position") + layout = QGridLayout() + self.distance = 0 + # p_3: ThirdPage = parent.page(2) + page_input_distance.input_distance.textChanged.connect(self._on_distance_changed) + self.label_intro = QLabel( + f"To train the output home Position the Prober will move both probes in the direction given in the previous" + f"step. \n" + f"First it will move the input probe 500um to the left, then the output probe the given distance " + f"d={self.distance}um so it is placed at the input position. \n" + f"Afterwards the Home position is set to the current " + f"position and both probes are moved back to it's initial position.") + self.label_intro.setWordWrap(True) + layout.addWidget(self.label_intro, 0, 0, 1, 2) + + self.btn_train = QPushButton('Set Home Position') + self.btn_train.clicked.connect(lambda: self.train_warn(self.distance)) + layout.addWidget(self.btn_train, 1, 0, 1, 2) + + self.setLayout(layout) + + def _on_distance_changed(self, distance): + self.distance = int(distance) + self.label_intro.setText( + f"To train the output home Position the Prober will move both probes in the direction given in the previous" + f"step. \n" + f"First it will move the input probe 500um to the left, then the output probe the given distance " + f"d={self.distance}um so it is placed at the input position. \n" + f"Afterwards the Home position is set to the current " + f"position and both probes are moved back to it's initial position.") + + # NO pressed + + def train_warn(self, distance, safe_move_distance=500): + # Bevor continuning display a warning as a dialog box to the user + if self.display_mbox_warning( + text=f"The output optical probes are about to move {distance} towards the input probe. The" + f" input probe will be moved away {safe_move_distance}." + f"Make sure that no obstacles are in the way and the distance is safe to move.", + title="Optical probe are about to move" + ): + self.train(distance, safe_move_distance) + else: + self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") + return + + def train(self, distance, safe_move_distance): + # First read out both positions + x_in, y_in, z_in, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=Prober.Probe.INPUT) + x_out, y_out, z_out, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=Prober.Probe.OUTPUT) + pos = Prober.ProbePosition(input=(x_in, y_in, z_in), output=(x_out, y_out, z_out)) + print(pos) + # Now move the input probe away from the position + + # INPUT -safe_move_distance #=================================================================================== + self.logger.info(f"Moving input probe {-safe_move_distance}um.") + self.prober.opt_if.move_optical_probe(Prober.Probe.INPUT, -safe_move_distance, '0', 'R') + self.logger.info(f"Moved input probe {-safe_move_distance}um.") + # ============================================================================================================== + + # OUTPUT -distance ============================================================================================= + self.logger.info(f"Moving output probe {-distance}um.") + if self.display_mbox_warning( + text=f"The optical output probe is about to move {-distance}um towards the input probe. " + f"Make sure that the output probe has been moved!", + title="Optical output probe are about to move", + ): + self.prober.opt_if.move_optical_probe(Prober.Probe.OUTPUT, -distance, '0', 'R') + self.logger.info(f"Moved output probe {-distance}um.") + else: + self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") + return + # ============================================================================================================== + + # ============================================================================================================== + self.prober.opt_if.set_optical_probe_home(Prober.Probe.OUTPUT) + self.logger.info(f"Set optical output home to current position") + # ============================================================================================================== + + # OUTPUT distance ============================================================================================== + self.logger.info(f"Moving output probe {distance}um back to initial position ") + self.prober.opt_if.move_optical_probe(Prober.Probe.OUTPUT, distance, '0', 'R') + # ============================================================================================================== + + # INPUT safe_move_distance ===================================================================================== + self.logger.info(f"Moving input probe {safe_move_distance}um back to initial position.") + if self.display_mbox_warning( + text=f"The optical input probe is about to move {safe_move_distance}um towards the output probe. " + f"Make sure that the output probe position has been reset!", + title="Optical output probe are about to move" + ): + self.prober.opt_if.move_optical_probe(Prober.Probe.INPUT, safe_move_distance, '0', 'R') + self.logger.info(f"Moved input probe {safe_move_distance}.") + else: + self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") + return + # ============================================================================================================== + self.display_mbox_ok(text="The home position has been set successfully!", + title="Home position set") diff --git a/src/FlexSensor/InitialSetupWizard/pages/FirstPage.py b/src/FlexSensor/InitialSetupWizard/pages/FirstPage.py new file mode 100644 index 0000000000000000000000000000000000000000..ad7b2688bfe6ac7f06141d46b38e804a810e433d --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/FirstPage.py @@ -0,0 +1,33 @@ +from PySide6.QtCore import Qt +from PySide6.QtGui import QPixmap +from PySide6.QtWidgets import QWizard, QVBoxLayout, QLabel + +import Prober as Prober +from InitialSetupWizard.pages.WizardPage import WizardPage + + +class FirstWizardPage(WizardPage): + def __init__(self, prober: Prober.Controller, parent=None): + super().__init__(prober, parent) + + self.setPixmap(QWizard.WizardPixmap.WatermarkPixmap, QPixmap()) + + layout = QVBoxLayout() + + self.setTitle("Train Output Home Position") + + label = QLabel("This wizard will guide you trough the calibration step. \n" + "During the process the Prober (Chuck, etc.) and the Optical Interface (Hexapods, etc.) will " + "move! The wizard won't start the movement automatically and each step " + "must be verified by the user and started manually.\n" + "\n" + "To prevent damage, the setup process are designed to check each steps. Thus," + "checking the individual steps is required to continue the calibration.\n\n " + "Click 'Next' to start the wizard.") + label.setWordWrap(True) + label.setAlignment(Qt.AlignLeft) + + # Add an image to the QWizardPage + layout.addWidget(label) + + self.setLayout(layout) diff --git a/src/FlexSensor/InitialSetupWizard/pages/ForthPage.py b/src/FlexSensor/InitialSetupWizard/pages/ForthPage.py new file mode 100644 index 0000000000000000000000000000000000000000..c6fe8a47352728f4617669cc3b64de4000a02c01 --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/ForthPage.py @@ -0,0 +1,74 @@ +from PySide6.QtWidgets import QGridLayout, QPushButton, QLabel, QLineEdit, QCheckBox + +import Prober as Prober +from InitialSetupWizard.pages.ThirdPage import ThirdWizardPage +from InitialSetupWizard.pages.WizardPage import WizardPage + + +class ForthWizardPage(WizardPage): + def __init__(self, prober: Prober.Controller, third_page: ThirdWizardPage, parent=None): + super().__init__(prober, parent) + self.third_page = third_page + self.setTitle("Positioning of the Probes") + layout = QGridLayout() + + task_set_chuck_home_position, _ = self.add_task( + "1. Move to the calibration structure", + "Click on the next button 'Move to calibration structure' to move the chuck back to the calibration structure.\n" + "Warning: The probes will be moved 250um away from the selected position to ease the next step.", + "task_move_back_to_cal_structure*") + layout.addWidget(task_set_chuck_home_position, 1, 0, 1, 4) + + # ============================================================================================================== + # layout.addWidget(self.add_graphics(path=f'{self.imgf}/1_placed_at_origin_cut.JPG'), 10, 0, 1, 4) + self.btn_move_back_to_cal_structure = QPushButton('Move to calibration structure') + layout.addWidget(self.btn_move_back_to_cal_structure, 2, 0, 1, 4) + self.btn_move_back_to_cal_structure.clicked.connect(lambda: self.move_back_to_cal_structure(probe_movement=250)) + + task_measure_distance, _ = self.add_task( + "2. Measure the distance between the input and the output.", + "For calibrating the position of the input probe to the output probe, " + "the difference of the input and the output must be determined. If the " + "distance is not known, Velox's Measurement Tool can be used. \n" + "Note: If using layout values make sure to include a distance which " + "corresponds to the position of input and the output probes", + "measure_distance*") + layout.addWidget(task_measure_distance, 3, 0, 1, 4) + + graphics1 = self.add_graphics(f'{self.imgf}/Step4_2.png') + layout.addWidget(graphics1, 4, 0, 1, 4) + + self.task_enter_distance, self.cb_distance_enterd = self.add_task( + "3. Enter the (measured) distance between input and output.", + "Enter the measured distance below and press 'Apply' to move the chuck half the given distance", + "task_measure_distance*") + layout.addWidget(self.task_enter_distance, 5, 0, 1, 4) + self.cb_distance_enterd.setCheckable(False) + + lbl_distance = QLabel("Distance (d)") + self.input_distance = QLineEdit() + + # self.btn_apply = QPushButton('Move chuck') + layout.addWidget(lbl_distance, 6, 0, 1, 1) + layout.addWidget(self.input_distance, 6, 1, 1, 1) + self.btn_measurement_done = QPushButton("Apply") + layout.addWidget(self.btn_measurement_done, 6, 2, 1, 2) + self.btn_measurement_done.clicked.connect(lambda: self.move_probes_back(probe_movement=250)) + self.registerField('distance*', self.input_distance) + + self.setLayout(layout) + + + + def move_back_to_cal_structure(self, probe_movement=250): + self.move_chuck_x_y(-int(self.third_page.input_movement_x.text()), -int(self.third_page.lbl_movement_y.text()) ) + self.move_input_probes_x_y(-probe_movement, 0) + self.move_output_probes_x_y(probe_movement, 0) + + def move_probes_back(self, probe_movement=250): + self.move_input_probes_x_y(probe_movement, 0) + self.move_output_probes_x_y(-probe_movement, 0) + self.cb_distance_enterd: QCheckBox + self.cb_distance_enterd.setCheckable(True) + self.cb_distance_enterd.setChecked(True) + self.completeChanged.emit() \ No newline at end of file diff --git a/src/FlexSensor/InitialSetupWizard/pages/SecondPage.py b/src/FlexSensor/InitialSetupWizard/pages/SecondPage.py new file mode 100644 index 0000000000000000000000000000000000000000..e65cd134badd553202ef305f81cc5211378acced --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/SecondPage.py @@ -0,0 +1,50 @@ +from PySide6.QtWidgets import QVBoxLayout, QLabel, QPushButton + +import Prober as Prober +from InitialSetupWizard.pages.WizardPage import WizardPage + + +class SecondWizardPage(WizardPage): + + def __init__(self, prober: Prober.Controller, parent=None): + super().__init__(prober, parent) + self.setTitle("Initial Setup") + self.setSubTitle("In this step, the home position will be set.") + + layout = QVBoxLayout() + labeli = QLabel("The structure file relies on 'relative' positions to a 'zero' point. Usually such a suitable" + "structure can be chosen as the 'die' origin. From this 'zero' position, " + "every coordinates (x, y) is used to measure the distance to" + "the to/be measured structures.") + labeli.setWordWrap(True) + layout.addWidget(labeli) + + label1 = QLabel("Use the same 'mark' in the Klayout file and on the wafer. Usually the die's edge is a good" + "point.\n") + layout.addWidget(label1) + + # ============================================================================================================== + task_move_chuck, _ = self.add_task( + "1. Manually move chuck to the calibration structure", + "Manually move the Chuck to the calibration structure using the the Velox Chuck Control. " + "Then move the Probes using the FFI Photonic Interface to place it exaclty above the grating couplers.", + "task_move_chuck*") + layout.addWidget(task_move_chuck) + layout.addWidget(self.add_graphics(path=f'{self.imgf}/Step2_1.png')) + + # ============================================================================================================== + task_area_scan, self.cb_area_scan = self.add_task( + "2. Perform an 'Area Scan'", + "If the Probes are moved, perform an 'Area Scan' to find the best position of the probes." + "The program may freez during the area scan.", + "task_area_scan*") + self.cb_area_scan.setCheckable(True) + layout.addWidget(task_area_scan) + self.btn_area_scan = QPushButton('Perform Area Scan (Input/Output)') + self.txt_coupled_power = QLabel('In: N/A, Out:N/A - Not performed.') + layout.addWidget(self.btn_area_scan) + layout.addWidget(self.txt_coupled_power) + self.btn_area_scan.clicked.connect(lambda: self.area_scan(self.txt_coupled_power, self.cb_area_scan)) + + self.setLayout(layout) + diff --git a/src/FlexSensor/InitialSetupWizard/pages/ThirdPage.py b/src/FlexSensor/InitialSetupWizard/pages/ThirdPage.py new file mode 100644 index 0000000000000000000000000000000000000000..52982499b43fc5f72998ba6e7200994eb4f0dbce --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/ThirdPage.py @@ -0,0 +1,76 @@ +from PySide6.QtWidgets import QGridLayout, QLabel, QLineEdit, QPushButton, QLineEdit + +import Prober as Prober +from InitialSetupWizard.pages.WizardPage import WizardPage + + +class ThirdWizardPage(WizardPage): + def __init__(self, prober: Prober.Controller, parent=None): + super().__init__(prober, parent) + + self.setTitle("Selecting the reference structure.") + layout = QGridLayout() + # ============================================================================================================== + task_moved_to_ref_structure, _ = self.add_task( + "1. Place the Scope over the Input Probe.", + "Try to match the center point using the scope's cross. It is useful to set the scope home position to the" + "current position.", "task_moved_scope*") + + layout.addWidget(task_moved_to_ref_structure, 0, 0, 1, 4) + graphics1 = self.add_graphics(f'{self.imgf}/Step2_1.png') + layout.addWidget(graphics1, 1, 0, 1, 4) + + # ============================================================================================================== + task_move_to_home, _ = self.add_task( + "2. Move back to the zero position", + "Move back to the 'zero' point. This point is your arbitrarily chosen reference point and must be the same " + "in your layout file and the prober. Usually a mark or the die's corner is used, however not mandatory.\n" + "Input the X and y distance from the calibration structure to the 'zero' point. Make sure to have the " + "signs correct.", + "task_set_chuck_home_position*") + layout.addWidget(task_move_to_home, 2, 0, 1, 4) + # Input the X and y distance from the calibration structure to the Home Position + graphics1 = self.add_graphics(f'{self.imgf}/Step2_2.png', max_width=400) + layout.addWidget(graphics1, 3, 0, 1, 4) + self.lbl_movement_x = QLabel("X Movement: ") + self.input_movement_x = QLineEdit("-950") + + layout.addWidget(self.lbl_movement_x, 4, 0) + layout.addWidget(self.input_movement_x, 4, 1) + + self.input_movement_y = QLabel("Y Movement: ") + self.lbl_movement_y = QLineEdit("2120") + layout.addWidget(self.input_movement_y, 4, 2) + layout.addWidget(self.lbl_movement_y, 4, 3) + + self.btn_move_to_home = QPushButton('Move chuck') + layout.addWidget(self.btn_move_to_home, 5, 0, 1, 4) + self.btn_move_to_home.clicked.connect( + lambda: self.move_chuck_x_y(int(self.input_movement_x.text()), int(self.lbl_movement_y.text()))) + + # ============================================================================================================== + task_set_chuck_home_position, _ = self.add_task( + "3. Set Chuck Home position", + "Use the 'Set to Current Position' to the left to reset the prober's coordinates to (0,0,Z)", + "task_set_chuck_home_position*") + layout.addWidget(task_set_chuck_home_position, 6, 0, 1, 4) + # layout.addWidget(self.add_graphics(path=f'{self.imgf}/1_placed_at_origin_cut.JPG'), 7, 0, 1, 4) + self.btn_move_to_home = QPushButton('Set chuck Home') + layout.addWidget(self.btn_move_to_home, 7, 0, 1, 4) + self.btn_move_to_home.clicked.connect(lambda: self.prober.set_chuck_home()) + + self.setLayout(layout) + + # def get_distance(self) -> float: + # value = self.input_distance.text() + # try: + # distance = int(value) + # except Exception as e: + # self.logger.error(f"Can't convert {value} to int!") + # raise e + # return distance + # + # def move_chuck(self): + # distance = self.get_distance() + # distance_half = int(distance / 2) + # self.move_chuck_x_y(x=-distance_half, y=0) diff --git a/src/FlexSensor/InitialSetupWizard/pages/WizardPage.py b/src/FlexSensor/InitialSetupWizard/pages/WizardPage.py new file mode 100644 index 0000000000000000000000000000000000000000..46e10f4d14401a3e1ff9ffeed9ef3d73169663df --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/WizardPage.py @@ -0,0 +1,146 @@ +import logging +import pathlib + +import numpy as np +from PySide6 import QtGui +from PySide6.QtCore import QSize, Qt +from PySide6.QtGui import QPixmap +from PySide6.QtWidgets import QWizardPage, QLabel, QWidget, QCheckBox, QVBoxLayout, QMessageBox, QSizePolicy + +import Prober as Prober +from pathes import image_root + + +class WizardPage(QWizardPage): + def __init__(self, prober: Prober.Controller, parent=None): + super().__init__(parent) + self.parent = parent + self.prober = prober + self.logger = logging.getLogger('Wizard') + + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + #self.parent.setMinimumWidth(780) + self.parent.setMaximumHeight(900) + self.parent.setMinimumHeight(900) + + self.imgf = f"{image_root}/wizard_img" + + # Stores all included graphics for later accessing via the resize Event + self.graphics = [] + + # ================================================================================================================== + # For adding UI Elements + # ================================================================================================================== + def add_graphics(self, path, max_width=None): + print(f"Added {path}") + graphics = QLabel(self) + pixmap = QPixmap(str(pathlib.PurePosixPath(path))) + self._resize_graphics_on_resize_event(graphics, pixmap, max_width=max_width) + self.graphics.append({"graphics": graphics, "pixmap": pixmap}) + return graphics + + def add_task(self, title, description, task_desc) -> (QWidget, QCheckBox): + widget = QWidget() + layout = QVBoxLayout() + widget.setLayout(layout) + + task = QCheckBox(title) + task.setStyleSheet( + "QCheckBox:unchecked{ color: red; }QCheckBox:checked{ color: black; }") + label = QLabel(description) + label.setWordWrap(True) + layout.addWidget(task) + layout.addWidget(label) + self.registerField(task_desc, task) + return widget, task + + # ================================================================================================================== + # Message Boxes + # ================================================================================================================== + def display_mbox_warning(self, text, title): + self.logger.warning(text) + warning_dialog = QMessageBox() + warning_dialog.setText(text) + warning_dialog.setIcon(QMessageBox.Warning) + warning_dialog.setWindowTitle(title) + warning_dialog.show() + warning_dialog.setStandardButtons(QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Abort) + btn_ok = warning_dialog.button(QMessageBox.StandardButton.Ok) + btn_abort = warning_dialog.button(QMessageBox.StandardButton.Abort) + warning_dialog.exec() + if warning_dialog.clickedButton() == btn_ok: + return True + elif warning_dialog.clickedButton() == btn_abort: + return False + + def display_mbox_error(self, text, title): + self.logger.error(text) + warning_dialog = QMessageBox() + warning_dialog.setText(text) + warning_dialog.setIcon(QMessageBox.Critical) + warning_dialog.setWindowTitle(title) + warning_dialog.show() + warning_dialog.exec() + + def display_mbox_ok(self, text, title): + self.logger.error(text) + warning_dialog = QMessageBox() + warning_dialog.setText(text) + warning_dialog.setIcon(QMessageBox.Information) + warning_dialog.setWindowTitle(title) + warning_dialog.show() + warning_dialog.exec() + + # ================================================================================================================== + # Prober Controls + # ================================================================================================================== + def move_chuck_x_y(self, x, y): + if self.display_mbox_warning(f"The chuck is about to move relatively {x} in x-direction und {y} y-direction. " + f"Continue?", + "Move chuck"): + self.prober.move_chuck(x_value=x, y_value=y, pos_ref="R") + # Enable the next button when the user has entered a non-empty + # string. + # self.cb_distance_enterd.setCheckable(True) + # self.cb_distance_enterd.setChecked(True) + self.completeChanged.emit() + else: + self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") + return + + def area_scan(self, txt_coupled_power: QLabel, checkbox: QCheckBox, threshold: float = -70): + x_1, x_2, y_1, y_2, input_power, output_power = self.prober.opt_if.area_scan(True, True) + if input_power > threshold and output_power > threshold: + checkbox.setCheckable(True) + checkbox.setChecked(True) + # self.distance_task.setCheckable(False) + txt_coupled_power.setText(f'In: {input_power}, Out: {output_power} - Passed/Threshold < -70dB.') + self.completeChanged.emit() + else: + txt_coupled_power.setText(f'In: {input_power}, Out: {output_power} - Not passed/Threshold < -70dB.') + + def move_input_probes_x_y(self, x: float, y: float): + self.prober.opt_if.move_optical_probe(0, x, y, pos_ref='R') + + def move_output_probes_x_y(self, x: float, y: float): + self.prober.opt_if.move_optical_probe(1, x, y, pos_ref='R') + + # ================================================================================================================== + # + # ================================================================================================================== + def _resize_graphics_on_resize_event(self, graphics, pixmap, max_width=None): + + aspect_ratio = pixmap.height() / pixmap.width() + if max_width is None: + max_width = int(self.parent.width()*0.95) + max_height = np.floor(aspect_ratio * max_width) + # print(f"{aspect_ratio}: {max_width}x{max_height} - {max_height / max_width}") + + graphics.setPixmap(pixmap.scaled(QSize(max_width, max_height), + Qt.AspectRatioMode.KeepAspectRatio, + Qt.SmoothTransformation)) + + def resizeEvent(self, event: QtGui.QResizeEvent) -> None: + # print(self.graphics) + for ele in self.graphics: + self._resize_graphics_on_resize_event(ele['graphics'], ele['pixmap']) diff --git a/src/FlexSensor/InitialSetupWizard/pages/tmp.txt b/src/FlexSensor/InitialSetupWizard/pages/tmp.txt new file mode 100644 index 0000000000000000000000000000000000000000..24c71afe88dd6af291a554f0974f24ced2974318 --- /dev/null +++ b/src/FlexSensor/InitialSetupWizard/pages/tmp.txt @@ -0,0 +1,25 @@ +task_move_chuck, _ = self.add_task( + "1. Move chuck to the 'mark'", + "Use the same 'mark' in the Klayout file and on the wafer. Usually the die's edge is " + "a good point. Move your chuck, thus the yellow cross precisely matches " + "the selected mark.", "task_move_chuck*") +layout.addWidget(task_move_chuck) + + + + + + +task_set_chuck_home_position, _ = self.add_task( + "2. Set Chuck Home position", + "Use the 'Set to Current Position' to the left to reset the " + "prober's coordinates to (0,0,Z)", + "task_set_chuck_home_position*") +layout.addWidget(task_set_chuck_home_position) +layout.addWidget(self.add_graphics(path=f'{self.imgf}/1_placed_at_origin_cut.JPG')) + + + +label2 = QLabel("The Prober's coordinates are now at zero.") +label2.setWordWrap(True) +layout.addWidget(label2) \ No newline at end of file diff --git a/src/FlexSensor/MainWindow/__init__.py b/src/FlexSensor/MainWindow/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/controller/MainThreadController.py b/src/FlexSensor/MainWindow/controller/MainThreadController.py new file mode 100644 index 0000000000000000000000000000000000000000..47a94951948b33be77f76d7a86bf3829c8b509b7 --- /dev/null +++ b/src/FlexSensor/MainWindow/controller/MainThreadController.py @@ -0,0 +1,99 @@ +import logging + +from PySide6.QtCore import QThread + +import ConfigHandler as Config +import Laser as Laser +import AD2CaptDevice as AD2Dev +import Prober as Prober +import MeasurementEvaluationTool + +from MainWindow.model.MainThreadModel import MainThreadModel +from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine +from Prober.controller.ProberController import ProberController + + +class MainThreadController(object): + def __init__(self, model: MainThreadModel): + self.logger = logging.getLogger("MainThread") + self._model = model + + # self.model._laser_controller.connect_device(self._vaut_config.laser_config.get_port()) + + mypath = ( + r'F:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement') + + # Device init: Connect signals and slots + self._device_initialization() + + # Load the measurement routine + self.model.measurement_routine = self._load_measurement_routine() + + # Thread for the measurement routine + self.measurement_thread = QThread() + + # Create the working folders + self._create_working_folders() + + @property + def model(self) -> MainThreadModel: + return self._model + + def start_measurement_routine(self): + # 1. Create all working folders + self._create_working_folders() + self._move_measurement_routine_thread(self.model.measurement_routine) + self.measurement_thread.start() + self.logger.info("Started worker thread for running the measurement routine.") + + if self.measurement_thread.isRunning(): + self.logger.debug("Thread is running.") + + def _create_working_folders(self): + """Creates all working folders to store the measurement data. + """ + self.model.vaut_config.setup_folders() + + def _move_measurement_routine_thread(self, measurement_routine): + measurement_routine.moveToThread(self.measurement_thread) + self.measurement_thread.started.connect(measurement_routine.run) + self.logger.debug("Moved worker/measurement routine to thread and connected the signals.") + + + def _load_measurement_routine(self) -> MeasurementRoutine: + """ + Loads the measurement routine and initializes it. + + Returns: + MeasurementRoutine: The measurement routine. + + Raises: + Exception: If some or all devices have not been initialized. + """ + if not self.device_are_init: + raise Exception("Some or all devices have not been initialized. First call `_device_initialization()`!") + + measurement_routine = MeasurementRoutine( + self.model.laser_controller, + self.model.ad2_controller, + self.model.prober_controller, + self.model.vaut_config) + self.logger.debug("Initialized MeasurementRoutine.") + return measurement_routine + + def _device_initialization(self): + """ + Initializes all devices and connects the signals and slots. + """ + self.model.ad2_controller.connect_device(0) + # # Connect the required signals and slots + # self.model.laser_model.signals.laser_ready_for_sweep_changed.connect( + # self.model.ad2_controller.start_capture_flag) + # + # self.model.ad2_model.signals.device_ready_changed.connect( + # self.model.laser_controller.start_wavelength_sweep) + # + # self.model.laser_model.signals.wavelength_sweep_running_changed.connect( + # self.model.ad2_controller.set_ad2_acq_status) + + self.device_are_init = True diff --git a/src/FlexSensor/MainWindow/controller/__init__.py b/src/FlexSensor/MainWindow/controller/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/model/MainThreadModel.py b/src/FlexSensor/MainWindow/model/MainThreadModel.py new file mode 100644 index 0000000000000000000000000000000000000000..0c4a7c9aace1588fe6bd8d7dac3de035088606df --- /dev/null +++ b/src/FlexSensor/MainWindow/model/MainThreadModel.py @@ -0,0 +1,170 @@ +from PySide6.QtCore import QObject, Signal + +import Laser as Laser +import AD2CaptDevice as AD2Dev +import Prober as Prober +import MeasurementEvaluationTool as met +import ConfigHandler as Config +from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine + + +class MainThreadSignals(QObject): + # Signals for the main thread + vaut_config_changed = Signal(Config.VAutomatorConfig) + laser_changed = Signal(Laser.Model, Laser.Controller, Laser.ControlWindow) + ad2_changed = Signal(AD2Dev.Model, AD2Dev.Controller, AD2Dev.ControlWindow) + prober_changed = Signal(Prober.Model, Prober.Controller, Prober.ControlWindow) + + measurement_routine_changed = Signal(MeasurementRoutine) + +class MainThreadModel(QObject): + + def __init__(self, vaut_config: Config.VAutomatorConfig): + super().__init__() + + self.signals = MainThreadSignals() + + self._vaut_config: Config.VAutomatorConfig = vaut_config + + self._measurement_routine: MeasurementRoutine = None + + + + self._ad2_model: AD2Dev.Model = AD2Dev.Model(self.vaut_config.ad2_device_config) + self._ad2_controller: AD2Dev.Controller = AD2Dev.Controller( + self._ad2_model) + self._ad2_window: AD2Dev.ControlWindow = AD2Dev.ControlWindow( + self._ad2_model, self._ad2_controller) + + # Devices + self._laser_model: Laser.Model = Laser.Model(self.vaut_config.laser_config) + self._laser_controller: Laser.Controller = Laser.Controller(self._laser_model, self._ad2_controller) + + self._laser_window: Laser.ControlWindow = Laser.ControlWindow( + self._laser_model, + self._laser_controller) + + self._prober_model: Prober.Model = Prober.Model() + self._prober_controller: Prober.Controller = Prober.Controller( + self._prober_model, + self.vaut_config) + self._prober_window: Prober.ControlWindow = Prober.ControlWindow( + self._prober_model, + self._prober_controller) + + # Widgets + self.mea_eval_tool_model: met.Model = met.Model() + self.mea_eval_tool_controller: met.Controller = met.Controller( + self.mea_eval_tool_model) + self.mea_eval_tool_window: met.View = met.View( + self.mea_eval_tool_model, + self.mea_eval_tool_controller) + + # Implement all getter and setter methods for the model here + @property + def vaut_config(self) -> Config.VAutomatorConfig: + return self._vaut_config + + @vaut_config.setter + def vaut_config(self, value: Config.VAutomatorConfig): + self._vaut_config = value + self.signals.vaut_config_changed.emit(self.vaut_config) + + @property + def laser_model(self) -> Laser.Model: + return self._laser_model + + @laser_model.setter + def laser_model(self, value: Laser.Model): + self._laser_model = value + self.signals.laser_changed.emit(self.laser_model, self.laser_controller, self.laser_window) + + + @property + def laser_controller(self) -> Laser.Controller: + return self._laser_controller + + @laser_controller.setter + def laser_controller(self, value: Laser.Controller): + self._laser_controller = value + self.signals.laser_changed.emit(self.laser_model, self.laser_controller, self.laser_window) + + @property + def laser_window(self) -> Laser.ControlWindow: + return self._laser_window + + @laser_window.setter + def laser_window(self, value: Laser.ControlWindow): + self._laser_window = value + self.signals.laser_changed.emit(self.laser_model, self.laser_controller, self.laser_window) + + + @property + def ad2_model(self) -> AD2Dev.Model: + return self._ad2_model + + @ad2_model.setter + def ad2_model(self, value: AD2Dev.Model): + self._ad2_model = value + self.signals.ad2_changed.emit(self.ad2_model, self.ad2_controller, self.ad2_window) + + @property + def ad2_controller(self) -> AD2Dev.Controller: + return self._ad2_controller + + @ad2_controller.setter + def ad2_controller(self, value: AD2Dev.Controller): + self._ad2_controller = value + self.signals.ad2_changed.emit(self.ad2_model, self.ad2_controller, self.ad2_window) + + @property + def ad2_window(self) -> AD2Dev.ControlWindow: + return self._ad2_window + + @ad2_window.setter + def ad2_window(self, value: AD2Dev.ControlWindow): + self._ad2_window = value + self.signals.ad2_changed.emit(self.ad2_model, self.ad2_controller, self.ad2_window) + + @property + def prober_model(self) -> Prober.Model: + return self._prober_model + + @prober_model.setter + def prober_model(self, value: Prober.Model): + self._prober_model = value + self.signals.prober_changed.emit(self.prober_model, self.prober_controller, self.prober_window) + + @property + def prober_controller(self) -> Prober.Controller: + return self._prober_controller + + @prober_controller.setter + def prober_controller(self, value: Prober.Controller): + self._prober_controller = value + self.signals.prober_changed.emit(self.prober_model, self.prober_controller, self.prober_window) + + @property + def prober_window(self) -> Prober.ControlWindow: + return self._prober_window + + @prober_window.setter + def prober_window(self, value: Prober.ControlWindow): + self._prober_window = value + self.signals.prober_changed.emit(self.prober_model, self.prober_controller, self.prober_window) + + + @property + def measurement_routine(self) -> MeasurementRoutine: + return self._measurement_routine + + @measurement_routine.setter + def measurement_routine(self, value: MeasurementRoutine): + self._measurement_routine = value + self.signals.measurement_routine_changed.emit(self.measurement_routine) + + + + + + diff --git a/src/FlexSensor/MainWindow/model/__init__.py b/src/FlexSensor/MainWindow/model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/resources/MainView.ui b/src/FlexSensor/MainWindow/resources/MainView.ui new file mode 100644 index 0000000000000000000000000000000000000000..3cb89cb8e02edb91db7c753b193dfc886fd4d7a0 --- /dev/null +++ b/src/FlexSensor/MainWindow/resources/MainView.ui @@ -0,0 +1,2608 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <author>Wanderson M. Pimenta</author> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1085</width> + <height>753</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>940</width> + <height>560</height> + </size> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <property name="toolTipDuration"> + <number>-9</number> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <widget class="QWidget" name="styleSheet"> + <property name="maximumSize"> + <size> + <width>16777214</width> + <height>16777215</height> + </size> + </property> + <property name="toolTipDuration"> + <number>0</number> + </property> + <property name="styleSheet"> + <string notr="true">/* ///////////////////////////////////////////////////////////////////////////////////////////////// + +SET APP STYLESHEET - FULL STYLES HERE +DARK THEME - DRACULA COLOR BASED + +///////////////////////////////////////////////////////////////////////////////////////////////// */ + +QWidget{ + color: rgb(221, 221, 221); + font: 10pt "Segoe UI"; +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Tooltip */ +QToolTip { + color: #ffffff; + background-color: rgba(33, 37, 43, 180); + border: 1px solid rgb(44, 49, 58); + background-image: none; + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 2px solid rgb(255, 121, 198); + text-align: left; + padding-left: 8px; + margin: 0px; +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Bg App */ +#bgApp { + background-color: rgb(40, 44, 52); + border: 1px solid rgb(44, 49, 58); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Left Menu */ +#leftMenuBg { + background-color: rgb(33, 37, 43); +} +#topLogo { + background-color: rgb(33, 37, 43); + border-image: url(:/images/images/images/FlexSensorIcon.png) 10 0 0 0 strech strech; + background-position: centered; + background-repeat: no-repeat; +} +#titleLeftApp { font: 63 12pt "Segoe UI Semibold"; } +#titleLeftDescription { font: 8pt "Segoe UI"; color: rgb(189, 147, 249); } + +/* MENUS */ + + + +#topMenu .QPushButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 22px solid transparent; + background-color: transparent; + text-align: left; + padding-left: 44px; +} +#topMenu .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#topMenu .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} +#bottomMenu .QPushButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 20px solid transparent; + background-color:transparent; + text-align: left; + padding-left: 44px; +} +#bottomMenu .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#bottomMenu .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} +#leftMenuFrame{ + border-top: 3px solid rgb(44, 49, 58); +} + +/* Toggle Button */ +#toggleButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 20px solid transparent; + background-color: rgb(37, 41, 48); + text-align: left; + padding-left: 44px; + color: rgb(113, 126, 149); +} +#toggleButton:hover { + background-color: rgb(40, 44, 52); +} +#toggleButton:pressed { + background-color: rgb(189, 147, 249); +} + +/* Title Menu */ +/*#titleRightInfo { padding-left: 10px; }*/ + + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Extra Tab */ +#extraLeftBox { + background-color: rgb(44, 49, 58); +} +#extraTopBg{ + background-color: rgb(189, 147, 249) +} + +/* Icon */ +#extraIcon { + background-position: center; + background-repeat: no-repeat; + background-image: url(:/icons/images/icons/icon_settings.png); +} + +/* Label */ +#extraLabel { color: rgb(255, 255, 255); } + +/* Btn Close */ +#extraCloseColumnBtn { background-color: rgba(255, 255, 255, 0); border: none; border-radius: 5px; } +#extraCloseColumnBtn:hover { background-color: rgb(196, 161, 249); border-style: solid; border-radius: 4px; } +#extraCloseColumnBtn:pressed { background-color: rgb(180, 141, 238); border-style: solid; border-radius: 4px; } + +/* Extra Content */ +#extraContent{ + border-top: 3px solid rgb(40, 44, 52); +} + +/* Extra Top Menus */ +#extraTopMenu .QPushButton { + /*background-position: left center;*/ + background-repeat: no-repeat; + border: none; + border-left: 22px solid transparent; + background-color:transparent; + text-align: left; + padding-left: 44px; +} +#extraTopMenu .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#extraTopMenu .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + + + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Content App */ +#contentTopBg{ + background-color: rgb(33, 37, 43); +} +#contentBottom{ + border-top: 3px solid rgb(44, 49, 58); +} + +/* Top Buttons */ +#rightButtons .QPushButton { background-color: rgba(255, 255, 255, 0); border: none; border-radius: 5px; } +#rightButtons .QPushButton:hover { background-color: rgb(44, 49, 57); border-style: solid; border-radius: 4px; } +#rightButtons .QPushButton:pressed { background-color: rgb(23, 26, 30); border-style: solid; border-radius: 4px; } + +/* Theme Settings */ +#extraRightBox { background-color: rgb(44, 49, 58); } +#themeSettingsTopDetail { background-color: rgb(189, 147, 249); } + +/* Bottom Bar */ +#bottomBar { background-color: rgb(44, 49, 58); } +#bottomBar QLabel { font-size: 11px; color: rgb(113, 126, 149); padding-left: 10px; padding-right: 10px; padding-bottom: 2px; } + +/* CONTENT SETTINGS */ +/* MENUS */ +#contentSettings .QPushButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 22px solid transparent; + background-color:transparent; + text-align: left; + padding-left: 44px; +} +#contentSettings .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#contentSettings .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +QTableWidget */ +QTableWidget { + background-color: transparent; + padding: 10px; + border-radius: 5px; + gridline-color: rgb(44, 49, 58); + border-bottom: 1px solid rgb(44, 49, 60); +} +QTableWidget::item{ + border-color: rgb(44, 49, 60); + padding-left: 5px; + padding-right: 5px; + gridline-color: rgb(44, 49, 60); +} +QTableWidget::item:selected{ + background-color: rgb(189, 147, 249); +} +QHeaderView::section{ + background-color: rgb(33, 37, 43); + max-width: 30px; + border: 1px solid rgb(44, 49, 58); + border-style: none; + border-bottom: 1px solid rgb(44, 49, 60); + border-right: 1px solid rgb(44, 49, 60); +} +QTableWidget::horizontalHeader { + background-color: rgb(33, 37, 43); +} +QHeaderView::section:horizontal +{ + border: 1px solid rgb(33, 37, 43); + background-color: rgb(33, 37, 43); + padding: 3px; + border-top-left-radius: 7px; + border-top-right-radius: 7px; +} +QHeaderView::section:vertical +{ + border: 1px solid rgb(44, 49, 60); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +LineEdit */ +QLineEdit { + background-color: rgb(33, 37, 43); + border-radius: 5px; + border: 2px solid rgb(33, 37, 43); + padding-left: 10px; + selection-color: rgb(255, 255, 255); + selection-background-color: rgb(255, 121, 198); +} +QLineEdit:hover { + border: 2px solid rgb(64, 71, 88); +} +QLineEdit:focus { + border: 2px solid rgb(91, 101, 124); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +PlainTextEdit */ +QPlainTextEdit { + background-color: rgb(27, 29, 35); + border-radius: 5px; + padding: 10px; + selection-color: rgb(255, 255, 255); + selection-background-color: rgb(255, 121, 198); +} +QPlainTextEdit QScrollBar:vertical { + width: 8px; + } +QPlainTextEdit QScrollBar:horizontal { + height: 8px; + } +QPlainTextEdit:hover { + border: 2px solid rgb(64, 71, 88); +} +QPlainTextEdit:focus { + border: 2px solid rgb(91, 101, 124); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +ScrollBars */ +QScrollBar:horizontal { + border: none; + background: rgb(52, 59, 72); + height: 8px; + margin: 0px 21px 0 21px; + border-radius: 0px; +} +QScrollBar::handle:horizontal { + background: rgb(189, 147, 249); + min-width: 25px; + border-radius: 4px +} +QScrollBar::add-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + subcontrol-position: right; + subcontrol-origin: margin; +} +QScrollBar::sub-line:horizontal { + border: none; + background: rgb(55, 63, 77); + width: 20px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + subcontrol-position: left; + subcontrol-origin: margin; +} +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal +{ + background: none; +} +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ + background: none; +} + QScrollBar:vertical { + border: none; + background: rgb(52, 59, 72); + width: 8px; + margin: 21px 0 21px 0; + border-radius: 0px; + } + QScrollBar::handle:vertical { + background: rgb(189, 147, 249); + min-height: 25px; + border-radius: 4px + } + QScrollBar::add-line:vertical { + border: none; + background: rgb(55, 63, 77); + height: 20px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + subcontrol-position: bottom; + subcontrol-origin: margin; + } + QScrollBar::sub-line:vertical { + border: none; + background: rgb(55, 63, 77); + height: 20px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + subcontrol-position: top; + subcontrol-origin: margin; + } + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; + } + + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; + } + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +CheckBox */ +QCheckBox::indicator { + border: 3px solid rgb(52, 59, 72); + width: 15px; + height: 15px; + border-radius: 10px; + background: rgb(44, 49, 60); +} +QCheckBox::indicator:hover { + border: 3px solid rgb(58, 66, 81); +} +QCheckBox::indicator:checked { + background: 3px solid rgb(52, 59, 72); + border: 3px solid rgb(52, 59, 72); + background-image: url(:/icons/images/icons/cil-check-alt.png); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +RadioButton */ +QRadioButton::indicator { + border: 3px solid rgb(52, 59, 72); + width: 15px; + height: 15px; + border-radius: 10px; + background: rgb(44, 49, 60); +} +QRadioButton::indicator:hover { + border: 3px solid rgb(58, 66, 81); +} +QRadioButton::indicator:checked { + background: 3px solid rgb(94, 106, 130); + border: 3px solid rgb(52, 59, 72); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +ComboBox */ +QComboBox{ + background-color: rgb(27, 29, 35); + border-radius: 5px; + border: 2px solid rgb(33, 37, 43); + padding: 5px; + padding-left: 10px; +} +QComboBox:hover{ + border: 2px solid rgb(64, 71, 88); +} +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 25px; + border-left-width: 3px; + border-left-color: rgba(39, 44, 54, 150); + border-left-style: solid; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + background-image: url(:/icons/images/icons/cil-arrow-bottom.png); + background-position: center; + background-repeat: no-reperat; + } +QComboBox QAbstractItemView { + color: rgb(255, 121, 198); + background-color: rgb(33, 37, 43); + padding: 10px; + selection-background-color: rgb(39, 44, 54); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Sliders */ +QSlider::groove:horizontal { + border-radius: 5px; + height: 10px; + margin: 0px; + background-color: rgb(52, 59, 72); +} +QSlider::groove:horizontal:hover { + background-color: rgb(55, 62, 76); +} +QSlider::handle:horizontal { + background-color: rgb(189, 147, 249); + border: none; + height: 10px; + width: 10px; + margin: 0px; + border-radius: 5px; +} +QSlider::handle:horizontal:hover { + background-color: rgb(195, 155, 255); +} +QSlider::handle:horizontal:pressed { + background-color: rgb(255, 121, 198); +} + +QSlider::groove:vertical { + border-radius: 5px; + width: 10px; + margin: 0px; + background-color: rgb(52, 59, 72); +} +QSlider::groove:vertical:hover { + background-color: rgb(55, 62, 76); +} +QSlider::handle:vertical { + background-color: rgb(189, 147, 249); + border: none; + height: 10px; + width: 10px; + margin: 0px; + border-radius: 5px; +} +QSlider::handle:vertical:hover { + background-color: rgb(195, 155, 255); +} +QSlider::handle:vertical:pressed { + background-color: rgb(255, 121, 198); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +CommandLinkButton */ +QCommandLinkButton { + color: rgb(255, 121, 198); + border-radius: 5px; + padding: 5px; + color: rgb(255, 170, 255); +} +QCommandLinkButton:hover { + color: rgb(255, 170, 255); + background-color: rgb(44, 49, 60); +} +QCommandLinkButton:pressed { + color: rgb(189, 147, 249); + background-color: rgb(52, 58, 71); +} + +/* ///////////////////////////////////////////////////////////////////////////////////////////////// +Button */ +#pagesContainer QPushButton { + border: 2px solid rgb(52, 59, 72); + border-radius: 5px; + background-color: rgb(52, 59, 72); +} +#pagesContainer QPushButton:hover { + background-color: rgb(57, 65, 80); + border: 2px solid rgb(61, 70, 86); +} +#pagesContainer QPushButton:pressed { + background-color: rgb(35, 40, 49); + border: 2px solid rgb(43, 50, 61); +} + + + + + + + + + + + + +QToolButton { +border-image: url(:/img/btn_mid_0.png); +text-align: center; +} +QToolButton::menu-indicator { image: none; } + + +#menuBar .QPushButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + /*border-left: 22px solid transparent;*/ + /*text-align: center;*/ + padding-right: 10px; +} +#menuBar .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#menuBar .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + +#menuBar .QToolButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + /*border-left: 22px solid transparent;*/ + /*text-align: center;*/ + padding-right: 10px; +} +#menuBar .QToolButton:hover { + background-color: rgb(40, 44, 52); +} +#menuBar .QToolButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + + +#extraMenuBar .QToolButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + /*border-left: 22px solid transparent;*/ + /*text-align: center;*/ + padding-right: 10px; +} +#extraMenuBar .QToolButton:hover { + background-color: rgb(40, 44, 52); +} +#extraMenuBar .QToolButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + + +#extraMenuBar .QPushButton { + /*background-position: left center;*/ + background-repeat: no-repeat; + border: none; + border-left: 22px solid transparent; + text-align: center; + /*padding-left: 44px;*/ +} +#extraMenuBar .QPushButton:hover { + background-color: rgb(40, 44, 52); +} +#extraMenuBar .QPushButton:pressed { + background-color: rgb(189, 147, 249); + color: rgb(255, 255, 255); +} + + + + +/* QMenu ------------------------------------------------------------------ + +examples: https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + background-color: rgb(40, 44, 52); + margin: 2px; /* some spacing around the menu */ +} + +QMenu::item { + padding: 2px 25px 2px 20px; + border: 1px solid transparent; /* reserve space for selection border */ +} + +QMenu::item:selected { + border-color: darkblue; + background: rgba(100, 100, 100, 150); +} + +QMenu::icon:checked { /* appearance of a 'checked' icon */ + background: gray; + border: 1px inset gray; + position: absolute; + top: 1px; + right: 1px; + bottom: 1px; + left: 1px; +} + +QMenu::separator { + height: 2px; + background: lightblue; + margin-left: 10px; + margin-right: 5px; +} + +QMenu::indicator { + width: 13px; + height: 13px; +} + +/* + +QMenu::indicator:non-exclusive:unchecked { + image: url(:/images/checkbox_unchecked.png); +} + +QMenu::indicator:non-exclusive:unchecked:selected { + image: url(:/images/checkbox_unchecked_hover.png); +} + +QMenu::indicator:non-exclusive:checked { + image: url(:/images/checkbox_checked.png); +} + +QMenu::indicator:non-exclusive:checked:selected { + image: url(:/images/checkbox_checked_hover.png); +} + + +QMenu::indicator:exclusive:unchecked { + image: url(:/images/radiobutton_unchecked.png); +} + +QMenu::indicator:exclusive:unchecked:selected { + image: url(:/images/radiobutton_unchecked_hover.png); +} + +QMenu::indicator:exclusive:checked { + image: url(:/images/radiobutton_checked.png); +} + +QMenu::indicator:exclusive:checked:selected { + image: url(:/images/radiobutton_checked_hover.png); +}*/ + +QTabWidget::pane { + border: 1px solid lightgray; + top:-1px; + background: rgb(40, 44, 52); +} + +QTabBar::tab { + background: rgb(40, 44, 52);; + border: 1px solid lightgray; + padding: 2px; + padding-left: 10px; + padding-right: 10px; +} + +QTabBar::tab:selected { + background: rgb(189, 147, 249); + margin-bottom: -1px; +}</string> + </property> + <layout class="QVBoxLayout" name="appMargins"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="topMargin"> + <number>10</number> + </property> + <property name="rightMargin"> + <number>10</number> + </property> + <property name="bottomMargin"> + <number>10</number> + </property> + <item> + <widget class="QFrame" name="bgApp"> + <property name="toolTipDuration"> + <number>0</number> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <layout class="QHBoxLayout" name="appLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="leftMenuBg"> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>60</width> + <height>16777215</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="topLogoInfo"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>50</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <widget class="QLabel" name="titleLeftApp"> + <property name="geometry"> + <rect> + <x>60</x> + <y>3</y> + <width>160</width> + <height>20</height> + </rect> + </property> + <property name="font"> + <font> + <pointsize>12</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>PyDracula</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + <widget class="QFrame" name="topLogo"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>32</width> + <height>32</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QLabel" name="titleLeftDescription"> + <property name="geometry"> + <rect> + <x>60</x> + <y>22</y> + <width>160</width> + <height>16</height> + </rect> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>8</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Modern GUI / Flat Style</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QFrame" name="leftMenuFrame"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="toolTipDuration"> + <number>0</number> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalMenuLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="toggleBox"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>45</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="toggleButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/icon_menu.png);</string> + </property> + <property name="text"> + <string>Hide</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="topMenu"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>10</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="btn_start_measuring_routine"> + <property name="minimumSize"> + <size> + <width>60</width> + <height>60</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16660</width> + <height>60</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { + background-position: left center; + background-repeat: no-repeat; + border: none; + border-left: 22px solid transparent; + background-color: rgb(36, 209, 21); + text-align: left; + padding-left: 44px; + background-image: url(:/icons/images/icons/cil-media-play.png); +} + +QPushButton:hover { + background-color: rgb(26, 153, 16); +} + +QPushButton:pressed { + background-color: rgb(20, 120, 12); + color: rgb(255, 255, 255); +} + + +</string> + </property> + <property name="text"> + <string>PushButton</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_home"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-home.png);</string> + </property> + <property name="text"> + <string>Home</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_adc_control"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-signal-cellular-3.png);</string> + </property> + <property name="text"> + <string>ADC Control</string> + </property> + <property name="iconSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_laser_control"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-lightbulb.png);</string> + </property> + <property name="text"> + <string>Laser Control</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_probe_control"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-action-redo.png);</string> + </property> + <property name="text"> + <string>Probe Control</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_measured_data"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-description.png);</string> + </property> + <property name="text"> + <string>Measured Data</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_exit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>60</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-x.png);</string> + </property> + <property name="text"> + <string>Exit</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="bottomMenu"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_9"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="toggleLeftBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/icon_settings.png);</string> + </property> + <property name="text"> + <string>Left Box</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="extraLeftBox"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>0</width> + <height>16777215</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <layout class="QVBoxLayout" name="extraColumLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="extraTopBg"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>50</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout" name="extraTopLayout"> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="rightMargin"> + <number>10</number> + </property> + <property name="horizontalSpacing"> + <number>10</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QFrame" name="extraIcon"> + <property name="minimumSize"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="extraLabel"> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>Left Box</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="extraCloseColumnBtn"> + <property name="minimumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Close left box</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../resources.qrc"> + <normaloff>:/icons/images/icons/icon_close.png</normaloff>:/icons/images/icons/icon_close.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="extraContent"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item alignment="Qt::AlignTop"> + <widget class="QFrame" name="extraTopMenu"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_11"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="btn_share"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-share-boxed.png);</string> + </property> + <property name="text"> + <string>Share</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_adjustments"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-equalizer.png);</string> + </property> + <property name="text"> + <string>Adjustments</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="btn_more"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-layers.png);</string> + </property> + <property name="text"> + <string>More</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="extraCenter"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_10"> + <item> + <widget class="QTextEdit" name="textEdit"> + <property name="minimumSize"> + <size> + <width>222</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true">background: transparent;</string> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="html"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Segoe UI'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#ff79c6;">PyDracula</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ffffff;">An interface created using Python and PySide (support for PyQt), and with colors based on the Dracula theme created by Zeno Rocha.</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ffffff;">MIT License</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#bd93f9;">Created by: Wanderson M. Pimenta</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#ff79c6;">Convert UI</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#ffffff;">pyside6-uic main.ui &gt; ui_main.py</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#ff79c6;">Convert QRC</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#ffffff;">pyside6-rcc resources.qrc -o resources_rc.py</span></p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="extraBottom"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="contentBox"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="contentTopBg"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>50</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>50</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>10</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="leftBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="verticalFrame"> + <layout class="QFormLayout" name="formLayout"> + <property name="horizontalSpacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="1" column="0"> + <widget class="QFrame" name="menuBar"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QToolButton" name="menu_file"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>16</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + <kerning>true</kerning> + </font> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>File</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="popupMode"> + <enum>QToolButton::InstantPopup</enum> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextOnly</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="menu_edit"> + <property name="text"> + <string>Edit</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="menu_run"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="text"> + <string>Run</string> + </property> + <property name="popupMode"> + <enum>QToolButton::InstantPopup</enum> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextOnly</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="titleRight"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>FlexSensor 6</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item alignment="Qt::AlignRight"> + <widget class="QFrame" name="rightButtons"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>28</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>5</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="settingsTopBtn"> + <property name="minimumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Settings</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../resources.qrc"> + <normaloff>:/icons/images/icons/icon_settings.png</normaloff>:/icons/images/icons/icon_settings.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="minimizeAppBtn"> + <property name="minimumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Minimize</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../resources.qrc"> + <normaloff>:/icons/images/icons/icon_minimize.png</normaloff>:/icons/images/icons/icon_minimize.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="maximizeRestoreAppBtn"> + <property name="minimumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + <stylestrategy>PreferDefault</stylestrategy> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Maximize</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../resources.qrc"> + <normaloff>:/icons/images/icons/icon_maximize.png</normaloff>:/icons/images/icons/icon_maximize.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="closeAppBtn"> + <property name="minimumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>28</width> + <height>28</height> + </size> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="toolTip"> + <string>Close</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../../resources.qrc"> + <normaloff>:/icons/images/icons/icon_close.png</normaloff>:/icons/images/icons/icon_close.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="contentBottom"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="content"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="pagesContainer"> + <property name="styleSheet"> + <string notr="true"/> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QGridLayout" name="gridLayout_5"> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="topMargin"> + <number>10</number> + </property> + <property name="rightMargin"> + <number>10</number> + </property> + <property name="bottomMargin"> + <number>10</number> + </property> + <item row="0" column="0"> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="styleSheet"> + <string notr="true">background: transparent;</string> + </property> + <property name="currentIndex"> + <number>4</number> + </property> + <widget class="QWidget" name="home"> + <property name="styleSheet"> + <string notr="true"/> + </property> + <layout class="QGridLayout" name="gridLayout_7"> + <item row="0" column="0"> + <layout class="QGridLayout" name="home_layout"/> + </item> + </layout> + </widget> + <widget class="QWidget" name="prober_control"> + <layout class="QVBoxLayout" name="verticalLayout_20"> + <item> + <layout class="QGridLayout" name="prober_control_layout"> + <property name="leftMargin"> + <number>1</number> + </property> + <property name="topMargin"> + <number>2</number> + </property> + <property name="rightMargin"> + <number>3</number> + </property> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="adc_control"> + <layout class="QGridLayout" name="gridLayout_6"> + <item row="0" column="0"> + <layout class="QGridLayout" name="adc_control_layout"/> + </item> + </layout> + </widget> + <widget class="QWidget" name="laser_control"> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <layout class="QGridLayout" name="laser_control_layout"/> + </item> + </layout> + </widget> + <widget class="QWidget" name="measured_data"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QGridLayout" name="measured_data_layout"/> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="extraRightBox"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>0</width> + <height>16777215</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="themeSettingsTopDetail"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>3</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="contentSettings"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_13"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QTextEdit" name="txt_logs"/> + </item> + <item alignment="Qt::AlignTop"> + <widget class="QFrame" name="topMenus"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_14"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="btn_print"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>45</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="cursor"> + <cursorShape>PointingHandCursor</cursorShape> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="styleSheet"> + <string notr="true">background-image: url(:/icons/images/icons/cil-print.png);</string> + </property> + <property name="text"> + <string>Print</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="bottomBar"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>22</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="creditsLabel"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>-1</pointsize> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Flexsensor 6</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="version"> + <property name="text"> + <string>v1.0.3</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="frame_size_grip"> + <property name="minimumSize"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>16777215</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + <resources> + <include location="../../resources.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/FlexSensor/MainWindow/resources/convert.sh b/src/FlexSensor/MainWindow/resources/convert.sh new file mode 100644 index 0000000000000000000000000000000000000000..eb75364500a9ddc5fb07ab9e2990bc1c2251cb18 --- /dev/null +++ b/src/FlexSensor/MainWindow/resources/convert.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Convert .ui files to .py files +for ui in *.ui; do + pyside6-uic $ui > ../view/${ui%.*}.py +done + pyside6-rcc ../../resources.qrc -o ../../resources_rc.py diff --git a/src/FlexSensor/MainWindow/resources/ui_palette.xml b/src/FlexSensor/MainWindow/resources/ui_palette.xml new file mode 100644 index 0000000000000000000000000000000000000000..b8fafb2b667af4fd7f647bd0e9d84a005270aab0 --- /dev/null +++ b/src/FlexSensor/MainWindow/resources/ui_palette.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<palette> + <active/> + <inactive/> + <disabled/> +</palette> diff --git a/src/FlexSensor/MainWindow/resources/ui_palette_QFrame.xml b/src/FlexSensor/MainWindow/resources/ui_palette_QFrame.xml new file mode 100644 index 0000000000000000000000000000000000000000..b8fafb2b667af4fd7f647bd0e9d84a005270aab0 --- /dev/null +++ b/src/FlexSensor/MainWindow/resources/ui_palette_QFrame.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<palette> + <active/> + <inactive/> + <disabled/> +</palette> diff --git a/src/FlexSensor/MainWindow/view/BaseWindow.py b/src/FlexSensor/MainWindow/view/BaseWindow.py new file mode 100644 index 0000000000000000000000000000000000000000..ae6ca6e885ac46bf3737ce528c4428ce196ace1a --- /dev/null +++ b/src/FlexSensor/MainWindow/view/BaseWindow.py @@ -0,0 +1,282 @@ +from PySide6.QtCore import QPropertyAnimation, QEasingCurve, QParallelAnimationGroup +from PySide6.QtGui import QColor, Qt, QIcon +from PySide6.QtWidgets import QMainWindow, QGraphicsDropShadowEffect, QSizeGrip, QPushButton + +import __version__ +from ConfigHandler.controller.AppSettings import Settings +from MainWindow.view.MainView import Ui_MainWindow +from MainWindow.view.widgets.custom_grips import CustomGrip + + +class BaseWindow(QMainWindow): + + def __init__(self, ui_main_window: Ui_MainWindow): + super().__init__() + self.GLOBAL_STATE = False + self.GLOBAL_TITLE_BAR = True + + self._ui = ui_main_window + self._ui.setupUi(self) + Settings.ENABLE_CUSTOM_TITLE_BAR = True + + # APP NAME + # /////////////////////////////////////////////////////////////// + title = "FlexSensor 6 - A SiPh automation tool" + description = f"Flexsensor {__version__.__version__}" + # APPLY TEXTS + self.setWindowTitle(title) + self._ui.titleRight.setText(description) + + if not Settings.ENABLE_CUSTOM_TITLE_BAR: + self._ui.appMargins.setContentsMargins(0, 0, 0, 0) + self._ui.minimizeAppBtn.hide() + self._ui.maximizeRestoreAppBtn.hide() + self._ui.closeAppBtn.hide() + self._ui.frame_size_grip.hide() + + # DROP SHADOW + self.shadow = QGraphicsDropShadowEffect(self) + self.shadow.setBlurRadius(17) + self.shadow.setXOffset(0) + self.shadow.setYOffset(0) + self.shadow.setColor(QColor(0, 0, 0, 150)) + self._ui.bgApp.setGraphicsEffect(self.shadow) + + # RESIZE WINDOW + self.sizegrip = QSizeGrip(self._ui.frame_size_grip) + self.sizegrip.setStyleSheet("width: 20px; height: 20px; margin 0px; padding: 0px;") + # self.setStyleSheet("background-color: rgb(0, 0, 0);") + + # MINIMIZE + self._ui.minimizeAppBtn.clicked.connect(lambda: self.showMinimized()) + + # MAXIMIZE/RESTORE + self._ui.maximizeRestoreAppBtn.clicked.connect(lambda: self.maximize_restore()) + + # CLOSE APPLICATION + self._ui.closeAppBtn.clicked.connect(lambda: self.close()) + + self.setWindowFlags(Qt.FramelessWindowHint) + self.setAttribute(Qt.WA_TranslucentBackground) + + self.left_grip = CustomGrip(self, Qt.LeftEdge, True) + self.right_grip = CustomGrip(self, Qt.RightEdge, True) + self.top_grip = CustomGrip(self, Qt.TopEdge, True) + self.bottom_grip = CustomGrip(self, Qt.BottomEdge, True) + self.maximize_restore() + # self._ui.titleRightInfo.mouseMoveEvent = self.moveWindow + + # def moveWindow(self, event): + + def openCloseRightBox(self): + self.toggleRightBox(True) + + def openCloseLeftBox(self): + self.toggleLeftBox(True) + + def toggleLeftBox(self, enable): + if enable: + # GET WIDTH + width = self._ui.extraLeftBox.width() + widthRightBox = self._ui.extraRightBox.width() + maxExtend = Settings.LEFT_BOX_WIDTH + color = Settings.BTN_LEFT_BOX_COLOR + standard = 0 + + # GET BTN STYLE + style = self._ui.toggleLeftBox.styleSheet() + + # SET MAX WIDTH + if width == 0: + widthExtended = maxExtend + # SELECT BTN + self._ui.toggleLeftBox.setStyleSheet(style + color) + if widthRightBox != 0: + style = self._ui.settingsTopBtn.styleSheet() + self._ui.settingsTopBtn.setStyleSheet(style.replace(Settings.BTN_RIGHT_BOX_COLOR, '')) + else: + widthExtended = standard + # RESET BTN + self._ui.toggleLeftBox.setStyleSheet(style.replace(color, '')) + + self.start_box_animation(width, widthRightBox, "left") + + # UI initialization + # TOGGLE RIGHT BOX + # # /////////////////////////////////////////////////////////////// + def toggleRightBox(self, enable): + if enable: + # GET WIDTH + width = self._ui.extraRightBox.width() + widthLeftBox = self._ui.extraLeftBox.width() + maxExtend = Settings.RIGHT_BOX_WIDTH + color = Settings.BTN_RIGHT_BOX_COLOR + standard = 0 + + # GET BTN STYLE + style = self._ui.settingsTopBtn.styleSheet() + + # SET MAX WIDTH + if width == 0: + widthExtended = maxExtend + # SELECT BTN + self._ui.settingsTopBtn.setStyleSheet(style + color) + if widthLeftBox != 0: + style = self._ui.toggleLeftBox.styleSheet() + self._ui.toggleLeftBox.setStyleSheet(style.replace(Settings.BTN_LEFT_BOX_COLOR, '')) + else: + widthExtended = standard + # RESET BTN + self._ui.settingsTopBtn.setStyleSheet(style.replace(color, '')) + + self.start_box_animation(widthLeftBox, width, "right") + + # TOGGLE MENU + # /////////////////////////////////////////////////////////////// + def toggleMenu(self, enable): + if enable: + # GET WIDTH + width = self._ui.leftMenuBg.width() + maxExtend = Settings.MENU_WIDTH + standard = 60 + + # SET MAX WIDTH + if width == 60: + widthExtended = maxExtend + else: + widthExtended = standard + + # ANIMATION + self.animation = QPropertyAnimation(self._ui.leftMenuBg, b"minimumWidth") + self.animation.setDuration(Settings.TIME_ANIMATION) + self.animation.setStartValue(width) + self.animation.setEndValue(widthExtended) + self.animation.setEasingCurve(QEasingCurve.InOutQuart) + self.animation.start() + + def start_box_animation(self, left_box_width, right_box_width, direction): + right_width = 0 + left_width = 0 + + # Check values + if left_box_width == 0 and direction == "left": + left_width = 240 + else: + left_width = 0 + # Check values + if right_box_width == 0 and direction == "right": + right_width = 240 + else: + right_width = 0 + + # ANIMATION LEFT BOX + self.left_box = QPropertyAnimation(self._ui.extraLeftBox, b"minimumWidth") + self.left_box.setDuration(Settings.TIME_ANIMATION) + self.left_box.setStartValue(left_box_width) + self.left_box.setEndValue(left_width) + self.left_box.setEasingCurve(QEasingCurve.InOutQuart) + + # ANIMATION RIGHT BOX + self.right_box = QPropertyAnimation(self._ui.extraRightBox, b"minimumWidth") + self.right_box.setDuration(Settings.TIME_ANIMATION) + self.right_box.setStartValue(right_box_width) + self.right_box.setEndValue(right_width) + self.right_box.setEasingCurve(QEasingCurve.InOutQuart) + + # GROUP ANIMATION + self.group = QParallelAnimationGroup() + self.group.addAnimation(self.left_box) + self.group.addAnimation(self.right_box) + self.group.start() + + def selectMenu(self, getStyle): + select = getStyle + Settings.MENU_SELECTED_STYLESHEET + return select + + def deselectMenu(self, getStyle): + deselect = getStyle.replace(Settings.MENU_SELECTED_STYLESHEET, "") + return deselect + + # START SELECTION + def selectStandardMenu(self, widget): + for w in self._ui.topMenu.findChildren(QPushButton): + if w.objectName() == widget: + w.setStyleSheet(self.selectMenu(w.styleSheet())) + + # RESET SELECTION + def resetStyle(self, widget): + for w in self._ui.topMenu.findChildren(QPushButton): + if w.objectName() != widget: + w.setStyleSheet(self.deselectMenu(w.styleSheet())) + + def resize_grips(self): + if Settings.ENABLE_CUSTOM_TITLE_BAR: + self.left_grip.setGeometry(0, 10, 10, self.height()) + self.right_grip.setGeometry(self.width() - 10, 10, 10, self.height()) + self.top_grip.setGeometry(0, 0, self.width(), 10) + self.bottom_grip.setGeometry(0, self.height() - 10, self.width(), 10) + + def resizeEvent(self, event): + # Update Size Grips + self.resize_grips() + + # MOUSE CLICK EVENTS + # /////////////////////////////////////////////////////////////// + def mousePressEvent(self, event): + # SET DRAG POS WINDOW + self.dragPos = event.globalPos() + + # PRINT MOUSE EVENTS + #if event.buttons() == Qt.LeftButton: + # print(f'Mouse click: LEFT CLICK {self.dragPos}') + #if event.buttons() == Qt.RightButton: + # print('Mouse click: RIGHT CLICK') + + def mouseMoveEvent(self, event) -> None: + # IF MAXIMIZED CHANGE TO NORMAL + + if self.returStatus(): + self.maximize_restore() + # MOVE WINDOW + if event.buttons() == Qt.LeftButton: + self.move(self.pos() + event.globalPos() - self.dragPos) + print(f"Mouse move: {event.pos()} - {self.pos()}") + self.dragPos = event.globalPos() + # event.accept() + # self.update() + + def maximize_restore(self): + status = self.GLOBAL_STATE + if status == False: + self.showMaximized() + GLOBAL_STATE = True + self._ui.appMargins.setContentsMargins(0, 0, 0, 0) + self._ui.maximizeRestoreAppBtn.setToolTip("Restore") + self._ui.maximizeRestoreAppBtn.setIcon(QIcon(u":/icons/images/icons/icon_restore.png")) + self._ui.frame_size_grip.hide() + self.left_grip.hide() + self.right_grip.hide() + self.top_grip.hide() + self.bottom_grip.hide() + else: + GLOBAL_STATE = False + self.showNormal() + self.resize(self.width() + 1, self.height() + 1) + self._ui.appMargins.setContentsMargins(10, 10, 10, 10) + self._ui.maximizeRestoreAppBtn.setToolTip("Maximize") + self._ui.maximizeRestoreAppBtn.setIcon(QIcon(u":/icons/images/icons/icon_maximize.png")) + self._ui.frame_size_grip.show() + self.left_grip.show() + self.right_grip.show() + self.top_grip.show() + self.bottom_grip.show() + + # RETURN STATUS + # /////////////////////////////////////////////////////////////// + def returStatus(self): + return self.GLOBAL_STATE + + # SET STATUS + # /////////////////////////////////////////////////////////////// + def setStatus(self, status): + self.GLOBAL_STATE = status diff --git a/src/FlexSensor/MainWindow/view/MainThreadView.py b/src/FlexSensor/MainWindow/view/MainThreadView.py new file mode 100644 index 0000000000000000000000000000000000000000..8a852bd475396d4f41c11fdb31f0671aea227472 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/MainThreadView.py @@ -0,0 +1,396 @@ +import logging +import sys +import traceback + +from PySide6.QtWidgets import ( + QMessageBox, QGridLayout, QGroupBox, QStatusBar, QPushButton, QTabWidget, QToolButton, QDockWidget, ) +from PySide6.QtCore import QThread + +from PySide6.QtGui import QIcon, QAction + +import pyqtgraph as pg +from pyqtgraph.dockarea import * + +import __version__ +from ConfigHandler.controller.VASInputFileParser import VASInputFileParser +from MainWindow.view.BaseWindow import BaseWindow +from MainWindow.view.widgets.HomeStatusWidget import HomeStatusWidget +from MainWindow.view.widgets.ScopeWidget import ScopeWidget + +from MainWindow.view.MainView import Ui_MainWindow + +from MainWindow.controller.MainThreadController import MainThreadController +from MainWindow.model.MainThreadModel import MainThreadModel +from MainWindow.view.StepThroughView import StepThroughView +from InitialSetupWizard.InitialSetupWizard import InitialSetupWizard +from MainWindow.view.widgets.WidgetSettingsFilesFolders import (WidgetSettingsOutFilesFolders, + WidgetLaserSettings, WidgetSettingsInFilesFolders, + WidgetAD2Settings) +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementEvaluationTool.view.widgets.MenuBarDefinition import MenuBarDefinition +from constants.qs_style_sheets import CSSPlayPushButton + +# +from pathes import image_root +import ConfigHandler as Config + + +class MainWindow(BaseWindow): + + def __init__(self, model: MainThreadModel, controller: MainThreadController): + super().__init__(Ui_MainWindow()) + self.logger = logging.getLogger("MainThread (UI)") + + self._model: MainThreadModel = model + self._controller: MainThreadController = controller + + # Signals for finished acquisition + self.model.measurement_routine.signals.routine_iteration_finished.connect( + self.on_routine_iteration_finished) + + self._ui.settingsTopBtn.clicked.connect(self.openCloseRightBox) + self._ui.toggleButton.clicked.connect(lambda: self.toggleMenu(True)) + self._ui.btn_start_measuring_routine.clicked.connect(self._on_btn_run_clicked) + + self.init_UI() + + # SET HOME PAGE AND SELECT MENU + # /////////////////////////////////////////////////////////////// + self._ui.stackedWidget.setCurrentWidget(self._ui.home) + self._ui.btn_home.setStyleSheet(self.selectMenu(self._ui.btn_home.styleSheet())) + + @property + def model(self) -> MainThreadModel: + return self._model + + @property + def controller(self) -> MainThreadController: + return self._controller + + # ================================================================================================================== + # UI initialization methods + # ================================================================================================================== + def init_UI(self): + self.logger.debug("Initializing UI of MainWindow.") + self.grid_layout_main = QGridLayout() + self.init_UI_status_bar() + self.menu_bar = MenuBarDefinition(self) + + # Add the prober control + self._ui.prober_control_layout.addWidget(self.model.prober_window) + self._ui.btn_probe_control.clicked.connect(self._on_btn_prober_control_clicked) + + # Add the ADC control + dock_ad2 = QDockWidget("AD2 Control", self) + dock_ad2.setWidget(self.model.ad2_window) + self._ui.adc_control_layout.addWidget(dock_ad2, 0,0) + self._ui.btn_adc_control.clicked.connect(self._on_btn_adc_control_clicked) + + dock_laser = QDockWidget("Laser Control", self) + dock_laser.setWidget(self.model.laser_window) + self._ui.adc_control_layout.addWidget(dock_laser,0,1) + self._ui.btn_laser_control.clicked.connect(self._on_btn_laser_control_clicked) + + # add the measurement evaluation tool + self._ui.measured_data_layout.addWidget(self.model.mea_eval_tool_window) + self._ui.btn_measured_data.clicked.connect(self._on_btn_measurement_evaluation_clicked) + + + self._ui.home_layout.addWidget(HomeStatusWidget(self), 0, 0, 1, 2) + self._ui.home_layout.addWidget(self.init_UI_measurement_settings(), 1, 0) + self._ui.home_layout.addWidget(ScopeWidget(self), 1, 1) + # self._ui.grid_layout_main.addWidget(self.init_UI_device_control(), 1, 1, 2, 1) + + self._ui.home_layout.addWidget(self.init_UI_buttons(), 2, 0, 1, 2) + self._ui.btn_home.clicked.connect(self._on_btn_home_clicked) + + # self.setGeometry(100, 100, 1250, 150) + self.setWindowTitle(f'FlexSensor Automator {__version__.__version__}') + self.setWindowIcon(QIcon('../images/FlexSensorIcon.png')) + + # self.init_menu_run() + + # widget = QWidget() + # widget.setLayout(layout) + # self.setCentralWidget(widget) + self._ui.closeAppBtn.clicked.connect(lambda: exit()) + + + # def closeEvent(self, *args, **kwargs): + # # self.prober_worker.stop() + # # self.threadpool.waitForDone() + # self.thread.quit() + # self.logger.warning(f"Exiting {args}") + # sys.exit(1) + + def init_UI_status_bar(self): + # global status_bar + + self.status_bar = QStatusBar() + self.setStatusBar(self.status_bar) + + def init_UI_measurement_settings(self): + tabwidget = QTabWidget() + self.configView = Config.View(self.model.vaut_config) + tab_input = tabwidget.addTab(WidgetSettingsInFilesFolders(self.model.vaut_config), "Input") + tab_folders = tabwidget.addTab(WidgetSettingsOutFilesFolders(self.model.vaut_config), "Folder Settings") + tab_ad2 = tabwidget.addTab(WidgetAD2Settings(self.model.vaut_config), "AD2 Settings") + tab_laser = tabwidget.addTab(WidgetLaserSettings(self.model.vaut_config), "Laser Settings") + tab_yaml = tabwidget.addTab(self.configView, "YAML Config") + tabwidget.currentChanged.connect( + lambda idx: self.configView.repopulate(self.model.vaut_config) if idx == tab_yaml else print("fg") + ) + return tabwidget + + # def init_UI_device_control(self): + # tabwidget = QTabWidget() + # # tab_scope = tabwidget.addTab(self.init_scope_meter(), "Scope") + # # tab_laser = tabwidget.addTab(self._controller.laser_window, "Laser Control") + # # tab_ad2dev = tabwidget.addTab(self._controller.ad2_window, "AD2 Control") + # # tab_prober = tabwidget.addTab(self._controller.prober_window, "Prober Control") + # + # return tabwidget + + def init_scope_meter(self): + area = DockArea() + + d1 = Dock("Analog Discovery 2") + d2 = Dock("Filtered") + area.addDock(d1, 'bottom') + area.addDock(d2, 'bottom', d1) + + self.scope_original = pg.PlotWidget(title="AD2 Acquisition") + # self.scope_original.plot(np.random.normal(size=100)*1e12) + self.scope_original.plotItem.showGrid(x=True, y=True, alpha=1) + d1.addWidget(self.scope_original) + + self.scope_filtered = pg.PlotWidget(title="Filtered Data") + # self.scope_filtered.plot(np.random.normal(size=100)) + self.scope_filtered.plotItem.showGrid(x=True, y=True, alpha=1) + d2.addWidget(self.scope_filtered) + + # self.scope = pg.PlotWidget() + # self.scope.plot([1, 2]) + + return area + + def init_UI_buttons(self): + grid_group_box = QGroupBox() + layout = QGridLayout() + + self.btn_run = QPushButton(parent=self, text="Run") + self.btn_run.clicked.connect(self._on_btn_run_clicked) + layout.addWidget(self.btn_run, 0, 0) + + self.btn_stop = QPushButton(parent=self, text="Stop") + # self.btn_stop.clicked.connect(self.on_btn_stop_clicked) + layout.addWidget(self.btn_stop, 0, 1) + + self.btn_exit = QPushButton(parent=self, text="Exit") + # self.btn_exit.clicked.connect(self.on_btn_exit_clicked) + layout.addWidget(self.btn_exit, 0, 2) + + grid_group_box.setLayout(layout) + + return grid_group_box + + # def init_menu_file(self): + # exit_action = QAction(QIcon('exit.png'), '&Exit ', self) + # exit_action.setShortcut('Ctrl+Q') + # exit_action.setStatusTip('Exit application') + # exit_action.triggered.connect(self.close) + # self._ui.menu_file.addAction(exit_action) + # + # def init_menu_edit(self): + # pass + # + # def init_menu_run(self): + # # self.menu_run = self.menubar.addMenu("Run") + # self.open_step_trough = QAction('Open &Step Through Window', self) + # self.open_step_trough.setShortcut('Ctrl+W') + # self.open_step_trough.setStatusTip('Open Step Through Window') + # self.open_step_trough.triggered.connect(self.on_open_step_through) + # self._ui.menu_run.addAction(self.open_step_trough) + # + # self.open_train_home_wizard = QAction('&Initial Setup Wizard', self) + # self.open_train_home_wizard.setShortcut('Ctrl+I') + # self.open_train_home_wizard.setStatusTip('Open Initial Setup Wizard') + # self.open_train_home_wizard.setIcon(QIcon(f"{image_root}/icons/setup_wizard.png")) + # self.open_train_home_wizard.triggered.connect(self.on_open_initial_setup_wizard) + # self._ui.menu_run.addAction(self.open_train_home_wizard) + # + # + # def init_UI_menu_bar(self): + # # self.menubar = self.menuBar() + # self.init_menu_file() + # self.init_menu_edit() + # self.init_menu_run() + # # help_menu = menubar.addMenu("Help") + # # help_menu.addAction("About", self.on_about_clicked) + + # ================================================================================================================== + # Signal handlers + # ================================================================================================================== + def _on_open_step_through(self): + file_parser = VASInputFileParser() + grouped_structures, _ = file_parser.read_file( + input_file=self.model.vaut_config.wafer_config.get_structure_file().absolute + ) + self.step_through_view = StepThroughView(grouped_structures) + self.step_through_view.show() + + def _on_open_initial_setup_wizard(self): + self.wizard = InitialSetupWizard(self.model.prober_controller) + self.wizard.show() + + def _on_btn_laser_control_clicked(self): + self.resetStyle(self.sender().objectName()) + self._ui.stackedWidget.setCurrentWidget(self._ui.laser_control) + self.sender().setStyleSheet(self.selectMenu(self.sender().styleSheet())) + + def _on_btn_adc_control_clicked(self): + self.resetStyle(self.sender().objectName()) + self._ui.stackedWidget.setCurrentWidget(self._ui.adc_control) + self.sender().setStyleSheet(self.selectMenu(self.sender().styleSheet())) + + def _on_btn_prober_control_clicked(self): + self.resetStyle(self.sender().objectName()) + self._ui.stackedWidget.setCurrentWidget(self._ui.prober_control) + self.sender().setStyleSheet(self.selectMenu(self.sender().styleSheet())) + + def _on_btn_home_clicked(self): + self.resetStyle(self.sender().objectName()) + self._ui.stackedWidget.setCurrentWidget(self._ui.home) + self.sender().setStyleSheet(self.selectMenu(self.sender().styleSheet())) + + def _on_btn_measurement_evaluation_clicked(self): + self.resetStyle(self.sender().objectName()) + self._ui.stackedWidget.setCurrentWidget(self._ui.measured_data) + self.sender().setStyleSheet(self.selectMenu(self.sender().styleSheet())) + + def _on_btn_run_clicked(self): + self._ui.btn_start_measuring_routine.setStyleSheet(CSSPlayPushButton.style_pause()) + self._controller.start_measurement_routine() + + # ------------------------------------------------------------------------------------------------------------------ + # not used (yet) + def on_wafer_version_changed(self, value): + pass + # # Set the object property + # self.vaut_config.set_wafer_version(value) + # # Update all textfields + # self.on_tb_log_file_text_changed(self.tb_log_file.text()) + # self.on_tb_bookmark_file_text_changed(self.tb_bookmark_file.text()) + # self.on_tb_scope_image_file_text_changed(self.tb_scope_image_file.text()) + # self.on_tb_mat_files_output_text_changed(self.tb_mat_files_output.text()) + # self.on_tb_measurement_output_text_changed(self.tb_measurement_output.text()) + # self.tb_working_directory.setText(self.vaut_config.output_directory.rel) + + def on_wafer_nr_changed(self, value): + pass + # # Set the object property + # self.vaut_config.set_wafer_nr(value) + # # Update all textfields + # self.on_tb_log_file_text_changed(self.tb_log_file.text()) + # self.on_tb_bookmark_file_text_changed(self.tb_bookmark_file.text()) + # self.on_tb_scope_image_file_text_changed(self.tb_scope_image_file.text()) + # self.on_tb_mat_files_output_text_changed(self.tb_mat_files_output.text()) + # self.on_tb_measurement_output_text_changed(self.tb_measurement_output.text()) + # self.tb_working_directory.setText(self.vaut_config.output_directory.rel) + + def on_routine_iteration_finished(self, cur_measured_signal: SingleMeasuredData = None): + pass + # if not isinstance(cur_measured_signal, SingleMeasuredData): + # self.logger.error( + # f"Prober did not return any valid measured signal: measured_signal was {type(cur_measured_signal)}") + # self.on_error_emitted((ValueError, + # f"Prober did not return any valid measured signal: measured_signal was {type(cur_measured_signal)}", + # traceback.format_exc())) + # # raise ValueError(f"Prober did not return any valid measured signal: measured_signal was {type(measured_signal)}") + + # self.logger.info( + # f"Acquisition finished for structure {cur_measured_signal.wafer_properties.structure_name} (die: {cur_measured_signal.wafer_properties.die_number}).") + # try: + # if len(cur_measured_signal._filtered_amplitude['amplitude']) > 0: + # self.scope_original.clear() + # self.scope_original.plot(cur_measured_signal.measured_data['measurements'], pen=pg.mkPen(width=1)) + # else: + # self.logger.warning("Nothing to plot!") + # except Exception as e: + # self.logger.error(f"Error plotting scope: {e}") + # self.on_error_emitted((type(e), f"Error plotting scope: {e}", traceback.format_exc())) + + def on_error(self, error_message): + self.logger.error(error_message) + self.status_bar.showMessage(error_message) + self.status_bar.setStyleSheet("color: red") + + def on_writeout_emitted(self, msg_type, message): + + if msg_type == "debug": + self.status_bar.setStyleSheet('border: 0; color: blue;') + elif msg_type == "warning": + self.status_bar.setStyleSheet('border: 0; color: orange;') + elif msg_type == "error": + self.status_bar.setStyleSheet('border: 0; color: red;') + elif msg_type == "fatal": + self.status_bar.setStyleSheet('border: 0; color: red;') + else: + self.status_bar.setStyleSheet('border: 0; color: black;') + self.status_bar.showMessage(message) + + def on_report_info_emitted(self, version_info): + self.lbl_die_no.setText("<b>" + str(version_info["die_no"]) + "</b>") + self.lbl_structure.setText("<b>" + str(version_info["structure"]) + "</b>") + self.lbl_die_col.setText("<b>" + str(version_info["chuck_col"]) + "</b>") + self.lbl_die_row.setText("<b>" + str(version_info["chuck_row"]) + "</b>") + + def on_report_progress(self, progress): + self.progress.setValue(progress) + + def on_structure_select(self): + pass + # self.test_win.show() + + def on_error_emitted(self, value): + title, text, details = value + try: + self.error_dialog: QMessageBox + # self.error_dialog.close() + except Exception as e: + print(f"Can't close error_dialog: {e}") + # Show a error dialog + self.error_dialog = QMessageBox() + self.error_dialog.setText(str(text)) + # set detailed text + self.error_dialog.setDetailedText(str(details)) + self.error_dialog.setIcon(QMessageBox.Critical) + self.error_dialog.setWindowTitle(f"Measurmenent Routine Error: {title}") + self.error_dialog.exec_() + + def on_warning_emitted(self, value): + try: + self.warning_dialog: QMessageBox + self.warning_dialog.close() + except Exception as e: + print(f"Can't close warning_dialog: {e}") + + # Show a warning dialog + self.warning_dialog = QMessageBox() + self.warning_dialog.setText(str(value[1])) + # set detailed text + self.warning_dialog.setDetailedText(str(value[2])) + self.warning_dialog.setIcon(QMessageBox.Warning) + self.warning_dialog.setWindowTitle(f"Prober Task Warning: {value[0]}") + self.warning_dialog.exec_() + + def closeEvent(self, event): + # do stuff + self.model.ad2_controller.stop_process() + self.model.laser_controller.stop_process() + event.accept() # let the window close + + + def __del__(self): + self.logger.info("Exiting") + quit() \ No newline at end of file diff --git a/src/FlexSensor/MainWindow/view/MainView.py b/src/FlexSensor/MainWindow/view/MainView.py new file mode 100644 index 0000000000000000000000000000000000000000..e875299a596dcae7c9d3d00b7770fc0234450d2d --- /dev/null +++ b/src/FlexSensor/MainWindow/view/MainView.py @@ -0,0 +1,1587 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'MainViewWUffIj.ui' +## +## Created by: Qt User Interface Compiler version 6.2.3 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QFormLayout, QFrame, QGridLayout, + QHBoxLayout, QLabel, QLayout, QMainWindow, + QPushButton, QSizePolicy, QStackedWidget, QTextEdit, + QToolButton, QVBoxLayout, QWidget) +import resources_rc + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(1085, 753) + MainWindow.setMinimumSize(QSize(940, 560)) + MainWindow.setToolTipDuration(-9) + self.styleSheet = QWidget(MainWindow) + self.styleSheet.setObjectName(u"styleSheet") + self.styleSheet.setMaximumSize(QSize(16777214, 16777215)) + self.styleSheet.setToolTipDuration(0) + self.styleSheet.setStyleSheet(u"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"\n" +"SET APP STYLESHEET - FULL STYLES HERE\n" +"DARK THEME - DRACULA COLOR BASED\n" +"\n" +"///////////////////////////////////////////////////////////////////////////////////////////////// */\n" +"\n" +"QWidget{\n" +" color: rgb(221, 221, 221);\n" +" font: 10pt \"Segoe UI\";\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Tooltip */\n" +"QToolTip {\n" +" color: #ffffff;\n" +" background-color: rgba(33, 37, 43, 180);\n" +" border: 1px solid rgb(44, 49, 58);\n" +" background-image: none;\n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 2px solid rgb(255, 121, 198);\n" +" text-align: left;\n" +" padding-left: 8px;\n" +" margin: 0px;\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Bg App */\n" +"#bgApp { \n" +" background" + "-color: rgb(40, 44, 52);\n" +" border: 1px solid rgb(44, 49, 58);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Left Menu */\n" +"#leftMenuBg { \n" +" background-color: rgb(33, 37, 43);\n" +"}\n" +"#topLogo {\n" +" background-color: rgb(33, 37, 43);\n" +" border-image: url(:/images/images/images/FlexSensorIcon.png) 10 0 0 0 strech strech;\n" +" background-position: centered;\n" +" background-repeat: no-repeat;\n" +"}\n" +"#titleLeftApp { font: 63 12pt \"Segoe UI Semibold\"; }\n" +"#titleLeftDescription { font: 8pt \"Segoe UI\"; color: rgb(189, 147, 249); }\n" +"\n" +"/* MENUS */\n" +"\n" +"\n" +"\n" +"#topMenu .QPushButton { \n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 22px solid transparent;\n" +" background-color: transparent;\n" +" text-align: left;\n" +" padding-left: 44px;\n" +"}\n" +"#topMenu .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#topMenu .QPushButton:p" + "ressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"#bottomMenu .QPushButton { \n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 20px solid transparent;\n" +" background-color:transparent;\n" +" text-align: left;\n" +" padding-left: 44px;\n" +"}\n" +"#bottomMenu .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#bottomMenu .QPushButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"#leftMenuFrame{\n" +" border-top: 3px solid rgb(44, 49, 58);\n" +"}\n" +"\n" +"/* Toggle Button */\n" +"#toggleButton {\n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 20px solid transparent;\n" +" background-color: rgb(37, 41, 48);\n" +" text-align: left;\n" +" padding-left: 44px;\n" +" color: rgb(113, 126, 149);\n" +"}\n" +"#toggleButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#toggleButto" + "n:pressed {\n" +" background-color: rgb(189, 147, 249);\n" +"}\n" +"\n" +"/* Title Menu */\n" +"/*#titleRightInfo { padding-left: 10px; }*/\n" +"\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Extra Tab */\n" +"#extraLeftBox { \n" +" background-color: rgb(44, 49, 58);\n" +"}\n" +"#extraTopBg{ \n" +" background-color: rgb(189, 147, 249)\n" +"}\n" +"\n" +"/* Icon */\n" +"#extraIcon {\n" +" background-position: center;\n" +" background-repeat: no-repeat;\n" +" background-image: url(:/icons/images/icons/icon_settings.png);\n" +"}\n" +"\n" +"/* Label */\n" +"#extraLabel { color: rgb(255, 255, 255); }\n" +"\n" +"/* Btn Close */\n" +"#extraCloseColumnBtn { background-color: rgba(255, 255, 255, 0); border: none; border-radius: 5px; }\n" +"#extraCloseColumnBtn:hover { background-color: rgb(196, 161, 249); border-style: solid; border-radius: 4px; }\n" +"#extraCloseColumnBtn:pressed { background-color: rgb(180, 141, 238); border-style: solid; border-radius: 4px; }\n" +"\n" +"/* Extr" + "a Content */\n" +"#extraContent{\n" +" border-top: 3px solid rgb(40, 44, 52);\n" +"}\n" +"\n" +"/* Extra Top Menus */\n" +"#extraTopMenu .QPushButton {\n" +" /*background-position: left center;*/\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 22px solid transparent;\n" +" background-color:transparent;\n" +" text-align: left;\n" +" padding-left: 44px;\n" +"}\n" +"#extraTopMenu .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#extraTopMenu .QPushButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Content App */\n" +"#contentTopBg{ \n" +" background-color: rgb(33, 37, 43);\n" +"}\n" +"#contentBottom{\n" +" border-top: 3px solid rgb(44, 49, 58);\n" +"}\n" +"\n" +"/* Top Buttons */\n" +"#rightButtons .QPushButton { background-color: rgba(255, 255, 255, 0); border: none; border-radius: 5px; }\n" +"#rightButtons .QPushBu" + "tton:hover { background-color: rgb(44, 49, 57); border-style: solid; border-radius: 4px; }\n" +"#rightButtons .QPushButton:pressed { background-color: rgb(23, 26, 30); border-style: solid; border-radius: 4px; }\n" +"\n" +"/* Theme Settings */\n" +"#extraRightBox { background-color: rgb(44, 49, 58); }\n" +"#themeSettingsTopDetail { background-color: rgb(189, 147, 249); }\n" +"\n" +"/* Bottom Bar */\n" +"#bottomBar { background-color: rgb(44, 49, 58); }\n" +"#bottomBar QLabel { font-size: 11px; color: rgb(113, 126, 149); padding-left: 10px; padding-right: 10px; padding-bottom: 2px; }\n" +"\n" +"/* CONTENT SETTINGS */\n" +"/* MENUS */\n" +"#contentSettings .QPushButton { \n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 22px solid transparent;\n" +" background-color:transparent;\n" +" text-align: left;\n" +" padding-left: 44px;\n" +"}\n" +"#contentSettings .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#contentSettings .QPushButton:pressed { \n" +"" + " background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"QTableWidget */\n" +"QTableWidget { \n" +" background-color: transparent;\n" +" padding: 10px;\n" +" border-radius: 5px;\n" +" gridline-color: rgb(44, 49, 58);\n" +" border-bottom: 1px solid rgb(44, 49, 60);\n" +"}\n" +"QTableWidget::item{\n" +" border-color: rgb(44, 49, 60);\n" +" padding-left: 5px;\n" +" padding-right: 5px;\n" +" gridline-color: rgb(44, 49, 60);\n" +"}\n" +"QTableWidget::item:selected{\n" +" background-color: rgb(189, 147, 249);\n" +"}\n" +"QHeaderView::section{\n" +" background-color: rgb(33, 37, 43);\n" +" max-width: 30px;\n" +" border: 1px solid rgb(44, 49, 58);\n" +" border-style: none;\n" +" border-bottom: 1px solid rgb(44, 49, 60);\n" +" border-right: 1px solid rgb(44, 49, 60);\n" +"}\n" +"QTableWidget::horizontalHeader { \n" +" background-color: rgb(33, 37, 43);\n" +"}\n" +"QHeaderView::section:horizontal\n" +"{\n" +" " + " border: 1px solid rgb(33, 37, 43);\n" +" background-color: rgb(33, 37, 43);\n" +" padding: 3px;\n" +" border-top-left-radius: 7px;\n" +" border-top-right-radius: 7px;\n" +"}\n" +"QHeaderView::section:vertical\n" +"{\n" +" border: 1px solid rgb(44, 49, 60);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"LineEdit */\n" +"QLineEdit {\n" +" background-color: rgb(33, 37, 43);\n" +" border-radius: 5px;\n" +" border: 2px solid rgb(33, 37, 43);\n" +" padding-left: 10px;\n" +" selection-color: rgb(255, 255, 255);\n" +" selection-background-color: rgb(255, 121, 198);\n" +"}\n" +"QLineEdit:hover {\n" +" border: 2px solid rgb(64, 71, 88);\n" +"}\n" +"QLineEdit:focus {\n" +" border: 2px solid rgb(91, 101, 124);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"PlainTextEdit */\n" +"QPlainTextEdit {\n" +" background-color: rgb(27, 29, 35);\n" +" border-radius: 5px;\n" +" padding: 10px;\n" +" selection-" + "color: rgb(255, 255, 255);\n" +" selection-background-color: rgb(255, 121, 198);\n" +"}\n" +"QPlainTextEdit QScrollBar:vertical {\n" +" width: 8px;\n" +" }\n" +"QPlainTextEdit QScrollBar:horizontal {\n" +" height: 8px;\n" +" }\n" +"QPlainTextEdit:hover {\n" +" border: 2px solid rgb(64, 71, 88);\n" +"}\n" +"QPlainTextEdit:focus {\n" +" border: 2px solid rgb(91, 101, 124);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"ScrollBars */\n" +"QScrollBar:horizontal {\n" +" border: none;\n" +" background: rgb(52, 59, 72);\n" +" height: 8px;\n" +" margin: 0px 21px 0 21px;\n" +" border-radius: 0px;\n" +"}\n" +"QScrollBar::handle:horizontal {\n" +" background: rgb(189, 147, 249);\n" +" min-width: 25px;\n" +" border-radius: 4px\n" +"}\n" +"QScrollBar::add-line:horizontal {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" width: 20px;\n" +" border-top-right-radius: 4px;\n" +" border-bottom-right-radius: 4px;\n" +" subcontrol-positi" + "on: right;\n" +" subcontrol-origin: margin;\n" +"}\n" +"QScrollBar::sub-line:horizontal {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" width: 20px;\n" +" border-top-left-radius: 4px;\n" +" border-bottom-left-radius: 4px;\n" +" subcontrol-position: left;\n" +" subcontrol-origin: margin;\n" +"}\n" +"QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal\n" +"{\n" +" background: none;\n" +"}\n" +"QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal\n" +"{\n" +" background: none;\n" +"}\n" +" QScrollBar:vertical {\n" +" border: none;\n" +" background: rgb(52, 59, 72);\n" +" width: 8px;\n" +" margin: 21px 0 21px 0;\n" +" border-radius: 0px;\n" +" }\n" +" QScrollBar::handle:vertical { \n" +" background: rgb(189, 147, 249);\n" +" min-height: 25px;\n" +" border-radius: 4px\n" +" }\n" +" QScrollBar::add-line:vertical {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" height: 20px;\n" +" border-bottom-left-radius: 4px;\n" +" border-bottom-right-radius" + ": 4px;\n" +" subcontrol-position: bottom;\n" +" subcontrol-origin: margin;\n" +" }\n" +" QScrollBar::sub-line:vertical {\n" +" border: none;\n" +" background: rgb(55, 63, 77);\n" +" height: 20px;\n" +" border-top-left-radius: 4px;\n" +" border-top-right-radius: 4px;\n" +" subcontrol-position: top;\n" +" subcontrol-origin: margin;\n" +" }\n" +" QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {\n" +" background: none;\n" +" }\n" +"\n" +" QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {\n" +" background: none;\n" +" }\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"CheckBox */\n" +"QCheckBox::indicator {\n" +" border: 3px solid rgb(52, 59, 72);\n" +" width: 15px;\n" +" height: 15px;\n" +" border-radius: 10px;\n" +" background: rgb(44, 49, 60);\n" +"}\n" +"QCheckBox::indicator:hover {\n" +" border: 3px solid rgb(58, 66, 81);\n" +"}\n" +"QCheckBox::indicator:checked {\n" +" background: 3px solid rgb(52, 59," + " 72);\n" +" border: 3px solid rgb(52, 59, 72); \n" +" background-image: url(:/icons/images/icons/cil-check-alt.png);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"RadioButton */\n" +"QRadioButton::indicator {\n" +" border: 3px solid rgb(52, 59, 72);\n" +" width: 15px;\n" +" height: 15px;\n" +" border-radius: 10px;\n" +" background: rgb(44, 49, 60);\n" +"}\n" +"QRadioButton::indicator:hover {\n" +" border: 3px solid rgb(58, 66, 81);\n" +"}\n" +"QRadioButton::indicator:checked {\n" +" background: 3px solid rgb(94, 106, 130);\n" +" border: 3px solid rgb(52, 59, 72); \n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"ComboBox */\n" +"QComboBox{\n" +" background-color: rgb(27, 29, 35);\n" +" border-radius: 5px;\n" +" border: 2px solid rgb(33, 37, 43);\n" +" padding: 5px;\n" +" padding-left: 10px;\n" +"}\n" +"QComboBox:hover{\n" +" border: 2px solid rgb(64, 71, 88);\n" +"}\n" +"QComboBox:" + ":drop-down {\n" +" subcontrol-origin: padding;\n" +" subcontrol-position: top right;\n" +" width: 25px; \n" +" border-left-width: 3px;\n" +" border-left-color: rgba(39, 44, 54, 150);\n" +" border-left-style: solid;\n" +" border-top-right-radius: 3px;\n" +" border-bottom-right-radius: 3px; \n" +" background-image: url(:/icons/images/icons/cil-arrow-bottom.png);\n" +" background-position: center;\n" +" background-repeat: no-reperat;\n" +" }\n" +"QComboBox QAbstractItemView {\n" +" color: rgb(255, 121, 198); \n" +" background-color: rgb(33, 37, 43);\n" +" padding: 10px;\n" +" selection-background-color: rgb(39, 44, 54);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Sliders */\n" +"QSlider::groove:horizontal {\n" +" border-radius: 5px;\n" +" height: 10px;\n" +" margin: 0px;\n" +" background-color: rgb(52, 59, 72);\n" +"}\n" +"QSlider::groove:horizontal:hover {\n" +" background-color: rgb(55, 62, 76);\n" +"}\n" +"QSlider::handle:horizontal {\n" +" background-co" + "lor: rgb(189, 147, 249);\n" +" border: none;\n" +" height: 10px;\n" +" width: 10px;\n" +" margin: 0px;\n" +" border-radius: 5px;\n" +"}\n" +"QSlider::handle:horizontal:hover {\n" +" background-color: rgb(195, 155, 255);\n" +"}\n" +"QSlider::handle:horizontal:pressed {\n" +" background-color: rgb(255, 121, 198);\n" +"}\n" +"\n" +"QSlider::groove:vertical {\n" +" border-radius: 5px;\n" +" width: 10px;\n" +" margin: 0px;\n" +" background-color: rgb(52, 59, 72);\n" +"}\n" +"QSlider::groove:vertical:hover {\n" +" background-color: rgb(55, 62, 76);\n" +"}\n" +"QSlider::handle:vertical {\n" +" background-color: rgb(189, 147, 249);\n" +" border: none;\n" +" height: 10px;\n" +" width: 10px;\n" +" margin: 0px;\n" +" border-radius: 5px;\n" +"}\n" +"QSlider::handle:vertical:hover {\n" +" background-color: rgb(195, 155, 255);\n" +"}\n" +"QSlider::handle:vertical:pressed {\n" +" background-color: rgb(255, 121, 198);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////" + "////////////////\n" +"CommandLinkButton */\n" +"QCommandLinkButton { \n" +" color: rgb(255, 121, 198);\n" +" border-radius: 5px;\n" +" padding: 5px;\n" +" color: rgb(255, 170, 255);\n" +"}\n" +"QCommandLinkButton:hover { \n" +" color: rgb(255, 170, 255);\n" +" background-color: rgb(44, 49, 60);\n" +"}\n" +"QCommandLinkButton:pressed { \n" +" color: rgb(189, 147, 249);\n" +" background-color: rgb(52, 58, 71);\n" +"}\n" +"\n" +"/* /////////////////////////////////////////////////////////////////////////////////////////////////\n" +"Button */\n" +"#pagesContainer QPushButton {\n" +" border: 2px solid rgb(52, 59, 72);\n" +" border-radius: 5px; \n" +" background-color: rgb(52, 59, 72);\n" +"}\n" +"#pagesContainer QPushButton:hover {\n" +" background-color: rgb(57, 65, 80);\n" +" border: 2px solid rgb(61, 70, 86);\n" +"}\n" +"#pagesContainer QPushButton:pressed { \n" +" background-color: rgb(35, 40, 49);\n" +" border: 2px solid rgb(43, 50, 61);\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"QToolButton { \n" +"border-image:" + " url(:/img/btn_mid_0.png);\n" +"text-align: center;\n" +"}\n" +"QToolButton::menu-indicator { image: none; }\n" +"\n" +"\n" +"#menuBar .QPushButton { \n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" /*border-left: 22px solid transparent;*/\n" +" /*text-align: center;*/\n" +" padding-right: 10px;\n" +"}\n" +"#menuBar .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#menuBar .QPushButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"#menuBar .QToolButton {\n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" /*border-left: 22px solid transparent;*/\n" +" /*text-align: center;*/\n" +" padding-right: 10px;\n" +"}\n" +"#menuBar .QToolButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#menuBar .QToolButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"\n" +"#extraMenuBar ." + "QToolButton {\n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" /*border-left: 22px solid transparent;*/\n" +" /*text-align: center;*/\n" +" padding-right: 10px;\n" +"}\n" +"#extraMenuBar .QToolButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#extraMenuBar .QToolButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"\n" +"#extraMenuBar .QPushButton {\n" +" /*background-position: left center;*/\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 22px solid transparent;\n" +" text-align: center;\n" +" /*padding-left: 44px;*/\n" +"}\n" +"#extraMenuBar .QPushButton:hover {\n" +" background-color: rgb(40, 44, 52);\n" +"}\n" +"#extraMenuBar .QPushButton:pressed { \n" +" background-color: rgb(189, 147, 249);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"/* QMenu ------------------------------------------------------------------\n" +"\n" +"examples: https://doc.qt.io/" + "qt-5/stylesheet-examples.html#customizing-qmenu\n" +"\n" +"--------------------------------------------------------------------------- */\n" +"QMenu {\n" +" background-color: rgb(40, 44, 52);\n" +" margin: 2px; /* some spacing around the menu */\n" +"}\n" +"\n" +"QMenu::item {\n" +" padding: 2px 25px 2px 20px;\n" +" border: 1px solid transparent; /* reserve space for selection border */\n" +"}\n" +"\n" +"QMenu::item:selected {\n" +" border-color: darkblue;\n" +" background: rgba(100, 100, 100, 150);\n" +"}\n" +"\n" +"QMenu::icon:checked { /* appearance of a 'checked' icon */\n" +" background: gray;\n" +" border: 1px inset gray;\n" +" position: absolute;\n" +" top: 1px;\n" +" right: 1px;\n" +" bottom: 1px;\n" +" left: 1px;\n" +"}\n" +"\n" +"QMenu::separator {\n" +" height: 2px;\n" +" background: lightblue;\n" +" margin-left: 10px;\n" +" margin-right: 5px;\n" +"}\n" +"\n" +"QMenu::indicator {\n" +" width: 13px;\n" +" height: 13px;\n" +"}\n" +"\n" +"/*\n" +"\n" +"QMenu::indicator:non-exclusive:unch" + "ecked {\n" +" image: url(:/images/checkbox_unchecked.png);\n" +"}\n" +"\n" +"QMenu::indicator:non-exclusive:unchecked:selected {\n" +" image: url(:/images/checkbox_unchecked_hover.png);\n" +"}\n" +"\n" +"QMenu::indicator:non-exclusive:checked {\n" +" image: url(:/images/checkbox_checked.png);\n" +"}\n" +"\n" +"QMenu::indicator:non-exclusive:checked:selected {\n" +" image: url(:/images/checkbox_checked_hover.png);\n" +"}\n" +"\n" +"\n" +"QMenu::indicator:exclusive:unchecked {\n" +" image: url(:/images/radiobutton_unchecked.png);\n" +"}\n" +"\n" +"QMenu::indicator:exclusive:unchecked:selected {\n" +" image: url(:/images/radiobutton_unchecked_hover.png);\n" +"}\n" +"\n" +"QMenu::indicator:exclusive:checked {\n" +" image: url(:/images/radiobutton_checked.png);\n" +"}\n" +"\n" +"QMenu::indicator:exclusive:checked:selected {\n" +" image: url(:/images/radiobutton_checked_hover.png);\n" +"}*/\n" +"\n" +"QTabWidget::pane {\n" +" border: 1px solid lightgray;\n" +" top:-1px; \n" +" background: rgb(40, 44, 52); \n" +"} \n" +"\n" +"Q" + "TabBar::tab {\n" +" background: rgb(40, 44, 52);; \n" +" border: 1px solid lightgray; \n" +" padding: 2px;\n" +" padding-left: 10px;\n" +" padding-right: 10px;\n" +"} \n" +"\n" +"QTabBar::tab:selected { \n" +" background: rgb(189, 147, 249);\n" +" margin-bottom: -1px; \n" +"}") + self.appMargins = QVBoxLayout(self.styleSheet) + self.appMargins.setSpacing(0) + self.appMargins.setObjectName(u"appMargins") + self.appMargins.setContentsMargins(10, 10, 10, 10) + self.bgApp = QFrame(self.styleSheet) + self.bgApp.setObjectName(u"bgApp") + self.bgApp.setToolTipDuration(0) + self.bgApp.setStyleSheet(u"") + self.bgApp.setFrameShape(QFrame.NoFrame) + self.bgApp.setFrameShadow(QFrame.Plain) + self.appLayout = QHBoxLayout(self.bgApp) + self.appLayout.setSpacing(0) + self.appLayout.setObjectName(u"appLayout") + self.appLayout.setContentsMargins(0, 0, 0, 0) + self.leftMenuBg = QFrame(self.bgApp) + self.leftMenuBg.setObjectName(u"leftMenuBg") + self.leftMenuBg.setMinimumSize(QSize(60, 0)) + self.leftMenuBg.setMaximumSize(QSize(60, 16777215)) + self.leftMenuBg.setFrameShape(QFrame.NoFrame) + self.leftMenuBg.setFrameShadow(QFrame.Raised) + self.verticalLayout_3 = QVBoxLayout(self.leftMenuBg) + self.verticalLayout_3.setSpacing(0) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.topLogoInfo = QFrame(self.leftMenuBg) + self.topLogoInfo.setObjectName(u"topLogoInfo") + self.topLogoInfo.setMinimumSize(QSize(0, 50)) + self.topLogoInfo.setMaximumSize(QSize(16777215, 50)) + self.topLogoInfo.setFrameShape(QFrame.NoFrame) + self.topLogoInfo.setFrameShadow(QFrame.Raised) + self.titleLeftApp = QLabel(self.topLogoInfo) + self.titleLeftApp.setObjectName(u"titleLeftApp") + self.titleLeftApp.setGeometry(QRect(60, 3, 160, 20)) + font = QFont() + font.setFamilies([u"Segoe UI Semibold"]) + font.setPointSize(12) + font.setBold(False) + font.setItalic(False) + self.titleLeftApp.setFont(font) + self.titleLeftApp.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) + self.topLogo = QFrame(self.topLogoInfo) + self.topLogo.setObjectName(u"topLogo") + self.topLogo.setGeometry(QRect(10, 4, 42, 42)) + self.topLogo.setMinimumSize(QSize(42, 42)) + self.topLogo.setMaximumSize(QSize(42, 42)) + self.topLogo.setFrameShape(QFrame.NoFrame) + self.topLogo.setFrameShadow(QFrame.Raised) + self.titleLeftDescription = QLabel(self.topLogoInfo) + self.titleLeftDescription.setObjectName(u"titleLeftDescription") + self.titleLeftDescription.setGeometry(QRect(60, 22, 160, 16)) + self.titleLeftDescription.setMaximumSize(QSize(16777215, 16)) + font1 = QFont() + font1.setFamilies([u"Segoe UI"]) + font1.setPointSize(8) + font1.setBold(False) + font1.setItalic(False) + self.titleLeftDescription.setFont(font1) + self.titleLeftDescription.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) + + self.verticalLayout_3.addWidget(self.topLogoInfo) + + self.leftMenuFrame = QFrame(self.leftMenuBg) + self.leftMenuFrame.setObjectName(u"leftMenuFrame") + self.leftMenuFrame.setEnabled(True) + self.leftMenuFrame.setMinimumSize(QSize(0, 0)) + self.leftMenuFrame.setMaximumSize(QSize(16777215, 16777215)) + self.leftMenuFrame.setToolTipDuration(0) + self.leftMenuFrame.setLayoutDirection(Qt.LeftToRight) + self.leftMenuFrame.setFrameShape(QFrame.NoFrame) + self.leftMenuFrame.setFrameShadow(QFrame.Raised) + self.verticalMenuLayout = QVBoxLayout(self.leftMenuFrame) + self.verticalMenuLayout.setSpacing(0) + self.verticalMenuLayout.setObjectName(u"verticalMenuLayout") + self.verticalMenuLayout.setContentsMargins(0, 0, 0, 0) + self.toggleBox = QFrame(self.leftMenuFrame) + self.toggleBox.setObjectName(u"toggleBox") + self.toggleBox.setMaximumSize(QSize(16777215, 45)) + self.toggleBox.setFrameShape(QFrame.NoFrame) + self.toggleBox.setFrameShadow(QFrame.Raised) + self.verticalLayout_4 = QVBoxLayout(self.toggleBox) + self.verticalLayout_4.setSpacing(0) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) + self.toggleButton = QPushButton(self.toggleBox) + self.toggleButton.setObjectName(u"toggleButton") + sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.toggleButton.sizePolicy().hasHeightForWidth()) + self.toggleButton.setSizePolicy(sizePolicy) + self.toggleButton.setMinimumSize(QSize(0, 45)) + font2 = QFont() + font2.setFamilies([u"Segoe UI"]) + font2.setPointSize(10) + font2.setBold(False) + font2.setItalic(False) + self.toggleButton.setFont(font2) + self.toggleButton.setCursor(QCursor(Qt.PointingHandCursor)) + self.toggleButton.setLayoutDirection(Qt.LeftToRight) + self.toggleButton.setStyleSheet(u"background-image: url(:/icons/images/icons/icon_menu.png);") + + self.verticalLayout_4.addWidget(self.toggleButton) + + + self.verticalMenuLayout.addWidget(self.toggleBox) + + self.topMenu = QFrame(self.leftMenuFrame) + self.topMenu.setObjectName(u"topMenu") + self.topMenu.setMinimumSize(QSize(0, 10)) + self.topMenu.setLayoutDirection(Qt.LeftToRight) + self.topMenu.setFrameShape(QFrame.NoFrame) + self.topMenu.setFrameShadow(QFrame.Raised) + self.verticalLayout_8 = QVBoxLayout(self.topMenu) + self.verticalLayout_8.setSpacing(0) + self.verticalLayout_8.setObjectName(u"verticalLayout_8") + self.verticalLayout_8.setContentsMargins(0, 0, 0, 0) + self.btn_start_measuring_routine = QPushButton(self.topMenu) + self.btn_start_measuring_routine.setObjectName(u"btn_start_measuring_routine") + self.btn_start_measuring_routine.setMinimumSize(QSize(60, 60)) + self.btn_start_measuring_routine.setMaximumSize(QSize(16660, 60)) + self.btn_start_measuring_routine.setStyleSheet(u"QPushButton { \n" +" background-position: left center;\n" +" background-repeat: no-repeat;\n" +" border: none;\n" +" border-left: 22px solid transparent;\n" +" background-color: rgb(36, 209, 21);\n" +" text-align: left;\n" +" padding-left: 44px;\n" +" background-image: url(:/icons/images/icons/cil-media-play.png);\n" +"}\n" +"\n" +"QPushButton:hover {\n" +" background-color: rgb(26, 153, 16);\n" +"}\n" +"\n" +"QPushButton:pressed { \n" +" background-color: rgb(20, 120, 12);\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"\n" +"\n" +"") + + self.verticalLayout_8.addWidget(self.btn_start_measuring_routine) + + self.btn_home = QPushButton(self.topMenu) + self.btn_home.setObjectName(u"btn_home") + sizePolicy.setHeightForWidth(self.btn_home.sizePolicy().hasHeightForWidth()) + self.btn_home.setSizePolicy(sizePolicy) + self.btn_home.setMinimumSize(QSize(0, 45)) + self.btn_home.setMaximumSize(QSize(16777215, 16777215)) + self.btn_home.setFont(font2) + self.btn_home.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_home.setLayoutDirection(Qt.LeftToRight) + self.btn_home.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-home.png);") + + self.verticalLayout_8.addWidget(self.btn_home) + + self.btn_adc_control = QPushButton(self.topMenu) + self.btn_adc_control.setObjectName(u"btn_adc_control") + sizePolicy.setHeightForWidth(self.btn_adc_control.sizePolicy().hasHeightForWidth()) + self.btn_adc_control.setSizePolicy(sizePolicy) + self.btn_adc_control.setMinimumSize(QSize(0, 45)) + self.btn_adc_control.setFont(font2) + self.btn_adc_control.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_adc_control.setLayoutDirection(Qt.LeftToRight) + self.btn_adc_control.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-signal-cellular-3.png);") + self.btn_adc_control.setIconSize(QSize(16, 16)) + + self.verticalLayout_8.addWidget(self.btn_adc_control) + + self.btn_laser_control = QPushButton(self.topMenu) + self.btn_laser_control.setObjectName(u"btn_laser_control") + sizePolicy.setHeightForWidth(self.btn_laser_control.sizePolicy().hasHeightForWidth()) + self.btn_laser_control.setSizePolicy(sizePolicy) + self.btn_laser_control.setMinimumSize(QSize(0, 45)) + self.btn_laser_control.setFont(font2) + self.btn_laser_control.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_laser_control.setLayoutDirection(Qt.LeftToRight) + self.btn_laser_control.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-lightbulb.png);") + + self.verticalLayout_8.addWidget(self.btn_laser_control) + + self.btn_probe_control = QPushButton(self.topMenu) + self.btn_probe_control.setObjectName(u"btn_probe_control") + self.btn_probe_control.setEnabled(True) + sizePolicy.setHeightForWidth(self.btn_probe_control.sizePolicy().hasHeightForWidth()) + self.btn_probe_control.setSizePolicy(sizePolicy) + self.btn_probe_control.setMinimumSize(QSize(0, 45)) + self.btn_probe_control.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-action-redo.png);") + + self.verticalLayout_8.addWidget(self.btn_probe_control) + + self.btn_measured_data = QPushButton(self.topMenu) + self.btn_measured_data.setObjectName(u"btn_measured_data") + self.btn_measured_data.setMinimumSize(QSize(0, 45)) + self.btn_measured_data.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-description.png);") + + self.verticalLayout_8.addWidget(self.btn_measured_data) + + self.btn_exit = QPushButton(self.topMenu) + self.btn_exit.setObjectName(u"btn_exit") + sizePolicy.setHeightForWidth(self.btn_exit.sizePolicy().hasHeightForWidth()) + self.btn_exit.setSizePolicy(sizePolicy) + self.btn_exit.setMinimumSize(QSize(60, 45)) + self.btn_exit.setFont(font2) + self.btn_exit.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_exit.setLayoutDirection(Qt.LeftToRight) + self.btn_exit.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-x.png);") + + self.verticalLayout_8.addWidget(self.btn_exit) + + + self.verticalMenuLayout.addWidget(self.topMenu) + + self.bottomMenu = QFrame(self.leftMenuFrame) + self.bottomMenu.setObjectName(u"bottomMenu") + self.bottomMenu.setFrameShape(QFrame.NoFrame) + self.bottomMenu.setFrameShadow(QFrame.Raised) + self.verticalLayout_9 = QVBoxLayout(self.bottomMenu) + self.verticalLayout_9.setSpacing(0) + self.verticalLayout_9.setObjectName(u"verticalLayout_9") + self.verticalLayout_9.setContentsMargins(0, 0, 0, 0) + self.toggleLeftBox = QPushButton(self.bottomMenu) + self.toggleLeftBox.setObjectName(u"toggleLeftBox") + sizePolicy.setHeightForWidth(self.toggleLeftBox.sizePolicy().hasHeightForWidth()) + self.toggleLeftBox.setSizePolicy(sizePolicy) + self.toggleLeftBox.setMinimumSize(QSize(0, 45)) + self.toggleLeftBox.setFont(font2) + self.toggleLeftBox.setCursor(QCursor(Qt.PointingHandCursor)) + self.toggleLeftBox.setLayoutDirection(Qt.LeftToRight) + self.toggleLeftBox.setStyleSheet(u"background-image: url(:/icons/images/icons/icon_settings.png);") + + self.verticalLayout_9.addWidget(self.toggleLeftBox) + + + self.verticalMenuLayout.addWidget(self.bottomMenu) + + + self.verticalLayout_3.addWidget(self.leftMenuFrame) + + + self.appLayout.addWidget(self.leftMenuBg) + + self.extraLeftBox = QFrame(self.bgApp) + self.extraLeftBox.setObjectName(u"extraLeftBox") + self.extraLeftBox.setMinimumSize(QSize(0, 0)) + self.extraLeftBox.setMaximumSize(QSize(0, 16777215)) + self.extraLeftBox.setFrameShape(QFrame.NoFrame) + self.extraLeftBox.setFrameShadow(QFrame.Raised) + self.extraLeftBox.setLineWidth(0) + self.extraColumLayout = QVBoxLayout(self.extraLeftBox) + self.extraColumLayout.setSpacing(0) + self.extraColumLayout.setObjectName(u"extraColumLayout") + self.extraColumLayout.setContentsMargins(0, 0, 0, 0) + self.extraTopBg = QFrame(self.extraLeftBox) + self.extraTopBg.setObjectName(u"extraTopBg") + self.extraTopBg.setMinimumSize(QSize(0, 50)) + self.extraTopBg.setMaximumSize(QSize(16777215, 50)) + self.extraTopBg.setFrameShape(QFrame.NoFrame) + self.extraTopBg.setFrameShadow(QFrame.Raised) + self.verticalLayout_5 = QVBoxLayout(self.extraTopBg) + self.verticalLayout_5.setSpacing(0) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) + self.extraTopLayout = QGridLayout() + self.extraTopLayout.setObjectName(u"extraTopLayout") + self.extraTopLayout.setHorizontalSpacing(10) + self.extraTopLayout.setVerticalSpacing(0) + self.extraTopLayout.setContentsMargins(10, -1, 10, -1) + self.extraIcon = QFrame(self.extraTopBg) + self.extraIcon.setObjectName(u"extraIcon") + self.extraIcon.setMinimumSize(QSize(20, 0)) + self.extraIcon.setMaximumSize(QSize(20, 20)) + self.extraIcon.setFrameShape(QFrame.NoFrame) + self.extraIcon.setFrameShadow(QFrame.Raised) + + self.extraTopLayout.addWidget(self.extraIcon, 0, 0, 1, 1) + + self.extraLabel = QLabel(self.extraTopBg) + self.extraLabel.setObjectName(u"extraLabel") + self.extraLabel.setMinimumSize(QSize(150, 0)) + + self.extraTopLayout.addWidget(self.extraLabel, 0, 1, 1, 1) + + self.extraCloseColumnBtn = QPushButton(self.extraTopBg) + self.extraCloseColumnBtn.setObjectName(u"extraCloseColumnBtn") + self.extraCloseColumnBtn.setMinimumSize(QSize(28, 28)) + self.extraCloseColumnBtn.setMaximumSize(QSize(28, 28)) + self.extraCloseColumnBtn.setCursor(QCursor(Qt.PointingHandCursor)) + icon = QIcon() + icon.addFile(u":/icons/images/icons/icon_close.png", QSize(), QIcon.Normal, QIcon.Off) + self.extraCloseColumnBtn.setIcon(icon) + self.extraCloseColumnBtn.setIconSize(QSize(20, 20)) + + self.extraTopLayout.addWidget(self.extraCloseColumnBtn, 0, 2, 1, 1) + + + self.verticalLayout_5.addLayout(self.extraTopLayout) + + + self.extraColumLayout.addWidget(self.extraTopBg) + + self.extraContent = QFrame(self.extraLeftBox) + self.extraContent.setObjectName(u"extraContent") + self.extraContent.setFrameShape(QFrame.NoFrame) + self.extraContent.setFrameShadow(QFrame.Raised) + self.verticalLayout_12 = QVBoxLayout(self.extraContent) + self.verticalLayout_12.setSpacing(0) + self.verticalLayout_12.setObjectName(u"verticalLayout_12") + self.verticalLayout_12.setContentsMargins(0, 0, 0, 0) + self.extraTopMenu = QFrame(self.extraContent) + self.extraTopMenu.setObjectName(u"extraTopMenu") + self.extraTopMenu.setFrameShape(QFrame.NoFrame) + self.extraTopMenu.setFrameShadow(QFrame.Raised) + self.verticalLayout_11 = QVBoxLayout(self.extraTopMenu) + self.verticalLayout_11.setSpacing(0) + self.verticalLayout_11.setObjectName(u"verticalLayout_11") + self.verticalLayout_11.setContentsMargins(0, 0, 0, 0) + self.btn_share = QPushButton(self.extraTopMenu) + self.btn_share.setObjectName(u"btn_share") + sizePolicy.setHeightForWidth(self.btn_share.sizePolicy().hasHeightForWidth()) + self.btn_share.setSizePolicy(sizePolicy) + self.btn_share.setMinimumSize(QSize(0, 45)) + self.btn_share.setFont(font2) + self.btn_share.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_share.setLayoutDirection(Qt.LeftToRight) + self.btn_share.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-share-boxed.png);") + + self.verticalLayout_11.addWidget(self.btn_share) + + self.btn_adjustments = QPushButton(self.extraTopMenu) + self.btn_adjustments.setObjectName(u"btn_adjustments") + sizePolicy.setHeightForWidth(self.btn_adjustments.sizePolicy().hasHeightForWidth()) + self.btn_adjustments.setSizePolicy(sizePolicy) + self.btn_adjustments.setMinimumSize(QSize(0, 45)) + self.btn_adjustments.setFont(font2) + self.btn_adjustments.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_adjustments.setLayoutDirection(Qt.LeftToRight) + self.btn_adjustments.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-equalizer.png);") + + self.verticalLayout_11.addWidget(self.btn_adjustments) + + self.btn_more = QPushButton(self.extraTopMenu) + self.btn_more.setObjectName(u"btn_more") + sizePolicy.setHeightForWidth(self.btn_more.sizePolicy().hasHeightForWidth()) + self.btn_more.setSizePolicy(sizePolicy) + self.btn_more.setMinimumSize(QSize(0, 45)) + self.btn_more.setFont(font2) + self.btn_more.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_more.setLayoutDirection(Qt.LeftToRight) + self.btn_more.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-layers.png);") + + self.verticalLayout_11.addWidget(self.btn_more) + + + self.verticalLayout_12.addWidget(self.extraTopMenu, 0, Qt.AlignTop) + + self.extraCenter = QFrame(self.extraContent) + self.extraCenter.setObjectName(u"extraCenter") + self.extraCenter.setFrameShape(QFrame.NoFrame) + self.extraCenter.setFrameShadow(QFrame.Raised) + self.verticalLayout_10 = QVBoxLayout(self.extraCenter) + self.verticalLayout_10.setObjectName(u"verticalLayout_10") + self.textEdit = QTextEdit(self.extraCenter) + self.textEdit.setObjectName(u"textEdit") + self.textEdit.setMinimumSize(QSize(222, 0)) + self.textEdit.setStyleSheet(u"background: transparent;") + self.textEdit.setFrameShape(QFrame.NoFrame) + self.textEdit.setReadOnly(True) + + self.verticalLayout_10.addWidget(self.textEdit) + + + self.verticalLayout_12.addWidget(self.extraCenter) + + self.extraBottom = QFrame(self.extraContent) + self.extraBottom.setObjectName(u"extraBottom") + self.extraBottom.setFrameShape(QFrame.NoFrame) + self.extraBottom.setFrameShadow(QFrame.Raised) + + self.verticalLayout_12.addWidget(self.extraBottom) + + + self.extraColumLayout.addWidget(self.extraContent) + + + self.appLayout.addWidget(self.extraLeftBox) + + self.contentBox = QFrame(self.bgApp) + self.contentBox.setObjectName(u"contentBox") + self.contentBox.setFrameShape(QFrame.NoFrame) + self.contentBox.setFrameShadow(QFrame.Raised) + self.verticalLayout_2 = QVBoxLayout(self.contentBox) + self.verticalLayout_2.setSpacing(0) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.contentTopBg = QFrame(self.contentBox) + self.contentTopBg.setObjectName(u"contentTopBg") + self.contentTopBg.setMinimumSize(QSize(0, 50)) + self.contentTopBg.setMaximumSize(QSize(16777215, 50)) + self.contentTopBg.setFrameShape(QFrame.NoFrame) + self.contentTopBg.setFrameShadow(QFrame.Raised) + self.horizontalLayout = QHBoxLayout(self.contentTopBg) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalLayout.setContentsMargins(0, 0, 10, 0) + self.leftBox = QFrame(self.contentTopBg) + self.leftBox.setObjectName(u"leftBox") + sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.leftBox.sizePolicy().hasHeightForWidth()) + self.leftBox.setSizePolicy(sizePolicy1) + self.leftBox.setFocusPolicy(Qt.NoFocus) + self.leftBox.setFrameShape(QFrame.NoFrame) + self.leftBox.setFrameShadow(QFrame.Raised) + self.horizontalLayout_3 = QHBoxLayout(self.leftBox) + self.horizontalLayout_3.setSpacing(0) + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalFrame = QFrame(self.leftBox) + self.verticalFrame.setObjectName(u"verticalFrame") + self.formLayout = QFormLayout(self.verticalFrame) + self.formLayout.setObjectName(u"formLayout") + self.formLayout.setHorizontalSpacing(0) + self.formLayout.setContentsMargins(0, 0, 0, 0) + self.menuBar = QFrame(self.verticalFrame) + self.menuBar.setObjectName(u"menuBar") + sizePolicy2 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.menuBar.sizePolicy().hasHeightForWidth()) + self.menuBar.setSizePolicy(sizePolicy2) + self.menuBar.setMinimumSize(QSize(0, 0)) + self.menuBar.setFocusPolicy(Qt.NoFocus) + self.menuBar.setFrameShadow(QFrame.Raised) + self.horizontalLayout_6 = QHBoxLayout(self.menuBar) + self.horizontalLayout_6.setSpacing(0) + self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") + self.horizontalLayout_6.setSizeConstraint(QLayout.SetDefaultConstraint) + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.menu_file = QToolButton(self.menuBar) + self.menu_file.setObjectName(u"menu_file") + self.menu_file.setEnabled(True) + sizePolicy3 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy3.setHorizontalStretch(0) + sizePolicy3.setVerticalStretch(0) + sizePolicy3.setHeightForWidth(self.menu_file.sizePolicy().hasHeightForWidth()) + self.menu_file.setSizePolicy(sizePolicy3) + self.menu_file.setMinimumSize(QSize(0, 16)) + self.menu_file.setMaximumSize(QSize(16777215, 16777215)) + font3 = QFont() + font3.setFamilies([u"Segoe UI"]) + font3.setPointSize(10) + font3.setBold(False) + font3.setItalic(False) + font3.setKerning(True) + self.menu_file.setFont(font3) + self.menu_file.setMouseTracking(True) + self.menu_file.setLayoutDirection(Qt.LeftToRight) + self.menu_file.setAutoFillBackground(False) + self.menu_file.setStyleSheet(u"") + self.menu_file.setCheckable(False) + self.menu_file.setPopupMode(QToolButton.InstantPopup) + self.menu_file.setToolButtonStyle(Qt.ToolButtonTextOnly) + self.menu_file.setAutoRaise(True) + + self.horizontalLayout_6.addWidget(self.menu_file) + + self.menu_edit = QToolButton(self.menuBar) + self.menu_edit.setObjectName(u"menu_edit") + + self.horizontalLayout_6.addWidget(self.menu_edit) + + self.menu_run = QToolButton(self.menuBar) + self.menu_run.setObjectName(u"menu_run") + self.menu_run.setMinimumSize(QSize(0, 0)) + self.menu_run.setStyleSheet(u"") + self.menu_run.setPopupMode(QToolButton.InstantPopup) + self.menu_run.setToolButtonStyle(Qt.ToolButtonTextOnly) + self.menu_run.setAutoRaise(True) + + self.horizontalLayout_6.addWidget(self.menu_run) + + + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.menuBar) + + self.titleRight = QLabel(self.verticalFrame) + self.titleRight.setObjectName(u"titleRight") + sizePolicy4 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) + sizePolicy4.setHorizontalStretch(0) + sizePolicy4.setVerticalStretch(0) + sizePolicy4.setHeightForWidth(self.titleRight.sizePolicy().hasHeightForWidth()) + self.titleRight.setSizePolicy(sizePolicy4) + self.titleRight.setMaximumSize(QSize(16777215, 45)) + self.titleRight.setFont(font2) + self.titleRight.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) + + self.formLayout.setWidget(0, QFormLayout.LabelRole, self.titleRight) + + + self.horizontalLayout_3.addWidget(self.verticalFrame) + + + self.horizontalLayout.addWidget(self.leftBox) + + self.rightButtons = QFrame(self.contentTopBg) + self.rightButtons.setObjectName(u"rightButtons") + self.rightButtons.setMinimumSize(QSize(0, 28)) + self.rightButtons.setFrameShape(QFrame.NoFrame) + self.rightButtons.setFrameShadow(QFrame.Raised) + self.horizontalLayout_2 = QHBoxLayout(self.rightButtons) + self.horizontalLayout_2.setSpacing(5) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.settingsTopBtn = QPushButton(self.rightButtons) + self.settingsTopBtn.setObjectName(u"settingsTopBtn") + self.settingsTopBtn.setMinimumSize(QSize(28, 28)) + self.settingsTopBtn.setMaximumSize(QSize(28, 28)) + self.settingsTopBtn.setCursor(QCursor(Qt.PointingHandCursor)) + icon1 = QIcon() + icon1.addFile(u":/icons/images/icons/icon_settings.png", QSize(), QIcon.Normal, QIcon.Off) + self.settingsTopBtn.setIcon(icon1) + self.settingsTopBtn.setIconSize(QSize(20, 20)) + + self.horizontalLayout_2.addWidget(self.settingsTopBtn) + + self.minimizeAppBtn = QPushButton(self.rightButtons) + self.minimizeAppBtn.setObjectName(u"minimizeAppBtn") + self.minimizeAppBtn.setMinimumSize(QSize(28, 28)) + self.minimizeAppBtn.setMaximumSize(QSize(28, 28)) + self.minimizeAppBtn.setCursor(QCursor(Qt.PointingHandCursor)) + icon2 = QIcon() + icon2.addFile(u":/icons/images/icons/icon_minimize.png", QSize(), QIcon.Normal, QIcon.Off) + self.minimizeAppBtn.setIcon(icon2) + self.minimizeAppBtn.setIconSize(QSize(20, 20)) + + self.horizontalLayout_2.addWidget(self.minimizeAppBtn) + + self.maximizeRestoreAppBtn = QPushButton(self.rightButtons) + self.maximizeRestoreAppBtn.setObjectName(u"maximizeRestoreAppBtn") + self.maximizeRestoreAppBtn.setMinimumSize(QSize(28, 28)) + self.maximizeRestoreAppBtn.setMaximumSize(QSize(28, 28)) + font4 = QFont() + font4.setFamilies([u"Segoe UI"]) + font4.setPointSize(10) + font4.setBold(False) + font4.setItalic(False) + font4.setStyleStrategy(QFont.PreferDefault) + self.maximizeRestoreAppBtn.setFont(font4) + self.maximizeRestoreAppBtn.setCursor(QCursor(Qt.PointingHandCursor)) + icon3 = QIcon() + icon3.addFile(u":/icons/images/icons/icon_maximize.png", QSize(), QIcon.Normal, QIcon.Off) + self.maximizeRestoreAppBtn.setIcon(icon3) + self.maximizeRestoreAppBtn.setIconSize(QSize(20, 20)) + + self.horizontalLayout_2.addWidget(self.maximizeRestoreAppBtn) + + self.closeAppBtn = QPushButton(self.rightButtons) + self.closeAppBtn.setObjectName(u"closeAppBtn") + self.closeAppBtn.setMinimumSize(QSize(28, 28)) + self.closeAppBtn.setMaximumSize(QSize(28, 28)) + self.closeAppBtn.setCursor(QCursor(Qt.PointingHandCursor)) + self.closeAppBtn.setIcon(icon) + self.closeAppBtn.setIconSize(QSize(20, 20)) + + self.horizontalLayout_2.addWidget(self.closeAppBtn) + + + self.horizontalLayout.addWidget(self.rightButtons, 0, Qt.AlignRight) + + + self.verticalLayout_2.addWidget(self.contentTopBg) + + self.contentBottom = QFrame(self.contentBox) + self.contentBottom.setObjectName(u"contentBottom") + self.contentBottom.setFrameShape(QFrame.NoFrame) + self.contentBottom.setFrameShadow(QFrame.Raised) + self.verticalLayout_6 = QVBoxLayout(self.contentBottom) + self.verticalLayout_6.setSpacing(0) + self.verticalLayout_6.setObjectName(u"verticalLayout_6") + self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) + self.content = QFrame(self.contentBottom) + self.content.setObjectName(u"content") + self.content.setFrameShape(QFrame.NoFrame) + self.content.setFrameShadow(QFrame.Raised) + self.horizontalLayout_4 = QHBoxLayout(self.content) + self.horizontalLayout_4.setSpacing(0) + self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) + self.pagesContainer = QFrame(self.content) + self.pagesContainer.setObjectName(u"pagesContainer") + self.pagesContainer.setStyleSheet(u"") + self.pagesContainer.setFrameShape(QFrame.NoFrame) + self.pagesContainer.setFrameShadow(QFrame.Raised) + self.gridLayout_5 = QGridLayout(self.pagesContainer) + self.gridLayout_5.setObjectName(u"gridLayout_5") + self.gridLayout_5.setContentsMargins(10, 10, 10, 10) + self.stackedWidget = QStackedWidget(self.pagesContainer) + self.stackedWidget.setObjectName(u"stackedWidget") + self.stackedWidget.setStyleSheet(u"background: transparent;") + self.home = QWidget() + self.home.setObjectName(u"home") + self.home.setStyleSheet(u"") + self.gridLayout_7 = QGridLayout(self.home) + self.gridLayout_7.setObjectName(u"gridLayout_7") + self.home_layout = QGridLayout() + self.home_layout.setObjectName(u"home_layout") + + self.gridLayout_7.addLayout(self.home_layout, 0, 0, 1, 1) + + self.stackedWidget.addWidget(self.home) + self.prober_control = QWidget() + self.prober_control.setObjectName(u"prober_control") + self.verticalLayout_20 = QVBoxLayout(self.prober_control) + self.verticalLayout_20.setObjectName(u"verticalLayout_20") + self.prober_control_layout = QGridLayout() + self.prober_control_layout.setObjectName(u"prober_control_layout") + self.prober_control_layout.setContentsMargins(1, 2, 3, -1) + + self.verticalLayout_20.addLayout(self.prober_control_layout) + + self.stackedWidget.addWidget(self.prober_control) + self.adc_control = QWidget() + self.adc_control.setObjectName(u"adc_control") + self.gridLayout_6 = QGridLayout(self.adc_control) + self.gridLayout_6.setObjectName(u"gridLayout_6") + self.adc_control_layout = QGridLayout() + self.adc_control_layout.setObjectName(u"adc_control_layout") + + self.gridLayout_6.addLayout(self.adc_control_layout, 0, 0, 1, 1) + + self.stackedWidget.addWidget(self.adc_control) + self.laser_control = QWidget() + self.laser_control.setObjectName(u"laser_control") + self.gridLayout_4 = QGridLayout(self.laser_control) + self.gridLayout_4.setObjectName(u"gridLayout_4") + self.laser_control_layout = QGridLayout() + self.laser_control_layout.setObjectName(u"laser_control_layout") + + self.gridLayout_4.addLayout(self.laser_control_layout, 0, 0, 1, 1) + + self.stackedWidget.addWidget(self.laser_control) + self.measured_data = QWidget() + self.measured_data.setObjectName(u"measured_data") + self.gridLayout_2 = QGridLayout(self.measured_data) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.measured_data_layout = QGridLayout() + self.measured_data_layout.setObjectName(u"measured_data_layout") + + self.gridLayout_2.addLayout(self.measured_data_layout, 0, 0, 1, 1) + + self.stackedWidget.addWidget(self.measured_data) + + self.gridLayout_5.addWidget(self.stackedWidget, 0, 0, 1, 1) + + + self.horizontalLayout_4.addWidget(self.pagesContainer) + + self.extraRightBox = QFrame(self.content) + self.extraRightBox.setObjectName(u"extraRightBox") + self.extraRightBox.setMinimumSize(QSize(0, 0)) + self.extraRightBox.setMaximumSize(QSize(0, 16777215)) + self.extraRightBox.setFrameShape(QFrame.NoFrame) + self.extraRightBox.setFrameShadow(QFrame.Raised) + self.verticalLayout_7 = QVBoxLayout(self.extraRightBox) + self.verticalLayout_7.setSpacing(0) + self.verticalLayout_7.setObjectName(u"verticalLayout_7") + self.verticalLayout_7.setContentsMargins(0, 0, 0, 0) + self.themeSettingsTopDetail = QFrame(self.extraRightBox) + self.themeSettingsTopDetail.setObjectName(u"themeSettingsTopDetail") + self.themeSettingsTopDetail.setMaximumSize(QSize(16777215, 3)) + self.themeSettingsTopDetail.setFrameShape(QFrame.NoFrame) + self.themeSettingsTopDetail.setFrameShadow(QFrame.Raised) + + self.verticalLayout_7.addWidget(self.themeSettingsTopDetail) + + self.contentSettings = QFrame(self.extraRightBox) + self.contentSettings.setObjectName(u"contentSettings") + self.contentSettings.setFrameShape(QFrame.NoFrame) + self.contentSettings.setFrameShadow(QFrame.Raised) + self.verticalLayout_13 = QVBoxLayout(self.contentSettings) + self.verticalLayout_13.setSpacing(0) + self.verticalLayout_13.setObjectName(u"verticalLayout_13") + self.verticalLayout_13.setContentsMargins(0, 0, 0, 0) + self.txt_logs = QTextEdit(self.contentSettings) + self.txt_logs.setObjectName(u"txt_logs") + + self.verticalLayout_13.addWidget(self.txt_logs) + + self.topMenus = QFrame(self.contentSettings) + self.topMenus.setObjectName(u"topMenus") + self.topMenus.setFrameShape(QFrame.NoFrame) + self.topMenus.setFrameShadow(QFrame.Raised) + self.verticalLayout_14 = QVBoxLayout(self.topMenus) + self.verticalLayout_14.setSpacing(0) + self.verticalLayout_14.setObjectName(u"verticalLayout_14") + self.verticalLayout_14.setContentsMargins(0, 0, 0, 0) + self.btn_print = QPushButton(self.topMenus) + self.btn_print.setObjectName(u"btn_print") + sizePolicy.setHeightForWidth(self.btn_print.sizePolicy().hasHeightForWidth()) + self.btn_print.setSizePolicy(sizePolicy) + self.btn_print.setMinimumSize(QSize(0, 45)) + self.btn_print.setFont(font2) + self.btn_print.setCursor(QCursor(Qt.PointingHandCursor)) + self.btn_print.setLayoutDirection(Qt.LeftToRight) + self.btn_print.setStyleSheet(u"background-image: url(:/icons/images/icons/cil-print.png);") + + self.verticalLayout_14.addWidget(self.btn_print) + + + self.verticalLayout_13.addWidget(self.topMenus, 0, Qt.AlignTop) + + + self.verticalLayout_7.addWidget(self.contentSettings) + + + self.horizontalLayout_4.addWidget(self.extraRightBox) + + + self.verticalLayout_6.addWidget(self.content) + + self.bottomBar = QFrame(self.contentBottom) + self.bottomBar.setObjectName(u"bottomBar") + self.bottomBar.setMinimumSize(QSize(0, 22)) + self.bottomBar.setMaximumSize(QSize(16777215, 22)) + self.bottomBar.setFrameShape(QFrame.NoFrame) + self.bottomBar.setFrameShadow(QFrame.Raised) + self.horizontalLayout_5 = QHBoxLayout(self.bottomBar) + self.horizontalLayout_5.setSpacing(0) + self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.creditsLabel = QLabel(self.bottomBar) + self.creditsLabel.setObjectName(u"creditsLabel") + self.creditsLabel.setMaximumSize(QSize(16777215, 16)) + font5 = QFont() + font5.setFamilies([u"Segoe UI"]) + font5.setBold(False) + font5.setItalic(False) + self.creditsLabel.setFont(font5) + self.creditsLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) + + self.horizontalLayout_5.addWidget(self.creditsLabel) + + self.version = QLabel(self.bottomBar) + self.version.setObjectName(u"version") + self.version.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + + self.horizontalLayout_5.addWidget(self.version) + + self.frame_size_grip = QFrame(self.bottomBar) + self.frame_size_grip.setObjectName(u"frame_size_grip") + self.frame_size_grip.setMinimumSize(QSize(20, 0)) + self.frame_size_grip.setMaximumSize(QSize(20, 16777215)) + self.frame_size_grip.setFrameShape(QFrame.NoFrame) + self.frame_size_grip.setFrameShadow(QFrame.Raised) + + self.horizontalLayout_5.addWidget(self.frame_size_grip) + + + self.verticalLayout_6.addWidget(self.bottomBar) + + + self.verticalLayout_2.addWidget(self.contentBottom) + + + self.appLayout.addWidget(self.contentBox) + + + self.appMargins.addWidget(self.bgApp) + + MainWindow.setCentralWidget(self.styleSheet) + + self.retranslateUi(MainWindow) + + self.stackedWidget.setCurrentIndex(4) + + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + self.titleLeftApp.setText(QCoreApplication.translate("MainWindow", u"PyDracula", None)) + self.titleLeftDescription.setText(QCoreApplication.translate("MainWindow", u"Modern GUI / Flat Style", None)) + self.toggleButton.setText(QCoreApplication.translate("MainWindow", u"Hide", None)) + self.btn_start_measuring_routine.setText(QCoreApplication.translate("MainWindow", u"PushButton", None)) + self.btn_home.setText(QCoreApplication.translate("MainWindow", u"Home", None)) + self.btn_adc_control.setText(QCoreApplication.translate("MainWindow", u"ADC Control", None)) + self.btn_laser_control.setText(QCoreApplication.translate("MainWindow", u"Laser Control", None)) + self.btn_probe_control.setText(QCoreApplication.translate("MainWindow", u"Probe Control", None)) + self.btn_measured_data.setText(QCoreApplication.translate("MainWindow", u"Measured Data", None)) + self.btn_exit.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) + self.toggleLeftBox.setText(QCoreApplication.translate("MainWindow", u"Left Box", None)) + self.extraLabel.setText(QCoreApplication.translate("MainWindow", u"Left Box", None)) +#if QT_CONFIG(tooltip) + self.extraCloseColumnBtn.setToolTip(QCoreApplication.translate("MainWindow", u"Close left box", None)) +#endif // QT_CONFIG(tooltip) + self.extraCloseColumnBtn.setText("") + self.btn_share.setText(QCoreApplication.translate("MainWindow", u"Share", None)) + self.btn_adjustments.setText(QCoreApplication.translate("MainWindow", u"Adjustments", None)) + self.btn_more.setText(QCoreApplication.translate("MainWindow", u"More", None)) + self.textEdit.setHtml(QCoreApplication.translate("MainWindow", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" +"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">\n" +"p, li { white-space: pre-wrap; }\n" +"</style></head><body style=\" font-family:'Segoe UI'; font-size:10pt; font-weight:400; font-style:normal;\">\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt; font-weight:600; color:#ff79c6;\">PyDracula</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#ffffff;\">An interface created using Python and PySide (support for PyQt), and with colors based on the Dracula theme created by Zeno Rocha.</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-inde" + "nt:0; text-indent:0px;\"><span style=\" color:#ffffff;\">MIT License</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" color:#bd93f9;\">Created by: Wanderson M. Pimenta</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt; font-weight:600; color:#ff79c6;\">Convert UI</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:9pt; color:#ffffff;\">pyside6-uic main.ui > ui_main.py</span></p>\n" +"<p align=\"center\" style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt; font-weight:600; color:#ff79c6;\">Convert QRC</span></p>\n" +"<p align=\"center\" " + "style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:9pt; color:#ffffff;\">pyside6-rcc resources.qrc -o resources_rc.py</span></p></body></html>", None)) + self.menu_file.setText(QCoreApplication.translate("MainWindow", u"File", None)) + self.menu_edit.setText(QCoreApplication.translate("MainWindow", u"Edit", None)) + self.menu_run.setText(QCoreApplication.translate("MainWindow", u"Run", None)) + self.titleRight.setText(QCoreApplication.translate("MainWindow", u"FlexSensor 6", None)) +#if QT_CONFIG(tooltip) + self.settingsTopBtn.setToolTip(QCoreApplication.translate("MainWindow", u"Settings", None)) +#endif // QT_CONFIG(tooltip) + self.settingsTopBtn.setText("") +#if QT_CONFIG(tooltip) + self.minimizeAppBtn.setToolTip(QCoreApplication.translate("MainWindow", u"Minimize", None)) +#endif // QT_CONFIG(tooltip) + self.minimizeAppBtn.setText("") +#if QT_CONFIG(tooltip) + self.maximizeRestoreAppBtn.setToolTip(QCoreApplication.translate("MainWindow", u"Maximize", None)) +#endif // QT_CONFIG(tooltip) + self.maximizeRestoreAppBtn.setText("") +#if QT_CONFIG(tooltip) + self.closeAppBtn.setToolTip(QCoreApplication.translate("MainWindow", u"Close", None)) +#endif // QT_CONFIG(tooltip) + self.closeAppBtn.setText("") + self.btn_print.setText(QCoreApplication.translate("MainWindow", u"Print", None)) + self.creditsLabel.setText(QCoreApplication.translate("MainWindow", u"Flexsensor 6", None)) + self.version.setText(QCoreApplication.translate("MainWindow", u"v1.0.3", None)) + # retranslateUi + diff --git a/src/FlexSensor/MainWindow/view/StepThroughView.py b/src/FlexSensor/MainWindow/view/StepThroughView.py new file mode 100644 index 0000000000000000000000000000000000000000..37e506f32435d5834af85a0cd03abbbdfa61b4c4 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/StepThroughView.py @@ -0,0 +1,126 @@ +import traceback +from PySide6.QtWidgets import ( + QMainWindow, QWidget, QGridLayout, QPushButton, QLineEdit, +) +from PySide6.QtGui import QIcon + +import Prober as Prober + +import ConfigHandler.controller.VASInputFileParser as input_file_parser +from Prober.controller.ProberController import ProberController +from constants.FlexsensorConstants import Probe + + +class StepThroughView(QMainWindow): + def __init__(self, grouped_structures, prober: ProberController): + super(StepThroughView, self).__init__() + self.prober = prober + self.grouped_structures = grouped_structures + self.idx_struct = 0 + self.idx_group = 0 + self.init_UI() + self.move_to_structure() + self.msg_server = None + + + def init_UI(self): + # create a layout + layout = QGridLayout() + widget = QWidget() + # add a label + self.group_name = QLineEdit("This is a label") + self.structure_name = QLineEdit("This is a label") + # add a button + self.btn_prev = QPushButton("Previous") + self.btn_prev.clicked.connect(self.on_click_prev) + + # add a button + self.btn_next = QPushButton("Next") + self.btn_next.clicked.connect(self.on_click_next) + + self.btn_search_for_light = QPushButton("Search for light") + self.btn_search_for_light.clicked.connect(self.on_search_for_light) + + # Add the widgets to the layout + layout.addWidget(self.group_name, 0, 0, 1, 2) + layout.addWidget(self.structure_name, 1, 0, 1, 2) + layout.addWidget(self.btn_prev, 2, 0) + layout.addWidget(self.btn_next, 2, 1) + + + widget.setLayout(layout) + self.setCentralWidget(widget) + #self.layout.setLayout(tree) + + self.setWindowTitle(f'Step Structure') + self.setWindowIcon(QIcon('icon.ico')) + + def move_to_structure(self): + + self.group: str = list(self.grouped_structures)[self.idx_group] + self.structures: dict = self.grouped_structures[self.group] + self.structure: input_file_parser.Structure = list(self.structures.values())[self.idx_struct] + try: + #with Prober.velox_api.MessageServerInterface() as self.msg_server: + #velox_api.MoveChuck(0, 0) + #print(f"New structure group ({self.idx_groups}): {self.groups}. {len(structures)} structures in group.") + + + # Move to die + #print(f"Move chuck (first probe) to X({self.structure.x_in}), Y({self.structure.y_in}).") + self.prober.move_chuck(self.structure.x_in, self.structure.y_in) + + try: + if self.structure.in_out_diff_x > 50: + #print( + # f"Move second probe to X({self.structure.x_out}), Y({self.structure.y_out}) " + # f"- Difference x({self.structure.in_out_diff_x}) y({self.structure.in_out_diff_y})" + #) + self.prober.opt_if.move_optical_probe(Probe.OUTPUT, self.structure.in_out_diff_x, self.structure.in_out_diff_y, pos_ref="H") + #self.msg_server.sendSciCommand("MoveOpticalProbe",rparams='1 %s %s H' % + # (self.structure.in_out_diff_x, self.structure.in_out_diff_y) + #) + else: + raise Exception("Optical Probe Home not safe! x difference < 50 um: {self.structure.in_out_diff_x}") + except Exception as e: + print("error", f"Can't move optical probe safely. {e}") + print(( + type(e), f"Can't move optical probe safely. {e}. Omitting Structure!", traceback.format_exc() + )) + print("warning", f"[!] Omitting structure {self.structure.name}") + except Exception as e: + print("error", f"Can't move optical probe safely. {e}") + print(( + type(e), f"Can't move optical probe safely. {e}. Omitting Structure!", traceback.format_exc() + )) + + self.group_name.setText(f"Group: {self.group}") + self.structure_name.setText(f"Structure: {self.structure.name}") + + def on_search_for_light(self): + self.prober.opt_if.store_optical_probe_pos() + #self.prober.opt_if.restore_optical_probe_motor_pos(probe=Probe.INPUT) + #self.prober.opt_if.restore_optical_probe_motor_pos(probe=Probe.OUTPUT) + + + def on_click_prev(self): + self.idx_struct = self.idx_struct - 1 + if self.idx_struct < 0: + self.idx_group = self.idx_group - 1 + if self.idx_group < 0: + self.idx_group = len(self.grouped_structures) - 1 + + group: str = list(self.grouped_structures)[self.idx_group] + self.idx_struct = len(self.grouped_structures[group]) - 1 + self.move_to_structure() + + def on_click_next(self): + self.idx_struct = self.idx_struct + 1 + if self.idx_struct >= len(self.structures): + self.idx_group = self.idx_group + 1 + if self.idx_group >= len(self.grouped_structures): + self.idx_group = 0 + self.idx_struct = 0 + self.move_to_structure() + + \ No newline at end of file diff --git a/src/FlexSensor/MainWindow/view/__init__.py b/src/FlexSensor/MainWindow/view/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py b/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..cf4b98992cb76d348fc55ba5e0805b32ec10628d --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py @@ -0,0 +1,93 @@ +import sys + +from PySide6.QtWidgets import QWidget, QVBoxLayout, QGroupBox, QGridLayout, QLineEdit, QLabel, QProgressBar + +import __version__ +from MainWindow.view import MainView +from Prober.view.widgets.ProberPositionWidget import ProberPositionWidget + + +class HomeStatusWidget(QWidget): + + def __init__(self, view: MainView): + super().__init__() + + self.velox_kernel_version = None + self.python_version = None + self.script_version = None + + self.view: MainView = view + layout = QGridLayout() + layout.addWidget(self.init_UI_wafer_info(), 0, 0, 1, 1) + layout.addWidget(self.init_UI_status_wdg(), 0, 1, 1, 1) + layout.addWidget(self.init_UI_version_info(), 1, 0, 1, 2) + + self.setLayout(layout) + + def init_UI_wafer_info(self): + + grid_group_box = QGroupBox() + layout = QGridLayout() + + self.tb_wafer_version = QLineEdit(parent=self, text=str(self.view.model.vaut_config.wafer_version)) + #self.tb_wafer_version.textChanged.connect(self.on_wafer_version_changed) + layout.addWidget(QLabel("Wafer Version"), 0, 0, 1, 1) # row, column, rowspan, colspan + layout.addWidget(self.tb_wafer_version, 1, 0, 1, 2) # row, column, rowspan, colspan + + self.tb_wafer_nr = QLineEdit(parent=self, text=str(self.view.model.vaut_config.wafer_nr)) + #self.tb_wafer_nr.textChanged.connect(self.on_wafer_nr_changed) + layout.addWidget(QLabel("Wafer number"), 0, 2, 1, 1) + layout.addWidget(self.tb_wafer_nr, 1, 2, 1, 2) + + grid_group_box.setLayout(layout) + + return grid_group_box + + def init_UI_status_wdg(self): + grid_group_box = QGroupBox() + layout = QVBoxLayout() + layout.addWidget(ProberPositionWidget(self.view.model.prober_model, "Horizontal")) + + self.progress = QProgressBar(self) + self.progress.setStyleSheet( + "#GreenProgressBar { min-height: 12px; max-height: 12px; border-radius: 6px;}") + layout.addWidget(self.progress) + self.progress.setFixedHeight(self.progress.sizeHint().height() / 2) + + grid_group_box.setLayout(layout) + + return grid_group_box + + def init_UI_version_info(self): + + grid_group_box = QGroupBox() + layout = QGridLayout() + try: + self.velox_kernel_version = QLineEdit(parent=self, + text=self.view.model.prober_model.report_velox_kernel_version()) + + except Exception as e: + print(e) + self.velox_kernel_version = QLineEdit( + parent=self, text="Velox kernel version not available") + + self.velox_kernel_version.setReadOnly(True) + # self.velox_kernel_version.setEnabled(False) + layout.addWidget(QLabel("Velox Kernel Version"), 2, 0) + layout.addWidget(self.velox_kernel_version, 3, 0) + + self.python_version = QLineEdit(parent=self, text=str(sys.version)) + self.python_version.setReadOnly(True) + # self.python_version.setEnabled(False) + layout.addWidget(QLabel("Python Version"), 2, 1) + layout.addWidget(self.python_version, 3, 1) + + self.script_version = QLineEdit(parent=self, text=__version__.__version__) + self.script_version.setReadOnly(True) + self.script_version.setEnabled(False) + layout.addWidget(QLabel("Script Version"), 2, 2) + layout.addWidget(self.script_version, 3, 2) + + grid_group_box.setLayout(layout) + + return grid_group_box diff --git a/src/FlexSensor/MainWindow/view/widgets/ScopeWidget.py b/src/FlexSensor/MainWindow/view/widgets/ScopeWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..8301a8aa6287a6a254a7a525a3e76c1887130059 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/ScopeWidget.py @@ -0,0 +1,32 @@ +import pyqtgraph as pg +from PySide6.QtWidgets import QVBoxLayout, QWidget +from pyqtgraph.dockarea import DockArea, Dock + +from MainWindow.view import MainView + + +class ScopeWidget(QWidget): + + def __init__(self, parent_view: MainView): + super().__init__() + self.parent_view = parent_view + layout = QVBoxLayout() + area = DockArea() + + d1 = Dock("Analog Discovery 2") + d2 = Dock("Filtered") + area.addDock(d1, 'bottom') + area.addDock(d2, 'bottom', d1) + + self.scope_original = pg.PlotWidget(title="AD2 Acquisition") + # self.scope_original.plot(np.random.normal(size=100)*1e12) + self.scope_original.plotItem.showGrid(x=True, y=True, alpha=1) + d1.addWidget(self.scope_original) + + self.scope_filtered = pg.PlotWidget(title="Filtered Data") + # self.scope_filtered.plot(np.random.normal(size=100)) + self.scope_filtered.plotItem.showGrid(x=True, y=True, alpha=1) + d2.addWidget(self.scope_filtered) + layout.addWidget(area) + self.setMinimumWidth(800) + self.setLayout(layout) diff --git a/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py new file mode 100644 index 0000000000000000000000000000000000000000..240ac93a1dc076903db0255eb560d5d92d0445f9 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py @@ -0,0 +1,323 @@ +from PySide6.QtWidgets import QWidget, QGridLayout, QGroupBox, QLineEdit, QPushButton, QLabel, QDoubleSpinBox + +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from ConfigHandler.view.ConfigView import ConfigView + + +class WidgetSettingsInFilesFolders(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + + self.btn_select_list_of_structures = QPushButton(parent=self, text="...") + self.btn_select_working_directory = QPushButton(parent=self, text="...") + + self.layout = QGridLayout() + self.init_UI() + + def init_UI(self): + grid_group_box = QGroupBox("Input Files") + layout = QGridLayout() + # Working directory + self.tb_working_directory = QLineEdit(parent=self, text=str(self.vaut_config.get_output_directory().relative)) + self.btn_select_working_directory.setMaximumWidth(self.btn_select_working_directory.sizeHint().height()) + layout.addWidget(QLabel("Working directory"), 0, 0) + layout.addWidget(self.tb_working_directory, 0, 1) # row, column, rowspan, colspan + layout.addWidget(self.btn_select_working_directory, 0, 3) # row, column, rowspan, colspan + + # List of structures + self.tb_list_of_structures = QLineEdit(parent=self, text=str(self.vaut_config.wafer_config.get_structure_file().relative)) + self.btn_select_list_of_structures.setMaximumWidth(self.btn_select_list_of_structures.sizeHint().height()) + layout.addWidget(QLabel("Input Structure File"), 1, 0) + layout.addWidget(self.tb_list_of_structures, 1, 1) # row, column, rowspan, colspan + layout.addWidget(self.btn_select_list_of_structures, 1, 3) # row, column, rowspan, colspan + + grid_group_box.setLayout(layout) + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + + +class WidgetSettingsOutFilesFolders(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + + self.tb_log_file = QLineEdit( + text="self.vaut_config.wafer_config.get_log_file().filename") + self.tb_measurement_output = QLineEdit( + text="self.vaut_config.wafer_config.get_measurement_output().filename") + self.tb_mat_files_output = QLineEdit( + text="self.vaut_config.wafer_config.get_measurement_mat_file().filename") + self.tb_bookmark_file = QLineEdit( + text="self.vaut_config.wafer_config.get_bookmark_file()._mat_filename") + self.tb_scope_image_file = QLineEdit( + text="self.vaut_config.wafer_config.get_scope_image_file()._mat_filename") + + + + self.layout = QGridLayout() + self.init_UI() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Output Files") + grid_group_box.setLayout(layout) + + + + + + + self.lbl_log_file = QLabel(parent=self) + self.tb_log_file.textChanged.connect(self.on_tb_log_file_text_changed) + self.on_tb_log_file_text_changed(self.tb_log_file.text()) + layout.addWidget(QLabel("Log File"), 0, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_log_file, 0, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_log_file, 1, 0, 1, 2) # row, column, rowspan, colspan + + # measurement output + self.lbl_measurement_output = QLabel(parent=self) + self.tb_measurement_output.textChanged.connect(self.on_tb_measurement_output_text_changed) + self.on_tb_measurement_output_text_changed(self.tb_measurement_output.text()) + layout.addWidget(QLabel("Measurement output"), 2, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_measurement_output, 2, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_measurement_output, 3, 0, 1, 2) # row, column, rowspan, colspan + + # Mat files output + self.lbl_mat_files_output = QLabel(parent=self) + self.on_tb_mat_files_output_text_changed(self.tb_mat_files_output.text()) + + self.tb_mat_files_output.textChanged.connect(self.on_tb_mat_files_output_text_changed) + layout.addWidget(QLabel("Matlab Files"), 4, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_mat_files_output, 4, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_mat_files_output, 5, 0, 1, 2) # row, column, rowspan, colspan + + # bookmark files + self.lbl_bookmark_file = QLabel(parent=self) + self.on_tb_bookmark_file_text_changed(self.tb_bookmark_file.text()) + self.tb_bookmark_file.textChanged.connect(self.on_tb_bookmark_file_text_changed) + self.tb_scope_image_file.textChanged.connect(self.on_tb_scope_image_file_text_changed) + layout.addWidget(QLabel("Bookmark files"), 6, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_bookmark_file, 6, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_bookmark_file, 7, 0, 1, 2) # row, column, rowspan, colspan + + # scope shots + self.lbl_scope_image_file = QLabel(parent=self) + self.on_tb_scope_image_file_text_changed(self.tb_scope_image_file.text()) + layout.addWidget(QLabel("Scope Shots"), 8, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_scope_image_file, 8, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_scope_image_file, 9, 0, 1, 2) + + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + + def on_tb_scope_image_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_scope_image_file().set_obj(value) + val = self.vaut_config.wafer_config.get_scope_image_file().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_scope_image_file.setText(val) + # set label hover text + self.lbl_scope_image_file.setToolTip(self.vaut_config.wafer_config.get_scope_image_file().absolute) + + def on_tb_measurement_output_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_measurement_output().set_obj(value) + val = self.vaut_config.wafer_config.get_measurement_output().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_measurement_output.setText(val) + # set label hover text + self.lbl_measurement_output.setToolTip(self.vaut_config.wafer_config.get_scope_image_file().absolute) + + def on_tb_bookmark_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_bookmark_file().set_obj(value) + val = self.vaut_config.wafer_config.get_bookmark_file().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_bookmark_file.setText(val) + # set label hover text + self.lbl_bookmark_file.setToolTip(self.vaut_config.wafer_config.get_bookmark_file().absolute) + + config = self.vaut_config + + def on_tb_mat_files_output_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_measurement_mat_file().set_obj(value) + val = self.vaut_config.wafer_config.get_measurement_mat_file().relative.replace( + self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_mat_files_output.setText(val) + self.lbl_mat_files_output.setToolTip(self.vaut_config.wafer_config.get_measurement_mat_file().absolute) + + def on_tb_log_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_log_file().set_obj(value) + + val = self.vaut_config.wafer_config.get_log_file().relative.replace(self.vaut_config.get_output_directory().relative, "<b>wd</b>") + self.lbl_log_file.setText(val) + self.lbl_log_file.setToolTip(self.vaut_config.wafer_config.get_log_file().absolute) + +class WidgetAD2Settings(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + self.c = ConfigView(vaut_config) + + + self.num_sample_rate = QDoubleSpinBox() + self.num_total_samples = QDoubleSpinBox() + self.num_sample_time = QDoubleSpinBox() + + self.btn_select_ad2_raw_out_file = QPushButton(parent=self, text="....") + + self.btn_select_ad2_raw_out_file.clicked.connect(self.show_config) + self.layout = QGridLayout() + self.init_UI() + + + def show_config(self): + self.c = ConfigView(self.vaut_config) + self.c.show() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Analog Discovery 2 Settings") + grid_group_box.setLayout(layout) + + lbl_sample_rate = QLabel("Sample Rate") + layout.addWidget(lbl_sample_rate, 1, 0) + self.num_sample_rate.valueChanged.connect(lambda v: self.vaut_config.ad2_device_config.set_sample_rate(v)) + self.num_sample_rate.setRange(0, 10**8) + self.num_sample_rate.setSingleStep(1) + self.num_sample_rate.setValue(self.vaut_config.ad2_device_config.get_sample_rate()) + self.num_sample_rate.setSuffix(" Hz") + self.num_sample_rate.setDecimals(3) + self.num_sample_rate.setKeyboardTracking(False) + layout.addWidget(self.num_sample_rate, 1, 1, 1, 2) + + lbl_total_samples = QLabel("Total Samples") + layout.addWidget(lbl_total_samples, 2, 0) + self.num_total_samples.setRange(0, 10**8) + self.num_total_samples.setSingleStep(1) + self.num_total_samples.setValue(self.vaut_config.ad2_device_config.get_total_samples()) + self.num_total_samples.setDecimals(3) + self.num_total_samples.setKeyboardTracking(False) + layout.addWidget(self.num_total_samples, 2, 1, 1, 2) + + lbl_sample_time = QLabel("Sample Time") + layout.addWidget(lbl_sample_time, 3, 0) + self.num_sample_time.setRange(0, 10**8) + self.num_sample_time.setSingleStep(1) + self.num_sample_time.setValue(self.vaut_config.ad2_device_config.get_sample_time()) + self.num_sample_time.setSuffix(" s") + self.num_sample_time.setDecimals(3) + self.num_sample_time.setKeyboardTracking(False) + layout.addWidget(self.num_sample_time, 3, 1, 1, 2) + + lbl_ad2_raw_out_file = QLabel("Raw Out File") + layout.addWidget(lbl_ad2_raw_out_file, 4, 0) + tb_ad2_raw_out_file = QLineEdit(text=self.vaut_config.ad2_device_config.get_ad2_raw_out_file().relative) + layout.addWidget(tb_ad2_raw_out_file, 4, 1) + layout.addWidget(self.btn_select_ad2_raw_out_file, 4, 2) + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + +class WidgetLaserSettings(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + self.c = None + + + self.num_wavelength_sweep_start = QDoubleSpinBox() + self.num_wavelength_range_stop = QDoubleSpinBox() + self.num_velocity = QDoubleSpinBox() + self.num_acceleration = QDoubleSpinBox() + self.num_deceleration = QDoubleSpinBox() + + + #self.btn_select_ad2_raw_out_file = QPushButton(parent=self, text="....") + + #self.btn_select_ad2_raw_out_file.clicked.connect(self.show_config) + self.layout = QGridLayout() + self.init_UI() + + + def show_config(self): + self.c = ConfigView(self.vaut_config) + self.c.show() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Laser Settings") + grid_group_box.setLayout(layout) + + lbl_wavelength_sweep_start = QLabel("Wavelength Sweep") + layout.addWidget(lbl_wavelength_sweep_start, 1, 0) + + + + self.num_wavelength_sweep_start.setRange(0, 10 ** 8) + self.num_wavelength_sweep_start.setSingleStep(1) + self.num_wavelength_sweep_start.setValue(self.vaut_config.laser_config.get_wavelength_range()[0]) + self.num_wavelength_sweep_start.setSuffix(" nm") + self.num_wavelength_sweep_start.setDecimals(3) + self.num_wavelength_sweep_start.setKeyboardTracking(False) + layout.addWidget(self.num_wavelength_sweep_start, 1, 1) + self.num_wavelength_sweep_start.valueChanged.connect( + lambda v: self.vaut_config.laser_config.set_wavelength_range( + [float(v), float(self.num_wavelength_range_stop.value())]) + ) + + self.num_wavelength_range_stop.setRange(0, 10 ** 8) + self.num_wavelength_range_stop.setSingleStep(1) + self.num_wavelength_range_stop.setValue(self.vaut_config.laser_config.get_wavelength_range()[1]) + self.num_wavelength_range_stop.setSuffix(" nm") + self.num_wavelength_range_stop.setDecimals(3) + self.num_wavelength_range_stop.setKeyboardTracking(False) + layout.addWidget(self.num_wavelength_range_stop, 1, 2) + + self.num_wavelength_range_stop.valueChanged.connect( + lambda v: self.vaut_config.laser_config.set_wavelength_range( + [float(self.num_wavelength_sweep_start.value()), float(v)] + )) + + lbl_velocity = QLabel("Velocity") + layout.addWidget(lbl_velocity, 2, 0) + self.num_velocity.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_velocity(v)) + self.num_velocity.setRange(0, 10**8) + self.num_velocity.setSingleStep(1) + self.num_velocity.setValue(self.vaut_config.laser_config.get_velocity()) + self.num_acceleration.setSuffix(" m/s") + self.num_velocity.setDecimals(3) + self.num_velocity.setKeyboardTracking(False) + layout.addWidget(self.num_velocity, 2, 1, 1, 2) + + lbl_acceleration = QLabel("Acceleration") + layout.addWidget(lbl_acceleration, 3, 0) + self.num_acceleration.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_acceleration(v)) + self.num_acceleration.setRange(0, 10**8) + self.num_acceleration.setSingleStep(1) + self.num_acceleration.setValue(self.vaut_config.laser_config.get_acceleration()) + self.num_acceleration.setSuffix(" m/s^2") + self.num_acceleration.setDecimals(3) + self.num_acceleration.setKeyboardTracking(False) + layout.addWidget(self.num_acceleration, 3, 1, 1, 2) + + lbl_deceleration = QLabel("Deceleration") + layout.addWidget(lbl_deceleration, 4, 0) + self.num_deceleration.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_deceleration(v)) + self.num_deceleration.setRange(0, 10 ** 8) + self.num_deceleration.setSingleStep(1) + self.num_deceleration.setValue(self.vaut_config.laser_config.get_deceleration()) + self.num_deceleration.setSuffix(" m/s^2") + self.num_deceleration.setDecimals(3) + self.num_deceleration.setKeyboardTracking(False) + layout.addWidget(self.num_deceleration, 4, 1, 1, 2) + + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + diff --git a/src/FlexSensor/MainWindow/view/widgets/__init__.py b/src/FlexSensor/MainWindow/view/widgets/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/view/widgets/custom_grips/__init__.py b/src/FlexSensor/MainWindow/view/widgets/custom_grips/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..edc45ae18fc40102f8a27651f77dac72d5026488 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/custom_grips/__init__.py @@ -0,0 +1,17 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +from . custom_grips import CustomGrip diff --git a/src/FlexSensor/MainWindow/view/widgets/custom_grips/custom_grips.py b/src/FlexSensor/MainWindow/view/widgets/custom_grips/custom_grips.py new file mode 100644 index 0000000000000000000000000000000000000000..53a15a1d68cb56d2f1fe1821a1ce9dd261b6f340 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/custom_grips/custom_grips.py @@ -0,0 +1,238 @@ +# /////////////////////////////////////////////////////////////// +# +# BY: WANDERSON M.PIMENTA +# PROJECT MADE WITH: Qt Designer and PySide6 +# V: 1.0.0 +# +# This project can be used freely for all uses, as long as they maintain the +# respective credits only in the Python scripts, any information in the visual +# interface (GUI) can be modified without any implication. +# +# There are limitations on Qt licenses if you want to use your products +# commercially, I recommend reading them on the official website: +# https://doc.qt.io/qtforpython/licenses.html +# +# /////////////////////////////////////////////////////////////// + +from PySide6.QtCore import * +from PySide6.QtGui import * +from PySide6.QtWidgets import * + +class CustomGrip(QWidget): + def __init__(self, parent, position, disable_color = False): + + # SETUP UI + QWidget.__init__(self) + self.parent = parent + self.setParent(parent) + self.wi = Widgets() + + # SHOW TOP GRIP + if position == Qt.TopEdge: + self.wi.top(self) + self.setGeometry(0, 0, self.parent.width(), 10) + self.setMaximumHeight(10) + + # GRIPS + top_left = QSizeGrip(self.wi.top_left) + top_right = QSizeGrip(self.wi.top_right) + + # RESIZE TOP + def resize_top(event): + delta = event.pos() + height = max(self.parent.minimumHeight(), self.parent.height() - delta.y()) + geo = self.parent.geometry() + geo.setTop(geo.bottom() - height) + self.parent.setGeometry(geo) + event.accept() + self.wi.top.mouseMoveEvent = resize_top + + # ENABLE COLOR + if disable_color: + self.wi.top_left.setStyleSheet("background: transparent") + self.wi.top_right.setStyleSheet("background: transparent") + self.wi.top.setStyleSheet("background: transparent") + + # SHOW BOTTOM GRIP + elif position == Qt.BottomEdge: + self.wi.bottom(self) + self.setGeometry(0, self.parent.height() - 10, self.parent.width(), 10) + self.setMaximumHeight(10) + + # GRIPS + self.bottom_left = QSizeGrip(self.wi.bottom_left) + self.bottom_right = QSizeGrip(self.wi.bottom_right) + + # RESIZE BOTTOM + def resize_bottom(event): + delta = event.pos() + height = max(self.parent.minimumHeight(), self.parent.height() + delta.y()) + self.parent.resize(self.parent.width(), height) + event.accept() + self.wi.bottom.mouseMoveEvent = resize_bottom + + # ENABLE COLOR + if disable_color: + self.wi.bottom_left.setStyleSheet("background: transparent") + self.wi.bottom_right.setStyleSheet("background: transparent") + self.wi.bottom.setStyleSheet("background: transparent") + + # SHOW LEFT GRIP + elif position == Qt.LeftEdge: + self.wi.left(self) + self.setGeometry(0, 10, 10, self.parent.height()) + self.setMaximumWidth(10) + + # RESIZE LEFT + def resize_left(event): + delta = event.pos() + width = max(self.parent.minimumWidth(), self.parent.width() - delta.x()) + geo = self.parent.geometry() + geo.setLeft(geo.right() - width) + self.parent.setGeometry(geo) + event.accept() + self.wi.leftgrip.mouseMoveEvent = resize_left + + # ENABLE COLOR + if disable_color: + self.wi.leftgrip.setStyleSheet("background: transparent") + + # RESIZE RIGHT + elif position == Qt.RightEdge: + self.wi.right(self) + self.setGeometry(self.parent.width() - 10, 10, 10, self.parent.height()) + self.setMaximumWidth(10) + + def resize_right(event): + delta = event.pos() + width = max(self.parent.minimumWidth(), self.parent.width() + delta.x()) + self.parent.resize(width, self.parent.height()) + event.accept() + self.wi.rightgrip.mouseMoveEvent = resize_right + + # ENABLE COLOR + if disable_color: + self.wi.rightgrip.setStyleSheet("background: transparent") + + + def mouseReleaseEvent(self, event): + self.mousePos = None + + def resizeEvent(self, event): + if hasattr(self.wi, 'container_top'): + self.wi.container_top.setGeometry(0, 0, self.width(), 10) + + elif hasattr(self.wi, 'container_bottom'): + self.wi.container_bottom.setGeometry(0, 0, self.width(), 10) + + elif hasattr(self.wi, 'leftgrip'): + self.wi.leftgrip.setGeometry(0, 0, 10, self.height() - 20) + + elif hasattr(self.wi, 'rightgrip'): + self.wi.rightgrip.setGeometry(0, 0, 10, self.height() - 20) + +class Widgets(object): + def top(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.container_top = QFrame(Form) + self.container_top.setObjectName(u"container_top") + self.container_top.setGeometry(QRect(0, 0, 500, 10)) + self.container_top.setMinimumSize(QSize(0, 10)) + self.container_top.setMaximumSize(QSize(16777215, 10)) + self.container_top.setFrameShape(QFrame.NoFrame) + self.container_top.setFrameShadow(QFrame.Raised) + self.top_layout = QHBoxLayout(self.container_top) + self.top_layout.setSpacing(0) + self.top_layout.setObjectName(u"top_layout") + self.top_layout.setContentsMargins(0, 0, 0, 0) + self.top_left = QFrame(self.container_top) + self.top_left.setObjectName(u"top_left") + self.top_left.setMinimumSize(QSize(10, 10)) + self.top_left.setMaximumSize(QSize(10, 10)) + self.top_left.setCursor(QCursor(Qt.SizeFDiagCursor)) + self.top_left.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.top_left.setFrameShape(QFrame.NoFrame) + self.top_left.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top_left) + self.top = QFrame(self.container_top) + self.top.setObjectName(u"top") + self.top.setCursor(QCursor(Qt.SizeVerCursor)) + self.top.setStyleSheet(u"background-color: rgb(85, 255, 255);") + self.top.setFrameShape(QFrame.NoFrame) + self.top.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top) + self.top_right = QFrame(self.container_top) + self.top_right.setObjectName(u"top_right") + self.top_right.setMinimumSize(QSize(10, 10)) + self.top_right.setMaximumSize(QSize(10, 10)) + self.top_right.setCursor(QCursor(Qt.SizeBDiagCursor)) + self.top_right.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.top_right.setFrameShape(QFrame.NoFrame) + self.top_right.setFrameShadow(QFrame.Raised) + self.top_layout.addWidget(self.top_right) + + def bottom(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.container_bottom = QFrame(Form) + self.container_bottom.setObjectName(u"container_bottom") + self.container_bottom.setGeometry(QRect(0, 0, 500, 10)) + self.container_bottom.setMinimumSize(QSize(0, 10)) + self.container_bottom.setMaximumSize(QSize(16777215, 10)) + self.container_bottom.setFrameShape(QFrame.NoFrame) + self.container_bottom.setFrameShadow(QFrame.Raised) + self.bottom_layout = QHBoxLayout(self.container_bottom) + self.bottom_layout.setSpacing(0) + self.bottom_layout.setObjectName(u"bottom_layout") + self.bottom_layout.setContentsMargins(0, 0, 0, 0) + self.bottom_left = QFrame(self.container_bottom) + self.bottom_left.setObjectName(u"bottom_left") + self.bottom_left.setMinimumSize(QSize(10, 10)) + self.bottom_left.setMaximumSize(QSize(10, 10)) + self.bottom_left.setCursor(QCursor(Qt.SizeBDiagCursor)) + self.bottom_left.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.bottom_left.setFrameShape(QFrame.NoFrame) + self.bottom_left.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom_left) + self.bottom = QFrame(self.container_bottom) + self.bottom.setObjectName(u"bottom") + self.bottom.setCursor(QCursor(Qt.SizeVerCursor)) + self.bottom.setStyleSheet(u"background-color: rgb(85, 170, 0);") + self.bottom.setFrameShape(QFrame.NoFrame) + self.bottom.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom) + self.bottom_right = QFrame(self.container_bottom) + self.bottom_right.setObjectName(u"bottom_right") + self.bottom_right.setMinimumSize(QSize(10, 10)) + self.bottom_right.setMaximumSize(QSize(10, 10)) + self.bottom_right.setCursor(QCursor(Qt.SizeFDiagCursor)) + self.bottom_right.setStyleSheet(u"background-color: rgb(33, 37, 43);") + self.bottom_right.setFrameShape(QFrame.NoFrame) + self.bottom_right.setFrameShadow(QFrame.Raised) + self.bottom_layout.addWidget(self.bottom_right) + + def left(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + self.leftgrip = QFrame(Form) + self.leftgrip.setObjectName(u"left") + self.leftgrip.setGeometry(QRect(0, 10, 10, 480)) + self.leftgrip.setMinimumSize(QSize(10, 0)) + self.leftgrip.setCursor(QCursor(Qt.SizeHorCursor)) + self.leftgrip.setStyleSheet(u"background-color: rgb(255, 121, 198);") + self.leftgrip.setFrameShape(QFrame.NoFrame) + self.leftgrip.setFrameShadow(QFrame.Raised) + + def right(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(500, 500) + self.rightgrip = QFrame(Form) + self.rightgrip.setObjectName(u"right") + self.rightgrip.setGeometry(QRect(0, 0, 10, 500)) + self.rightgrip.setMinimumSize(QSize(10, 0)) + self.rightgrip.setCursor(QCursor(Qt.SizeHorCursor)) + self.rightgrip.setStyleSheet(u"background-color: rgb(255, 0, 127);") + self.rightgrip.setFrameShape(QFrame.NoFrame) + self.rightgrip.setFrameShadow(QFrame.Raised) diff --git a/src/FlexSensor/MainWindow/view/widgets/menu_bar_widget.py b/src/FlexSensor/MainWindow/view/widgets/menu_bar_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MainWindow/view/widgets/widget_settings_folder.py b/src/FlexSensor/MainWindow/view/widgets/widget_settings_folder.py new file mode 100644 index 0000000000000000000000000000000000000000..dcbe0d82efa3172ce5ecda09fa96125df16b4310 --- /dev/null +++ b/src/FlexSensor/MainWindow/view/widgets/widget_settings_folder.py @@ -0,0 +1,317 @@ +from PySide6.QtWidgets import QWidget, QGridLayout, QGroupBox, QLineEdit, QPushButton, QLabel, QDoubleSpinBox + +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from ConfigHandler.view.ConfigView import ConfigView + + +class WidgetSettingsInFilesFolders(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + + self.btn_select_list_of_structures = QPushButton(parent=self, text="...") + self.btn_select_working_directory = QPushButton(parent=self, text="...") + + self.layout = QGridLayout() + self.init_UI() + + def init_UI(self): + grid_group_box = QGroupBox("Input Files") + layout = QGridLayout() + # Working directory + self.tb_working_directory = QLineEdit(parent=self, text=str(self.vaut_config.get_output_directory().relative)) + self.btn_select_working_directory.setMaximumWidth(self.btn_select_working_directory.sizeHint().height()) + layout.addWidget(QLabel("Working directory"), 0, 0) + layout.addWidget(self.tb_working_directory, 0, 1) # row, column, rowspan, colspan + layout.addWidget(self.btn_select_working_directory, 0, 3) # row, column, rowspan, colspan + + # List of structures + self.tb_list_of_structures = QLineEdit(parent=self, text=str(self.vaut_config.wafer_config.get_structure_file().relative)) + self.btn_select_list_of_structures.setMaximumWidth(self.btn_select_list_of_structures.sizeHint().height()) + layout.addWidget(QLabel("Input Structure File"), 1, 0) + layout.addWidget(self.tb_list_of_structures, 1, 1) # row, column, rowspan, colspan + layout.addWidget(self.btn_select_list_of_structures, 1, 3) # row, column, rowspan, colspan + + grid_group_box.setLayout(layout) + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + + +class WidgetSettingsOutFilesFolders(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + + self.tb_log_file = QLineEdit(text=self.vaut_config.wafer_config.get_log_file().filename) + self.tb_measurement_output = QLineEdit(text=self.vaut_config.wafer_config.get_measurement_output().filename) + self.tb_mat_files_output = QLineEdit(text=self.vaut_config.wafer_config.get_measurement_mat_file().filename) + self.tb_bookmark_file = QLineEdit(text=self.vaut_config.wafer_config.get_bookmark_file().filename) + self.tb_scope_image_file = QLineEdit(text=self.vaut_config.wafer_config.get_scope_image_file().filename) + + + self.layout = QGridLayout() + self.init_UI() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Output Files") + grid_group_box.setLayout(layout) + + + + + + + self.lbl_log_file = QLabel(parent=self) + self.tb_log_file.textChanged.connect(self.on_tb_log_file_text_changed) + self.on_tb_log_file_text_changed(self.tb_log_file.text()) + layout.addWidget(QLabel("Log File"), 0, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_log_file, 0, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_log_file, 1, 0, 1, 2) # row, column, rowspan, colspan + + # measurement output + self.lbl_measurement_output = QLabel(parent=self) + self.tb_measurement_output.textChanged.connect(self.on_tb_measurement_output_text_changed) + self.on_tb_measurement_output_text_changed(self.tb_measurement_output.text()) + layout.addWidget(QLabel("Measurement output"), 2, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_measurement_output, 2, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_measurement_output, 3, 0, 1, 2) # row, column, rowspan, colspan + + # Mat files output + self.lbl_mat_files_output = QLabel(parent=self) + self.on_tb_mat_files_output_text_changed(self.tb_mat_files_output.text()) + + self.tb_mat_files_output.textChanged.connect(self.on_tb_mat_files_output_text_changed) + layout.addWidget(QLabel("Matlab Files"), 4, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_mat_files_output, 4, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_mat_files_output, 5, 0, 1, 2) # row, column, rowspan, colspan + + # bookmark files + self.lbl_bookmark_file = QLabel(parent=self) + self.on_tb_bookmark_file_text_changed(self.tb_bookmark_file.text()) + self.tb_bookmark_file.textChanged.connect(self.on_tb_bookmark_file_text_changed) + self.tb_scope_image_file.textChanged.connect(self.on_tb_scope_image_file_text_changed) + layout.addWidget(QLabel("Bookmark files"), 6, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_bookmark_file, 6, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_bookmark_file, 7, 0, 1, 2) # row, column, rowspan, colspan + + # scope shots + self.lbl_scope_image_file = QLabel(parent=self) + self.on_tb_scope_image_file_text_changed(self.tb_scope_image_file.text()) + layout.addWidget(QLabel("Scope Shots"), 8, 0) # row, column, rowspan, colspan + layout.addWidget(self.tb_scope_image_file, 8, 1) # row, column, rowspan, colspan + layout.addWidget(self.lbl_scope_image_file, 9, 0, 1, 2) + + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + + def on_tb_scope_image_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_scope_image_file().set_obj(value) + val = self.vaut_config.wafer_config.get_scope_image_file().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_scope_image_file.setText(val) + # set label hover text + self.lbl_scope_image_file.setToolTip(self.vaut_config.wafer_config.get_scope_image_file().absolute) + + def on_tb_measurement_output_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_measurement_output().set_obj(value) + val = self.vaut_config.wafer_config.get_measurement_output().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_measurement_output.setText(val) + # set label hover text + self.lbl_measurement_output.setToolTip(self.vaut_config.wafer_config.get_scope_image_file().absolute) + + def on_tb_bookmark_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_bookmark_file().set_obj(value) + val = self.vaut_config.wafer_config.get_bookmark_file().relative.replace(self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_bookmark_file.setText(val) + # set label hover text + self.lbl_bookmark_file.setToolTip(self.vaut_config.wafer_config.get_bookmark_file().absolute) + + config = self.vaut_config + + def on_tb_mat_files_output_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_measurement_mat_file().set_obj(value) + val = self.vaut_config.wafer_config.get_measurement_mat_file().relative.replace( + self.vaut_config.get_output_directory().relative, + "<b>wd</b>") + self.lbl_mat_files_output.setText(val) + self.lbl_mat_files_output.setToolTip(self.vaut_config.wafer_config.get_measurement_mat_file().absolute) + + def on_tb_log_file_text_changed(self, value): + if value is not None: + self.vaut_config.wafer_config.get_log_file().set_obj(value) + + val = self.vaut_config.wafer_config.get_log_file().relative.replace(self.vaut_config.get_output_directory().relative, "<b>wd</b>") + self.lbl_log_file.setText(val) + self.lbl_log_file.setToolTip(self.vaut_config.wafer_config.get_log_file().absolute) + +class WidgetAD2Settings(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + self.c = ConfigView(vaut_config) + + + self.num_sample_rate = QDoubleSpinBox() + self.num_total_samples = QDoubleSpinBox() + self.num_sample_time = QDoubleSpinBox() + + self.btn_select_ad2_raw_out_file = QPushButton(parent=self, text="....") + + self.btn_select_ad2_raw_out_file.clicked.connect(self.show_config) + self.layout = QGridLayout() + self.init_UI() + + + def show_config(self): + self.c = ConfigView(self.vaut_config) + self.c.show() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Analog Discovery 2 Settings") + grid_group_box.setLayout(layout) + + lbl_sample_rate = QLabel("Sample Rate") + layout.addWidget(lbl_sample_rate, 1, 0) + self.num_sample_rate.valueChanged.connect(lambda v: self.vaut_config.ad2_device_config.set_sample_rate(v)) + self.num_sample_rate.setRange(0, 10**8) + self.num_sample_rate.setSingleStep(1) + self.num_sample_rate.setValue(self.vaut_config.ad2_device_config.get_sample_rate()) + self.num_sample_rate.setSuffix(" Hz") + self.num_sample_rate.setDecimals(3) + self.num_sample_rate.setKeyboardTracking(False) + layout.addWidget(self.num_sample_rate, 1, 1, 1, 2) + + lbl_total_samples = QLabel("Total Samples") + layout.addWidget(lbl_total_samples, 2, 0) + self.num_total_samples.setRange(0, 10**8) + self.num_total_samples.setSingleStep(1) + self.num_total_samples.setValue(self.vaut_config.ad2_device_config.get_total_samples()) + self.num_total_samples.setDecimals(3) + self.num_total_samples.setKeyboardTracking(False) + layout.addWidget(self.num_total_samples, 2, 1, 1, 2) + + lbl_sample_time = QLabel("Sample Time") + layout.addWidget(lbl_sample_time, 3, 0) + self.num_sample_time.setRange(0, 10**8) + self.num_sample_time.setSingleStep(1) + self.num_sample_time.setValue(self.vaut_config.ad2_device_config.get_sample_time()) + self.num_sample_time.setSuffix(" s") + self.num_sample_time.setDecimals(3) + self.num_sample_time.setKeyboardTracking(False) + layout.addWidget(self.num_sample_time, 3, 1, 1, 2) + + lbl_ad2_raw_out_file = QLabel("Raw Out File") + layout.addWidget(lbl_ad2_raw_out_file, 4, 0) + tb_ad2_raw_out_file = QLineEdit(text=self.vaut_config.ad2_device_config.get_ad2_raw_out_file().relative) + layout.addWidget(tb_ad2_raw_out_file, 4, 1) + layout.addWidget(self.btn_select_ad2_raw_out_file, 4, 2) + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + +class WidgetLaserSettings(QWidget): + def __init__(self, vaut_config: VAutomatorConfig): + super().__init__() + self.vaut_config = vaut_config + self.c = None + + + self.num_wavelength_sweep_start = QDoubleSpinBox() + self.num_wavelength_range_stop = QDoubleSpinBox() + self.num_velocity = QDoubleSpinBox() + self.num_acceleration = QDoubleSpinBox() + self.num_deceleration = QDoubleSpinBox() + + + #self.btn_select_ad2_raw_out_file = QPushButton(parent=self, text="....") + + #self.btn_select_ad2_raw_out_file.clicked.connect(self.show_config) + self.layout = QGridLayout() + self.init_UI() + + + def show_config(self): + self.c = ConfigView(self.vaut_config) + self.c.show() + + def init_UI(self): + layout = QGridLayout() + grid_group_box = QGroupBox("Laser Settings") + grid_group_box.setLayout(layout) + + lbl_wavelength_sweep_start = QLabel("Wavelength Sweep") + layout.addWidget(lbl_wavelength_sweep_start, 1, 0) + + + + self.num_wavelength_sweep_start.setRange(0, 10 ** 8) + self.num_wavelength_sweep_start.setSingleStep(1) + self.num_wavelength_sweep_start.setValue(self.vaut_config.laser_config.get_wavelength_range()[0]) + self.num_wavelength_sweep_start.setSuffix(" nm") + self.num_wavelength_sweep_start.setDecimals(3) + self.num_wavelength_sweep_start.setKeyboardTracking(False) + layout.addWidget(self.num_wavelength_sweep_start, 1, 1) + self.num_wavelength_sweep_start.valueChanged.connect( + lambda v: self.vaut_config.laser_config.set_wavelength_range( + [float(v), float(self.num_wavelength_range_stop.value())]) + ) + + self.num_wavelength_range_stop.setRange(0, 10 ** 8) + self.num_wavelength_range_stop.setSingleStep(1) + self.num_wavelength_range_stop.setValue(self.vaut_config.laser_config.get_wavelength_range()[1]) + self.num_wavelength_range_stop.setSuffix(" nm") + self.num_wavelength_range_stop.setDecimals(3) + self.num_wavelength_range_stop.setKeyboardTracking(False) + layout.addWidget(self.num_wavelength_range_stop, 1, 2) + + self.num_wavelength_range_stop.valueChanged.connect( + lambda v: self.vaut_config.laser_config.set_wavelength_range( + [float(self.num_wavelength_sweep_start.value()), float(v)] + )) + + lbl_velocity = QLabel("Velocity") + layout.addWidget(lbl_velocity, 2, 0) + self.num_velocity.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_velocity(v)) + self.num_velocity.setRange(0, 10**8) + self.num_velocity.setSingleStep(1) + self.num_velocity.setValue(self.vaut_config.laser_config.get_velocity()) + self.num_acceleration.setSuffix(" m/s") + self.num_velocity.setDecimals(3) + self.num_velocity.setKeyboardTracking(False) + layout.addWidget(self.num_velocity, 2, 1, 1, 2) + + lbl_acceleration = QLabel("Acceleration") + layout.addWidget(lbl_acceleration, 3, 0) + self.num_acceleration.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_acceleration(v)) + self.num_acceleration.setRange(0, 10**8) + self.num_acceleration.setSingleStep(1) + self.num_acceleration.setValue(self.vaut_config.laser_config.get_acceleration()) + self.num_acceleration.setSuffix(" m/s^2") + self.num_acceleration.setDecimals(3) + self.num_acceleration.setKeyboardTracking(False) + layout.addWidget(self.num_acceleration, 3, 1, 1, 2) + + lbl_deceleration = QLabel("Deceleration") + layout.addWidget(lbl_deceleration, 4, 0) + self.num_deceleration.valueChanged.connect(lambda v: self.vaut_config.laser_config.set_deceleration(v)) + self.num_deceleration.setRange(0, 10 ** 8) + self.num_deceleration.setSingleStep(1) + self.num_deceleration.setValue(self.vaut_config.laser_config.get_deceleration()) + self.num_deceleration.setSuffix(" m/s^2") + self.num_deceleration.setDecimals(3) + self.num_deceleration.setKeyboardTracking(False) + layout.addWidget(self.num_deceleration, 4, 1, 1, 2) + + + self.layout.addWidget(grid_group_box) + self.setLayout(self.layout) + diff --git a/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py new file mode 100644 index 0000000000000000000000000000000000000000..217bfe27e638dd16e05d1575c480ff76f60c1331 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py @@ -0,0 +1,184 @@ +import logging +import os +from pathlib import Path + +import numpy as np +import pandas as pd +import scipy +from numpy import ndarray + +from MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties +from MeasurementData.Properties.LaserProperties import LaserProperties +from MeasurementData.MeasuredData.SupportClasses.MeasurementDataTables import MeasurementDataTables +from MeasurementData.Properties.MeasurementProperties import MeasurementProperties, \ + MPropertiesFindPeaks, WaveguideProperties +from MeasurementData.Properties.WaferProperties import WaferProperties + + +class MeasuredData: + + + def __init__(self, laser_properties: LaserProperties, ad2_properties: AD2CaptDeviceProperties, + wafer_properties: WaferProperties, waveguide_properties: WaveguideProperties, + measurement_properties: MeasurementProperties): + #super().__init__() + self.logger = logging.getLogger("MeasuredSignal") + # ============================================================================================================== + # Tables + self._tables: MeasurementDataTables = MeasurementDataTables() + + # ============================================================================================================== + # Properties for storing information + self._laser_properties: LaserProperties = laser_properties # Laser Properties + self._ad2_properties: AD2CaptDeviceProperties = ad2_properties # AD2CaptDev Properties + self._wafer_properties: WaferProperties = wafer_properties # Wafer Properties + self._waveguide_properties: WaveguideProperties = waveguide_properties # Waveguide Properties + # Measurement properties like findpeaks parameter + self._measurement_properties: MeasurementProperties = MeasurementProperties( + MPropertiesFindPeaks(0.1, 10000, None)) + + # ============================================================================================================== + # Dataframe with measured values + self._measured_data: pd.DataFrame = self._tables.append(pd.DataFrame(), '_measured_data', "Measured Data") + # Calculation Tables + # Stores the found peaks + self._peaks: pd.DataFrame = self._tables.append(pd.DataFrame(), '_peaks', 'Peaks') + # Store wg parameters like FSR, and ng + self._wg_param: pd.DataFrame = self._tables.append(pd.DataFrame(), '_wg_param', 'Waveguide Parameters') + + # ============================================================================================================== + # COnnect the signals + self._measurement_properties.find_peaks.properties_changed.connect(self.find_peaks) + + # ================================================================================================================== + # + # ================================================================================================================== + @property + def waveguide_properties(self): + return self._waveguide_properties + + @waveguide_properties.setter + def waveguide_properties(self, value): + self._waveguide_properties = value + + @property + def measurement_properties(self): + return self._measurement_properties + + @measurement_properties.setter + def measurement_properties(self, value): + self._measurement_properties = value + + @property + def ad2_properties(self): + return self._ad2_properties + + @ad2_properties.setter + def ad2_properties(self, value): + self._ad2_properties = value + + @property + def laser_properties(self): + return self._laser_properties + + @laser_properties.setter + def laser_properties(self, value): + self._laser_properties = value + + @property + def wafer_properties(self): + return self._wafer_properties + + @wafer_properties.setter + def wafer_properties(self, value): + self._wafer_properties = value + + # ================================================================================================================== + # Properties + # ================================================================================================================== + @property + def tables(self) -> MeasurementDataTables: + return self._tables + + @property + def peaks(self) -> pd.DataFrame: + return self._peaks + + # ================================================================================================================== + # Calculations and table creations + # ================================================================================================================== + def calculate_wg_params(self, table="_peaks"): + peaks_wl: ndarray = self.tables.get(table)['wavelength'].to_numpy() + try: + if len(peaks_wl) % 2 == 1: + self.logger.warning(f"[{self}] | Number of peaks not even ({len(peaks_wl)}), removing last peak.") + peaks_wl = peaks_wl[:-1] + self.logger.info(f"[{self}] | Reshaping {np.shape(peaks_wl)} to (-1, 2)") + self._wg_param = pd.DataFrame(peaks_wl.reshape(-1, 2), columns=['P1', 'P2']) + self._wg_param['FSR'] = self._wg_param.apply(lambda row: row['P2'] - row['P1'], axis=1) + self._wg_param['lambda'] = self._wg_param.apply(lambda row: np.mean((row['P2'], row['P1'])), axis=1) + self._wg_param['ng'] = self.waveguide_properties.group_index(self._wg_param) + # self._wg_param.apply(lambda row: (row['lambda'] ** 2) / (row['FSR'] * dl), axis=1) + # Filter outliers + self._wg_param = self._tables.update(self._wg_param[(np.abs(scipy.stats.zscore(self._wg_param['ng'])) < 2)], + '_wg_param') + except Exception as e: + print(f"Error {e}") + + def __str__(self): + return f"{self.wafer_properties.wafer_number}/" \ + f"{self.wafer_properties.die_number}/" \ + f"{self.wafer_properties.structure_name} - {self.wafer_properties.repetition}" + + # ================================================================================================================== + # I/O - Operations and Plotting + # ================================================================================================================== + def _save_mat_file(self, filename: str) -> object: + + self._mat_filename = Path(filename) + dirname = self._mat_filename.parent.absolute() + self.logger.info(f"[{self}] | Generating mat file and saving to {self._mat_filename.name} (folder: {dirname})") + if self._mat_filename is None or self._mat_filename == "": + raise ValueError("No mat file generated. Filename is not defined") + + if not str(self._mat_filename).endswith(".mat"): + raise ValueError("No mat file generated. Filename does not end with .mat") + if self._measured_data is None: + raise ValueError( + "No mat file generated. No measured amplitude data. No mat file produced fot this structure.") + # Get the file name from file + + # Make a path + # Check if path exists + if not os.path.exists(dirname): + try: + os.makedirs(dirname) + except OSError as exc: # Guard against + raise ValueError("No mat file generated. Could not create directory") + mdic = self.to_dict() + #print(mdic) + scipy.io.savemat(self._mat_filename, mdict=mdic) + #self._measured_data.to_csv(self.datafile) + self.write_matlab_file(self._mat_filename, self.datafile, f"{self._mat_filename.parent}/load_all.m") + + self.logger.info(f"[{self}] | Stored matlab file to {self._mat_filename}") + + return self._mat_filename + + def write_matlab_file(self, mat_file, csv_file, filename: str) -> object: + mfile = "" + mfile += "load('" + str(filename) + "');" + # load csv with matlab + mfile += "data = readcsv('" + str(self.datafile) + "');" + # save matlab file + with open(filename, 'w') as f: + f.write(mfile) + + # ================================================================================================================== + # abstract methods + # ================================================================================================================== + def find_peaks(self): + raise NotImplementedError() + + def to_dict(self) -> dict: + raise NotImplementedError() diff --git a/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py new file mode 100644 index 0000000000000000000000000000000000000000..77293227af0a117a1792590b8e355de068bf5d12 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py @@ -0,0 +1,142 @@ +import time + +import numpy as np +import pandas as pd +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QProgressDialog +from numpy import ndarray + +from MeasurementData.MeasuredData.MeasuredData import MeasuredData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +import mcpy +from MeasurementData.MeasuredData.SupportClasses.MatplotlibPlottingHelpers import MPLPlottingHelper +from MeasurementData.MeasuredData.SupportClasses.MeasurementDataLoader import MeasurementDataLoader +from generics.logger import setup_logging +from wrappers.QProgressBarWindow import QProgressBarWindow + + +class MultiMeasuredData(MeasuredData): + + def __init__(self, single_measurements: list[SingleMeasuredData]): + self._single_measurements = single_measurements + + super().__init__(laser_properties=self._single_measurements[0].laser_properties, + ad2_properties=self._single_measurements[0].ad2_properties, + wafer_properties=self._single_measurements[0].wafer_properties, + waveguide_properties=self._single_measurements[0].waveguide_properties, + measurement_properties=self._single_measurements[0].measurement_properties, + ) + self.wafer_properties._structure_name += " - Mean" + + self._recalculate_measured_data() + self.consolidate_measurement() + self.calculate_mean_and_std() + self.calculate_wg_params(table='_peaks') + self.calculate_all(table='_peaks') + + def consolidate_measurement(self): + self.logger.info("Consolidating all measurements to one measurement") + progress = QProgressDialog(f"Reading files...", "Abort", 0, len(self._single_measurements)) + progress.setWindowModality(Qt.WindowModal) + progress.show() + + tmp_measured_data = [] + for i, mea, it in QProgressBarWindow(self._single_measurements): + it.print(f"Consolidating measurement {str(mea)}") + tmp_measured_data.append(pd.DataFrame( + mea.tables.get('_peaks')['wavelength'].reset_index()[:].values, + columns=[f'index_{mea.wafer_properties.repetition}', + f'wavelength_{mea.wafer_properties.repetition}'] + )) + + self._measured_data = self._tables.update(pd.concat(tmp_measured_data, axis=1), '_measured_data') + + def _recalculate_measured_data(self): + self.logger.info("Recalculating all measurements") + + for i, mea, it in QProgressBarWindow(self._single_measurements): + mea.calulate_all() + + # ================================================================================================================== + # + # ================================================================================================================== + def calculate_mean_and_std(self): + self._peaks['wavelength'] = self._measured_data.filter(like='wavelength').apply( + lambda row: mcpy.DirectObservations(row), axis=1) + self._peaks['index'] = self._measured_data.filter(like='index').apply( + lambda row: mcpy.DirectObservations(row), axis=1) + self._tables.update(self._peaks, '_peaks') + + def calculate_all(self, table='_peaks', N=100000): + peaks_wl: ndarray = self.tables.get(table)['wavelength'].to_numpy() + try: + if len(peaks_wl) % 2 == 1: + self.logger.warning(f"[{self}] | Number of peaks not even ({len(peaks_wl)}), removing last peak.") + peaks_wl = peaks_wl[:-1] + self.logger.info(f"[{self}] | Reshaping {np.shape(peaks_wl)} to (-1, 2)") + self._wg_param = pd.DataFrame(peaks_wl.reshape(-1, 2), columns=['P1', 'P2']) # .astype(Uncertainty) + + self._wg_param['P1 (MC)'] = self._wg_param.apply( + lambda row: row['P1'].rand(N), axis=1) + + self._wg_param['P2 (MC)'] = self._wg_param.apply( + lambda row: row['P2'].rand(N), axis=1) + + self._wg_param['FSR (MC)'] = self._wg_param.apply( + lambda row: row['P2 (MC)'] - row['P1 (MC)'], axis=1) + + self._wg_param['lambda (MC)'] = self._wg_param.apply( + lambda row: (row['P2 (MC)']+row['P1 (MC)'])/2, axis=1) + + self._wg_param['ng (MC)'] = self._wg_param.apply( + lambda row: self.waveguide_properties.group_index(row['lambda (MC)'], row['FSR (MC)'] ), axis=1) + # Place here any other calculations + + # Update the _tables + self._tables.update(self._wg_param, '_wg_param') + self._tables.add_plot('ng (FSR)', + plot_function=lambda plotwidget: MPLPlottingHelper.plt_errorbar_mcsamples( + plotwidget, + x_values=self._wg_param['lambda (MC)'], + y_values=self._wg_param['ng (MC)'])) + self._tables.add_plot('FSR (FSR)', + plot_function=lambda plotwidget: MPLPlottingHelper.plt_errorbar_mcsamples( + plotwidget, + x_values=self._wg_param['lambda (MC)'], + y_values=self._wg_param['FSR (MC)'])) + except Exception as e: + print(f"Error {e}") + + # ================================================================================================================== + # + # ================================================================================================================== + def to_dict(self) -> dict: + return { + "laser_properties": self._laser_properties.to_dict(), + "wafer_properties": self._wafer_properties.to_dict(), + "measurement_properties": self._measurement_properties.to_dict(), + "waveguide_properties": self._waveguide_properties.to_dict(), + "amplitudes": [i.to_dict() for i in self._single_measurements], + + } + + def __str__(self): + return f"{self.wafer_properties.wafer_number}/" \ + f"{self.wafer_properties.die_number}/" \ + f"{self.wafer_properties.structure_name}-Sum" + + +if __name__ == "__main__": + setup_logging() + + mypath = 'E:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement_small' + mm_data = MeasurementDataLoader.from_folder(mypath) + print(mm_data.wafers) + print(mm_data.dies) + print(mm_data.structure_name) + + filtered_files = mm_data.get_measurement_series(structure_name='mzi2-2') + + data = MultiMeasuredData(filtered_files) + print(data._wg_param) + # ädata.generate_mat_file(r'E:\test.mat') diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py new file mode 100644 index 0000000000000000000000000000000000000000..e21abc0db0a958240a6bf1e0fdb270909a2d12ff --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py @@ -0,0 +1,667 @@ +import sys +sys.path.append("../flexsensorpy") +sys.path.append("../mcpy") +import pathlib +from datetime import datetime + + +import scipy.io +import numpy as np +import pandas as pd + +import logging +from pathlib import Path + +from PySide6.QtWidgets import QApplication +from numpy import linspace +from scipy import signal +from scipy.io import matlab +from scipy.signal import find_peaks +import scipy + +from MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties + +from MeasurementData.Properties.LaserProperties import LaserProperties +from MeasurementData.MeasuredData.MeasuredData import MeasuredData +from MeasurementData.Properties.MeasurementProperties import (WaveguideProperties, + MeasurementProperties, + WaveguidePropertiesMZI, + MPropertiesFindPeaks) + +import mcpy + +from MeasurementData.Properties.WaferProperties import WaferProperties +from generics.logger import setup_logging + + +class SingleMeasuredData(MeasuredData): + + # ================================================================================================================== + # Load a Measurement data from a matlab mat-file + # ================================================================================================================== + @classmethod + def from_mat(cls, mat_file: Path | str) -> 'SingleMeasuredData': + """ + This allows to open "old" mat files, that do not have some data. + """ + mat_file = pathlib.Path(mat_file) + logging.info(f"Loading {mat_file.name}") + matf = scipy.io.loadmat(mat_file) + + inst = cls( + laser_properties=LaserProperties( + mcpy.Rectangular(2, 0.01, unit='nm/s'), + mcpy.Rectangular(2, 0.01, unit='nm/s'), + mcpy.Rectangular(0.5, 0.01, unit='nm/s^2'), + (mcpy.Rectangular(835, 0.01, unit='nm'), mcpy.Rectangular(870, 0.01, unit='nm')) + ), + ad2_properties=AD2CaptDeviceProperties( + 0, 0, matf['ad2_sample_rate'], matf['ad2_total_samples'], matf['measure_time'] + ), + wafer_properties=WaferProperties( + matf['wafer_nr'], + matf['structure_name'], + matf['die_nr'], + matf['chuck_col'], + matf['chuck_row'], + (int(matf['structure_x_in']), int(matf['structure_y_in'])), + (int(matf['structure_x_out']), int(matf['structure_y_out'])), + int(mat_file.name.split('_')[9].replace('.mat', '')) + ), + waveguide_properties=WaveguidePropertiesMZI( + length1=mcpy.Rectangular(10e6, 20, unit='nm'), + length2=mcpy.Rectangular(10.38e6, 20, unit='nm'), + width=mcpy.Rectangular(550, 20, unit='nm'), + height=mcpy.Rectangular(625, 2.405, unit='nm')), + measurement_properties=MeasurementProperties( + MPropertiesFindPeaks(0.1, 10000, None) + ), + timestamp=matf['timestamp'], + measurement_file=None, + measurement_data=matf['amplitude'][0] + ) + """ + date_format = '%a %b %d %H:%M:%S %Y' + x = datetime. strptime( + re.search('(?<=Created on: ).*', matf['__header__'].decode('UTF-8')).group(0), + date_format)""" + + return inst + + @classmethod + def from_mat_v2(cls, mat_file: Path | str): + def loadmat(filename): + ''' + this function should be called instead of direct spio.loadmat + as it cures the problem of not properly recovering python dictionaries + from mat files. It calls the function check keys to cure all entries + which are still mat-objects + ''' + data = scipy.io.loadmat(filename, struct_as_record=False, squeeze_me=True) + return _check_keys(data) + + def _check_keys(dict): + ''' + checks if entries in dictionary are mat-objects. If yes + todict is called to change them to nested dictionaries + ''' + for key in dict: + if isinstance(dict[key], matlab.mio5_params.mat_struct): + dict[key] = _todict(dict[key]) + return dict + + def _todict(matobj): + ''' + A recursive function which constructs from matobjects nested dictionaries + ''' + dict = {} + for strg in matobj._fieldnames: + elem = matobj.__dict__[strg] + if isinstance(elem, matlab.mio5_params.mat_struct): + dict[strg] = _todict(elem) + else: + dict[strg] = elem + return dict + + if isinstance(mat_file, str): + mat_file = Path(mat_file) + + logging.info(f"Loading {mat_file.name}") + matf = loadmat(mat_file) + # mcpy.Uncertainty.from_tuple(matf['laser_properties']['laser_wavelength']) + inst = cls( + laser_properties=LaserProperties.from_dict(matf['laser_properties']), + ad2_properties=AD2CaptDeviceProperties.from_dict(matf['ad2_properties']), + wafer_properties=WaferProperties.from_dict(matf['wafer_properties']), + waveguide_properties=WaveguidePropertiesMZI.from_dict(matf['waveguide_properties']), + measurement_properties=MeasurementProperties.from_dict(matf['measurement_properties']), + timestamp=matf['timestamp'], + measurement_data=pd.DataFrame({ + 'wavelength': matf['wavelength'], + 'amplitude': matf['amplitude'], + 'amplitude_detrended': matf['amplitude_detrended']}), + + #measurement_file=Path(f"{mat_file.absolute().parent}/{matf['measurement_file']}").absolute() + ) + return inst + + @staticmethod + def convert(mat_file): + """Reads the mat file and converts the new format to the old format""" + data = SingleMeasuredData.from_mat(mat_file) + filename = mat_file.name.replace('.mat', '_v2.mat') + path = str(mat_file.parent).replace('measurements', 'measurements_v2') + # create a folder converted and save the file there + file = Path(f"{path}/{filename}") + data.save(str(file)) + + + def __init__(self, + laser_properties: LaserProperties, + ad2_properties: AD2CaptDeviceProperties, + wafer_properties: WaferProperties, + waveguide_properties: WaveguideProperties, + measurement_properties: MeasurementProperties, + timestamp: datetime, + measurement_file: Path | str = None, + measurement_data = None, + *args, **kwargs + ): + super().__init__(laser_properties, ad2_properties, wafer_properties, waveguide_properties, measurement_properties) + + if isinstance(measurement_data, list) or isinstance(measurement_data, np.ndarray): + self.measurement_file = measurement_file + # Store ot + self._measured_data: pd.DataFrame = self._tables.update( + pd.DataFrame(measurement_data, columns=['amplitude']), '_measured_data') + self._measurement_length = len(self._measured_data) + self.logger.debug(f"Measurement signal length: {self._measurement_length}") + # Generate the wacelength vector + self._create_wavelength_vector() + # Detrend the signal + self._detrend_signal() + else: + #self._raw_measurement_data: dask.array = dd.read_parquet(self.measurement_file) + self._measured_data = self._tables.update(measurement_data, '_measured_data') + + + self.print_enabled = True + self._calculated = False + # ============================================================================================================== + self._timestamp = timestamp + self._measure_time = self._ad2_properties.measurement_time + + self.datafile = None + # Measured Data (raw) + + # self._measurement_data_smoothed = self._smooth_signal(self._measurement_data_detrend) + + # ============================================================================================================== + # Dataframe with measured values + + # self._create_wavelength_vector() + # self._detrend_signal() + + @property + def measured_data(self): + return self._measured_data + + @measured_data.setter + def measured_data(self, value): + self._measured_data = value + + # ================================================================================================================== + # Generate a wavelength vector from the given settings + # ================================================================================================================== + def _create_wavelength_vector(self): + """ + Creates the wavelength vector for the measured data. + The wavelength vector is created based on the given laser properties. + """ + + sample_rate = float(self._ad2_properties.sample_rate) + acc = float(self._laser_properties.acceleration) + dec = float(self._laser_properties.deceleration) + vel = float(self._laser_properties.velocity) + wl_range = self._laser_properties.wavelength_range + + self.logger.debug(f"Creating wavelenght vector.") + self.logger.debug(f"Velocity: {vel}, Acc: {acc}, Dec: {dec}, Range: {wl_range}") + + # the duration of a sample in s + duration_sample = 1 / sample_rate + t_acc = vel / acc # Acceleration time of the laser; s + t_dec = vel / dec # Deceleration time of the laser; s + self.logger.debug(f"duration_sample: {duration_sample}, t_acc: {t_acc}, Dec: {t_dec}") + + self.p_acc_stop = int(t_acc * sample_rate) + self.logger.debug(f"Point acc_stop [{t_acc}*{sample_rate}]: {self.p_acc_stop}") + + self.p_dec_start = int(self._measurement_length - t_acc * sample_rate) + self.logger.debug(f"Point dec_start [{self._measurement_length}-{t_acc}*{sample_rate}]: {self.p_dec_start}") + + if self.p_acc_stop > self.p_dec_start: + raise ValueError("The Acceleration point cant be before the decceleration point: {self.p_acc_stop} > {self.p_dec_start}") + + s_acc = [] + for j in range(0, self.p_acc_stop): + s_acc.append( + ((1 / 2) * t_acc * (duration_sample * j) ** 2) + ) + wl_acc = np.add(s_acc, float(wl_range[0])) + self.logger.debug(f"Length of acc vector: {len(wl_acc)}") + wl_dec = np.subtract(float(wl_range[len(wl_range) - 1]), + s_acc)[::-1] + self.logger.debug(f"Length of dec vector: {len(wl_dec)}") + # Acceleration Phase/Deceleration Phase - Start and stop point + self.wl_acc_stop = wl_acc[-1] + self.wl_dec_start = wl_dec[0] + #self.logger.debug(f"lenght: {self.p_dec_start} - {self.p_acc_stop}") + length = int((self.p_dec_start - self.p_acc_stop)) + rounding_diff = self._measurement_length - (length + len(wl_acc) + len(wl_dec)) + length += rounding_diff + self.logger.debug(f"0 {length}") + # self.logger.debug(f"+1 {length+2}") + #self.logger.debug(f"+3{length+3}") + #length = length + 1 + # self.logger.debug(f"+1 {length}") + wl_move = linspace(self.wl_acc_stop, self.wl_dec_start, length) + + wl = np.concatenate((wl_acc, wl_move, wl_dec)) + self.logger.debug(f"[{self}] | Created wavelength vector: [0 - {self.p_acc_stop}] (Diff {len(wl_acc)}) -- " + f"<{len(wl_move)}> -- " + f"[{self.p_dec_start} - {len(wl)}] (Diff {len(wl_dec)})") + + self._measured_data['wavelength'] = wl + + def _smooth_signal(self, vec, window=150): + + return np.convolve(vec, np.ones(window), 'valid') / window + + def _detrend_signal(self): + self._measured_data['detrend'] = signal.detrend(self._measured_data['amplitude']) + + # ================================================================================================================== + # Calculations and table creations + # ================================================================================================================== + def find_peaks(self): + self._detrend_signal() + vec = self._measured_data['detrend'] + _peaks, _ = find_peaks(vec, + height=self.measurement_properties.find_peaks.height, + distance=self.measurement_properties.find_peaks.distance, + prominence=self.measurement_properties.find_peaks.prominence) + peaks = np.zeros(len(vec)) + peaks[_peaks] = 1 + self._measured_data['peaks'] = peaks.astype(bool) + self._peaks = self._tables.update(self._measured_data[self._measured_data['peaks'] == True], '_peaks') + self.logger.debug(f"[{self}] | Found {len(self._peaks)} peaks. " + f"Parameters {self.measurement_properties.find_peaks}") + + def calulate_all(self, recalculate=False): + if not self._calculated or recalculate: + self.logger.info(f"[{self}] | Recalculating measurements {str(self)}") + + self.find_peaks() + self.calculate_wg_params() + self._calculated = True + + # ================================================================================================================== + # Filtering (old) + # ================================================================================================================== + def apply_filter(self): + if not self._ad2_properties_set: + raise Exception("AD2 properties not set. Please set them first.") + + if not self._laser_properties_set: + raise Exception("Laser properties not set. Please set them first.") + + ( + self._filtered_amplitude, + first_start, self.start_idx, + first_end, self.end_idx, + self.signal_end_expected, + self.marker_start, + self.marker_stop + ) = self.filter_signal(self.measured_data, column='measurements') + + self.time_start_point = self.start_idx / self.ad2_sample_rate + self.time_end_point = self.end_idx / self.ad2_sample_rate + self.time_end_point_expected = self.signal_end_expected / self.ad2_sample_rate + + self._filtered_amplitude = self.assign_wavelength(self._filtered_amplitude, self.wavelength_range[0], + self.wavelength_range[1]) + self.signal_length = len(self._filtered_amplitude) + + # Sanity check if the found length is approximatly the same as the expected length + tolerance = 0.025 # 2,5 % tolerance = 0.25 sec + if 1 - abs(self.signal_end_expected / self.end_idx) > tolerance: + raise Exception( + f"The found signal length ({self.signal_end_expected})" + f"is not approximatly the same as the expected signal length ({self.end_idx})." + ) + + return (self._filtered_amplitude, + self.start_idx, self.time_start_point, + self.end_idx, self.time_end_point, + self.signal_end_expected, self.time_end_point_expected + ) + + def find_index(self, samples_sweep=None, keyword='filtered', threshold=0.0005, reverse_signal=False): + rolling_keyword = 'rolling' + marker = { + 'first_hit': 0, + 'steady_mean': 0, + 'steady_mean_pt': 0, + 'steady_mean_mt': 0, + 'steady_min': 0, + 'steady_max': 0, + 'window_for_mean': [0, 0], + 'window_for_search': [0, 0], + 'second_hit': 0, + } + if reverse_signal: + self.logger.debug("[FILTER:FIND INDEX] Reversing the signal") + samples = samples_sweep[::-1] + samples = samples.reset_index(drop=True) + else: + samples = samples_sweep + + # create a new dataframe + # Drop values that have been already marked as invalid + samples = samples.dropna() + + # ***************************************************************************************** + # (1): Extract 200 ms and calculate a mean value. This will be used to find the + # approximative start point of the signal. + # (1.1) Cut a part that we are sure is steady (e.g. 100 ms after the start up to 300ms) + start_idx = int(self.ad2_sample_rate / 10) + stop_idx = int((self.ad2_sample_rate / 10) * 3) + sample_window_steady = samples[keyword][start_idx:stop_idx] + self.logger.debug( + "[FILTER:FIND INDEX:1.1] Extract 200 ms and find min and max values. start_idx %s, stop_idx %s" % ( + start_idx, stop_idx)) + # (1.2) We now want to approximatly find the part where the signal starts rising or fluctuatig. + # This is, where the Signal is greater than our min or max values + # Also, store these values as a marker + signal_min = float(sample_window_steady.min()); + marker['steady_min'] = signal_min + signal_max = float(sample_window_steady.max()); + marker['steady_max'] = signal_max + self.logger.debug( + "[FILTER:FIND INDEX:1.2] Signal processed. signal_min %s, signal_max %s" % (signal_min, signal_max)) + # (1.3) Extract the first approximate starting position. This is, where the signal exceed + # our min or max values. We have found the first approximate starting point. + index_first_hit = samples[ + (samples[rolling_keyword] >= signal_max) | (samples[rolling_keyword] <= signal_min) + ].first_valid_index() + index_first_hit_abs = samples.index1[index_first_hit] + self.logger.info( + f"[FILTER:FIND INDEX:1.3] First index found at {index_first_hit_abs / self.ad2_sample_rate} sec. index_first_hit {int(index_first_hit_abs)}/{len(samples)} (rel: {index_first_hit})") + + # ***************************************************************************************** + # (2) Now we want to calculate a mean that is near our starting point. For this, we go back + # 200 ms and calculate the mean of 200 ms. This should yield to a mean value that corresponds + # to our signal shortly bevor it starts. + value = int(self.ad2_sample_rate / 10) + if reverse_signal: + start_idx = int(index_first_hit - value * 4) + start_idx_abs = int(index_first_hit_abs + value * 2) + stop_idx = int(index_first_hit - value * 2) + stop_idx_abs = int(index_first_hit_abs + value * 4) + else: + start_idx = int(index_first_hit - value * 4) + start_idx_abs = int(index_first_hit_abs - value * 4) + stop_idx = int(index_first_hit - value * 2) + stop_idx_abs = int(index_first_hit_abs - value * 2) + + window_for_mean = samples[keyword].loc[start_idx:stop_idx]; + marker['window_for_mean'] = [start_idx_abs, stop_idx_abs] + self.logger.debug( + "[FILTER:FIND INDEX:2.1] Extract 200 ms and calculate a new mean value. start_idx %s (rel %s), stop_idx %s (rel: %s). len <%s>" + % (start_idx_abs, start_idx, + stop_idx_abs, stop_idx, len(window_for_mean))) + # (2.1) Calculate the mean value of the 200 ms window + signal_mean = float(window_for_mean.mean()); + marker['steady_mean'] = signal_mean + self.logger.debug("[FILTER:FIND INDEX:2.2] Signal processed. signal_mean %s" % (signal_mean)) + + # ***************************************************************************************** + # (3) Since we have found a mean value that hopefully cooresponds to our mean value of the steady + # part near our first starting point, we can try to find a more accurate starting point. + # Again, this si done by defining a threshold that, if exceeded, mark our new, more accurate starting point. + treshold_max = signal_mean * (1 + threshold); + marker['steady_mean_pt'] = treshold_max + treshold_min = signal_mean * (1 - threshold); + marker['steady_mean_mt'] = treshold_min + self.logger.debug( + "[FILTER:FIND INDEX:3.1] Defining new thresholds for mean: <%s>: treshold_max <%s>, treshold_min <%s>" % ( + signal_mean, treshold_max, treshold_min)) + + # (3.1) New get a window of our expected signal start. + # self.print_m("[3]: dataframe 'samples_cut \n%s" % samples) + value = int(self.ad2_sample_rate / 10) + start_idx = int(index_first_hit - value) + start_idx_abs = int(index_first_hit_abs - value) + stop_idx = int(index_first_hit + value) + stop_idx_abs = int(index_first_hit_abs + value) + window_for_search = samples.loc[start_idx:stop_idx]; + marker['window_for_search'] = [start_idx_abs, stop_idx_abs] + self.logger.debug( + "[FILTER:FIND INDEX:3.2] Extract 200 ms around the starting point. start_idx %s (rel %s), stop_idx %s (rel: %s). len <%s>" + % (start_idx_abs, start_idx, stop_idx_abs, stop_idx, len(window_for_search))) + # (3.2) Now we want to find the first point where the signal exceeds our threshold. + index_second_hit = window_for_search[ + (window_for_search[rolling_keyword] > treshold_max) | (window_for_search[rolling_keyword] < treshold_min) + ].first_valid_index() + if index_second_hit is None: + raise Exception("End of Signal not found. index_second_hit %s" % index_second_hit) + # (3.3) This window may have not the corrct indices. We need to get the correct one + index_second_hit_abs = samples.index1[index_second_hit] + self.logger.info( + f"[FILTER:FIND INDEX:3.3] Second index found at {index_second_hit_abs / self.ad2_sample_rate} sec. index_second_hit {index_second_hit_abs}/{len(samples)} (rel: {index_second_hit})" + ) + + if index_second_hit == None: + index_second_hit = 0 + else: + index_second_hit = samples.index1[index_second_hit] + marker['second_hit'] = index_second_hit + index_first_hit = samples.index1[index_first_hit] + marker['first_hit'] = index_first_hit + + return index_first_hit_abs, index_second_hit_abs, marker + + def filter_signal(self, measured_amplitude, column='measurements'): + self.logger.info("[FILTER] Applying filter to given signal.") + # Filter the first second of the measurement + measured_amplitude = measured_amplitude.reset_index().rename({'index': 'index1'}, axis='columns') + measured_amplitude['filtered'] = measured_amplitude[column] + measured_amplitude.loc[:self.ad2_sample_rate] = None + # Calculate the moving average + measured_amplitude["rolling"] = measured_amplitude['filtered'].rolling(window=1000).mean().shift( + -500) # [1000-1:] # 0,01nm + self.logger.debug(f"[FILTER] Total Length of given signal {len(measured_amplitude)}") + + first_start, second_start, marker_start = self.find_index(measured_amplitude, column) + self.logger.info(f"[FILTER] Starting index found at {second_start} (first hit at {first_start}) ") + measured_amplitude['filtered'].loc[:second_start] = None + + # Now we need to find the end of the signal. For this we assume, that the laser movement is "nearly" correct. + # The laser waits approximatly 500 ms to move the laser back to it's starting position. + index_signal_end_expected = int(second_start + (self.laser_movement_time * self.ad2_sample_rate)) + self.logger.debug(f"[FILTER] Expected end: {index_signal_end_expected}") + + # We found the expected length, the laser waits for 500 ms until moving back + # We want to use this, to get the mean value of the amplitude of this specific wave length + # For this we cut the signal 400 ms (= ad2_sample_rate * 0.4) after the expected end + measured_amplitude['filtered'].loc[int(index_signal_end_expected + (self.ad2_sample_rate * 0.4)):] = None + # Reverse the signal and do the same procedure again + + first_end, second_end, marker_stop = self.find_index(measured_amplitude, column, reverse_signal=True) + self.logger.info(f"[FILTER] End index found at {second_end} (first hit at {first_end}).") + measured_amplitude['filtered'].loc[second_end:] = None + + measured_amplitude.dropna(inplace=True) + # measured_amplitude = measured_amplitude.drop(['index1'], axis = 1) + filtered_aplitude = measured_amplitude.filter(['filtered'], axis=1).reset_index(drop=True) + self.logger.info( + f"[FILTER] AD2 sample rate: {self.ad2_sample_rate} samples/sec. " + f"AD2 samples: {self.ad2_total_samples} samples. " + f"AD2 measurement duration: {self.ad2_total_measurement_time} sec." + ) + self.logger.info( + f"[FILTER] Laser movement ({self.wavelength_range[0]}-{self.wavelength_range[1]}): {self.laser_movement_time} sec. " + f"Laser velovity: {self.laser_velocity} m/s. " + f"Laser samples expected: {self.laser_samples_expected} samples ({self.laser_samples_expected / self.ad2_sample_rate}) sec." + ) + self.logger.info( + f"[FILTER] Signal length {len(self._measured_data)} ({len(self._measured_data) / self.ad2_sample_rate} sec). " + f"Start {second_start} ({second_start / self.ad2_sample_rate} sec). " + f"End {second_end} ({second_end / self.ad2_sample_rate} sec). " + f"Expected: {index_signal_end_expected} ({index_signal_end_expected / self.ad2_sample_rate} sec). " + f"Diff {second_end - second_start} ({second_end / self.ad2_sample_rate - second_start / self.ad2_sample_rate} sec)." + ) + + # self.print_m(samples_sweep_down) + return (filtered_aplitude, + first_start, second_start, + first_end, second_end, + index_signal_end_expected, + marker_start, + marker_stop + ) + + def assign_wavelength(self, filtered_amplitude: list = None, wavelength_start: float = 850, + wavelength_stop: float = 855, start_point: int = None): + measurment_points = len(filtered_amplitude) + filtered_amplitude['wavelength'] = pd.Series( + np.linspace(wavelength_start, wavelength_stop, measurment_points) + ) + # filtered_amplitude.set_index('wavelength',inplace=True) + # if start_point is None: + # # Get the number of measruement points (should be 50000): + + # #self.print_m(measurment_points) + + # #self.print_m(measured_amplitude) + # else: + # # We need to assign the first n (up to the start_point) points the l + # end_point = start_point + self.laser_samples_expected + # filtered_amplitude['wavelength'] = 0 + # filtered_amplitude.loc[0:start_point-1, 'wavelength'] = wavelength_start + # filtered_amplitude.loc[start_point:end_point, 'wavelength'] = pd.Series( + # np.linspace(wavelength_start, wavelength_stop, measurment_points) + # ) + # filtered_amplitude.loc[end_point+1:measurment_points-1, 'wavelength'] = wavelength_stop + + return filtered_amplitude + + # ================================================================================================================== + # To dicts + # ================================================================================================================== + def save(self, filename: str = None): + self.filename = filename + self._save_mat_file(self.filename) + #self._save_measurement_parquet(self.measurement_file) + + def _save_measurement_parquet(self, filename: str = None): + # Save the measurement file + + if filename is None: + filename = self.filename + filename = filename.replace('.mat', '.parquet') + self.measurement_file = filename + self._measured_data.to_parquet(self.measurement_file) + self.logger.info(f"Saved measurement file to {self.measurement_file}") + + def to_dict(self) -> dict: + return { + "laser_properties": self._laser_properties.to_dict(), + "ad2_properties": self._ad2_properties.to_dict(), + "wafer_properties": self._wafer_properties.to_dict(), + "measurement_properties": self._measurement_properties.to_dict(), + #"waveguide_properties": self._waveguide_properties.to_dict(), + #"measurement_file": str(Path(self.measurement_file).absolute().relative_to(Path(self._mat_filename).parent)), + "amplitude": self._measured_data['amplitude'].to_list(), + "wavelength": self._measured_data['wavelength'].to_list(), + "amplitude_detrended": self._measured_data['detrend'].to_list(), + 'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "version": "2.0.0" + } + + # def flatten(self, parent_key='', sep='.'): + # items = [] + # for key, value in self.to_dict().items(): + # new_key = f"{parent_key}{sep}{key}" if parent_key else key + # if isinstance(value, dict): + # items.extend(self.flatten(new_key, sep=sep).items()) + # else: + # items.append((new_key, value)) + # return dict(items) + + def plot(self): + + downsample = 100 + filtered_amplitude_down = self._measured_data.copy() + filtered_amplitude_down = filtered_amplitude_down[filtered_amplitude_down.reset_index().index % downsample == 0] + # measured_amplitude = self.measured_amplitude.copy() + # measured_amplitude = measured_amplitude[ + # measured_amplitude.reset_index().index % downsample == 0] # [240000:300000] + # app.run_server(debug=True, port=8050) + fig = make_subplots( + rows=2, cols=1, + subplot_titles=("filtered", "measurement") + ) + fig.append_trace( + go.Scatter( + x=self._measured_data['wavelength'], + y=self._measured_data['amplitude']), + row=1, col=1 + ) + + # fig.append_trace( + # go.Scatter(x=measured_amplitude.index, y=measured_amplitude['measurements']), + # row=2, col=1 + # ) + + fig.add_vrect(x0=self.wl_acc_stop, x1=self.wl_dec_start, row=1, col=1, + annotation_text="valid: %s" % self._measurement_length, annotation_position="top left", + fillcolor="green", opacity=0.25, line_width=0) + + # fig.update_layout(title_text=str(self._wafer_nr)) + + html = fig.to_html(full_html=False, include_plotlyjs='cdn') + # html += '</body></html>' + + with open('p_graph.html', 'a') as f: + f.write(html) + + return html + # fig.show() + + # ================================================================================================================== + # + # ================================================================================================================== + def enable_print(self, enable: bool = True): + self.print_enabled = enable + + def print_m(self, *args, **kwargs): + if self.print_enabled: + self.logger.info(*args, **kwargs) + + +if __name__ == "__main__": + app = QApplication() + + # Load a mat file from E:\03_Simulations\03_Simulations\measurements\Ary1 using scipy + setup_logging() + # filename = r"E:\03_Simulations\03_Simulations\measurements\Ary1\Ary1_2021-03-10_15-00-00.mat" + data1 = SingleMeasuredData.from_mat( + r"support/measurement_die_22_struct_mzi2_2_20220306_1908_rep_11.mat" + ) + data1.calulate_all() + data1._save_mat_file(r'test.mat') + + data2 = SingleMeasuredData.from_mat_v2(r'test.mat') + print("done") diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MatplotlibPlottingHelpers.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MatplotlibPlottingHelpers.py new file mode 100644 index 0000000000000000000000000000000000000000..0877d48ba056628516fba5707bba7668e2e7b358 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MatplotlibPlottingHelpers.py @@ -0,0 +1,26 @@ +import numpy as np +import pandas as pd + +import mcpy + + +class MPLPlottingHelper: + + @staticmethod + def plt_errorbar_mcsamples(plot_widget, x_values: pd.Series, y_values: pd.Series, + xlable='Wavelength [nm]', ylable='(nm)'): + x = x_values + #y_values = y_values + y = y_values.apply(lambda row: row.mean) + err = y_values.apply(lambda row: row.uncertainty.ustd) + plot_widget.ax.clear() + # Plot the simple line + plot_widget.ax.errorbar(x, y, err) + #plot_widget.ax.set_xlim(np.min(data[x_axis]), np.max(data[x_axis])) + #plot_widget.ax.set_ylim(np.min(data[y_axis]), np.max(data[y_axis])) + # Scatter plot of the peaks + plot_widget.ax.set_xlabel(xlable) + plot_widget.ax.set_ylabel(ylable) + plot_widget.ax.grid(True) + + plot_widget.canvas.draw() diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasuredDataModel.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasuredDataModel.py new file mode 100644 index 0000000000000000000000000000000000000000..91a7a2ad1881fec1c6ec3fe9f96447f08c7f4e29 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasuredDataModel.py @@ -0,0 +1,70 @@ +from PySide6.QtCore import Qt, QAbstractItemModel, QModelIndex, Signal +import collections + +from PySide6.QtGui import QStandardItem +from PySide6.QtWidgets import QTreeWidgetItem, QTreeWidget + +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class MeasuredDataTree(QTreeWidget): + + selected_data_changed = Signal(int) + + def __init__(self, measured_data_list: list[SingleMeasuredData]): + super().__init__() + self.setHeaderLabels(['Name', 'Xin', 'Yin', 'Xout', 'Yout', 'number']) + self.grouped_data = {} + self.measured_data_list = measured_data_list + for it, data in enumerate(self.measured_data_list): + if data.wafer_properties.wafer_number not in self.grouped_data: + self.grouped_data[data.wafer_properties.wafer_number] = {} + if data.wafer_properties.die_number not in self.grouped_data[data.wafer_properties.wafer_number]: + self.grouped_data[data.wafer_properties.wafer_number][data.wafer_properties.die_number] = [] + self.grouped_data[data.wafer_properties.wafer_number][data.wafer_properties.die_number].append((data, it)) + self.populate_tree() + + + + + def populate_tree(self): + + for wafer, die_dict in self.grouped_data.items(): + wafer_item = QTreeWidgetItem([f'Wafer {wafer}']) + for die, data_list in die_dict.items(): + die_item = QTreeWidgetItem([f'Die {die}']) + for data in data_list: + data, it = data + print(it) + data_item = QTreeWidgetItem([ + data.wafer_properties.structure_name, + str(data.wafer_properties.structure_x_in), + str(data.wafer_properties.structure_y_in), + str(data.wafer_properties.structure_x_out), + str(data.wafer_properties.structure_y_out), + str(it) + ]) + die_item.addChild(data_item) + wafer_item.addChild(die_item) + self.addTopLevelItem(wafer_item) + + # def selected_data(self): + # item = self.currentItem() + # if item.parent(): + # # Return MeasuredData instance for selected die + # wafer_item = item.parent() + # wafer_num = int(wafer_item.text(0).split()[-1]) + # die_num = int(item.text(0).split()[-1]) + # for data in self.measured_data_list: + # if data.wafer_number == wafer_num and data.die_number == die_num: + # return data + # else: + # # Return None for selected wafer + # return None + + def mouseDoubleClickEvent(self, event): + + item = self.currentItem() + print(item) + if item: + self.selected_data_changed.emit(int(item)) diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py new file mode 100644 index 0000000000000000000000000000000000000000..1a685ec39967f90049a0412301649b1e7482c589 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py @@ -0,0 +1,132 @@ +import logging +import time +from dataclasses import dataclass +from os import listdir +from os.path import isfile, join +from pathlib import Path +from typing import Dict, Any + +from PySide6.QtCore import Qt +from PySide6.QtWidgets import QProgressDialog, QWidget + +import MeasurementEvaluationTool as met +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + +from wrappers.QProgressBarWindow import QProgressBarWindow + + +class MeasurementDataLoader(QWidget): + + @staticmethod + def glob_files(path, glob): + """Recursively glob for files in a directory and subdirectories. Returns a list of paths""" + # use list comprehension and rglob + return [f for f in Path(path).rglob(glob)] + + @classmethod + def from_folder(cls, path, to_database): + logging.info(f"Opening path {path}") + files = MeasurementDataLoader.glob_files(path, "*.mat") #[Path(f"{path}/{f}").absolute() for f in listdir(path) if isfile(join(path, f)) and ".mat" in f] + logging.info(f"Found {len(files)}.") + + mea_list = [] + for i, f, it in QProgressBarWindow(files): + it.print(f"Loading measurement {str(f.name)}") + + #try: + #mea_list.append(SingleMeasuredData.from_mat_v2(f)) + to_database.add_data(SingleMeasuredData.from_mat_v2(f)) + #except Exception as e: + # logging.error(f"Could not load file {f.name}: {e}") + + return cls(mea_list) + + def __init__(self, data: list[SingleMeasuredData]): + super().__init__() + self._data = data + self.logger = logging + self._wafers = set() + self._dies = set() + self._structure_name = set() + self._sorted_files = self.classify(self._data) + # Now classify + + @property + def structure_name(self) -> set[str]: + return self._structure_name + + @property + def sorted_files(self) -> dict[str, dict[int, dict[Any, list[SingleMeasuredData]]]]: + return self._sorted_files + + @property + def dies(self) -> set[int]: + return self._dies + + @property + def wafers(self) -> set[str]: + return self._wafers + + def classify(self, measurement_data: list[SingleMeasuredData]): + sorted_files = {} + for i, measurement, it in QProgressBarWindow(measurement_data): + it.print(f"Classifying {measurement}") + self.add_to_list(sorted_files, measurement) + return sorted_files + + def get_measurement_series(self, wafer_number=None, die_number=None, structure_name=None) -> list[SingleMeasuredData]: + if wafer_number is None and len(self._sorted_files.keys()) > 1: + raise Exception(f"Wafer Number is ambiguous ({len(self._sorted_files)} possibilities). " + f"Please specify the wafer number!") + elif wafer_number is None: + wafer_number = list(self._sorted_files.keys())[0] + print(f"Wafer Number is not ambiguous. Selected wafer number {wafer_number}") + + if die_number is None and len(self._sorted_files[wafer_number]) > 1: + raise Exception(f"Die Number is ambiguous ({len(self._sorted_files[wafer_number])} possibilities). " + f"Please specify the wafer number!") + elif die_number is None: + die_number = list(self._sorted_files[wafer_number].keys())[0] + print(f"Die Number is not ambiguous. Selected die number {die_number}") + + if structure_name is None and len(self._sorted_files[wafer_number][die_number]) > 1: + raise Exception(f"Structure name is ambiguous ({len(self._sorted_files[wafer_number][die_number])} " + f"possibilities). Please specify the structure name!") + elif structure_name is None: + structure_name = list(self._sorted_files[wafer_number][die_number].keys())[0] + print(f"Structure name is not ambiguous. Selected structure name {structure_name}") + + return self._sorted_files[wafer_number][die_number][structure_name] + + def get_measurement(self, repetition, wafer_number=None, die_number=None, structure_name=None, ) -> SingleMeasuredData: + return self.get_measurement_series(wafer_number, die_number, structure_name)[repetition] + + def add_to_list(self, sorted_files: dict, measurement: SingleMeasuredData): + """ + Adds a measurement to the measurement list + """ + wafer_number = measurement.wafer_properties.wafer_number + die_number = measurement.wafer_properties.die_number + structure_name = measurement.wafer_properties.structure_name + + + if (wafer_number in sorted_files and + die_number in sorted_files[wafer_number] and + structure_name in sorted_files[wafer_number][die_number]): + sorted_files[wafer_number][die_number][structure_name].append(measurement) + elif (wafer_number in sorted_files and + die_number not in sorted_files[wafer_number]): + sorted_files[wafer_number][die_number] = {structure_name: [measurement]} + elif (wafer_number in sorted_files and + die_number in sorted_files[wafer_number] and + structure_name not in sorted_files[wafer_number][die_number]): + sorted_files[wafer_number][die_number][structure_name] = [measurement] + else: + sorted_files[wafer_number] = {die_number: {structure_name: [measurement]}} + self._wafers.add(wafer_number) + self._dies.add(die_number) + self._structure_name.add(structure_name) + +if __name__ == "__main__": + mypath = r'E:\test_measurements' + mm_data = MeasurementDataLoader(mypath) diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataTables.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataTables.py new file mode 100644 index 0000000000000000000000000000000000000000..5810242617a638facf5de65af75929aa2d283235 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataTables.py @@ -0,0 +1,45 @@ +import pandas as pd + +class MeasurementDataTables: + + def __init__(self): + self._hidden_friendly_name: dict = {} + self._hidden_table_plt_functions: dict = {} + + def append(self, new_table: pd.DataFrame, name, friendly_name=None): + if friendly_name is None: + friendly_name = name + self.__setattr__(name, new_table) + self._hidden_friendly_name[name] = friendly_name + + return getattr(self, name) + + def add_plot(self, name, plot_function = None): + if plot_function: + self._hidden_table_plt_functions[f"{name}"] = plot_function + return getattr(self, name) + + def update(self, new_table: pd.DataFrame, name): + self.__setattr__(name, new_table) + return getattr(self, name) + + def to_list(self) -> list[(pd.DataFrame, str, str)]: + # write a function that returns all attributes of this class + return [ + (getattr(self, a), str(a), str(self._hidden_friendly_name[a])) for a in dir(self) + if not a.startswith('__') + and not callable(getattr(self, a)) + and not '_hidden' in str(a) + ] + + def get(self, table_name: str) -> pd.DataFrame: + return getattr(self, table_name) + + def get_plot_function(self, name): + return self._hidden_table_plt_functions[name] + + def get_plot_function_names(self): + return self._hidden_table_plt_functions.keys() + + def plot(self): + pass diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..ac931f73649fc750400125673beb850275b87a58 --- /dev/null +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py @@ -0,0 +1,203 @@ +import numpy as np +from PySide6.QtCore import Signal + +import mcpy +from mcpy import Uncertainty + +from generics.GenericProperties import GenericProperties + + +class MPropertiesFindPeaks(GenericProperties): + properties_changed = Signal() + + def __init__(self, prominence: float | None, distance: float | None, height: float | None): + super().__init__() + self.set_properties(prominence, distance, height) + + def set_properties(self, prominence: float | None, distance: float | None, height: float | None): + self._prominence = prominence + self._distance = distance + self._height = height + self.properties_changed.emit() + + @property + def height(self): + return self._height + + @height.setter + def height(self, value): + self._height = value + self.properties_changed.emit() + + @property + def prominence(self): + return self._prominence + + @prominence.setter + def prominence(self, value): + self._prominence = value + self.properties_changed.emit() + + @property + def distance(self): + return self._distance + + @distance.setter + def distance(self, value): + self._distance = value + self.properties_changed.emit() + + def fields(self) -> dict: + return { + 'prominence': self.prominence if self.prominence is not None else np.NaN, + 'distance': self.distance if self.prominence is not None else np.NaN, + 'height': self.height if self.height is not None else np.NaN, + } + + def __str__(self): + return f"h: {self.height} - d: {self.distance} - p: {self.prominence}" + + +class WaveguideProperties(GenericProperties): + def __init__(self, length: Uncertainty, width: Uncertainty, height: Uncertainty): + super().__init__() + self._length: Uncertainty = length + self._width: Uncertainty = width + self._height: Uncertainty = height + + @property + def height(self): + return self._height + + @height.setter + def height(self, value): + self._height = value + + @property + def length(self): + return self._length + + @length.setter + def length(self, value): + self._length = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + def fields(self) -> dict: + return { + 'width': self.width.to_tuple(), + 'length': self.length.to_tuple(), + 'height': self.height.to_tuple(), + } + +class WaveguidePropertiesMZI(WaveguideProperties): + def __init__(self, length1: Uncertainty, length2: Uncertainty, width: Uncertainty, height: Uncertainty): + + self._arm1 = WaveguideProperties(length1, width, height) + self._arm2 = WaveguideProperties(length2, width, height) + super().__init__(mcpy.Uncertainty(float(self._arm1.length) - float(self._arm2.length)), width, height) + + @property + def length_diff(self): + return self._length_diff + + @length_diff.setter + def length_diff(self, value): + self._length_diff = value + + @property + def arm1(self): + return self._arm1 + + @arm1.setter + def arm1(self, value): + self._arm1 = value + + @property + def arm2(self): + return self._arm2 + + @arm2.setter + def arm2(self, value): + self._arm2 = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + def fields(self) -> dict: + return { + 'width': self.width, + 'length': self.length, + 'arm1': self.arm1, + 'arm2': self.arm2 + } + +class WaveguidePropertiesMRR(WaveguideProperties): + def __init__(self, length, width: float, radius, gap: float): + super().__init__() + super().__init__(length, width) + self._radius = radius + self._gap = gap + + @property + def length_diff(self): + return self._length_diff + + @length_diff.setter + def length_diff(self, value): + self._length_diff = value + + @property + def arm1(self): + return self._arm1 + + @arm1.setter + def arm1(self, value): + self._arm1 = value + + @property + def arm2(self): + return self._arm2 + + @arm2.setter + def arm2(self, value): + self._arm2 = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + +class MeasurementProperties(GenericProperties): + def __init__(self, find_peaks_properties: MPropertiesFindPeaks): + super().__init__() + self._find_peaks = find_peaks_properties + + @property + def find_peaks(self): + return self._find_peaks + + @find_peaks.setter + def find_peaks(self, value): + self._find_peaks = value + + def fields(self) -> dict: + return { + 'find_peaks': self.find_peaks.fields(), + 'test': 1 + } diff --git a/src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py b/src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..231b75c81572eb64175920632ffaeb01129645e7 --- /dev/null +++ b/src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py @@ -0,0 +1,79 @@ +import pandas as pd + +from MeasurementData.Properties.GenericProperties import GenericProperties + + +class AD2CaptDeviceProperties(GenericProperties): + + def __init__(self, samples_lost: float, samples_corrupted: float, + acquisition_rate: float, n_samples: int, + measurement_time: float): + super().__init__() + # Laser properties + self._samples_lost: float = self.to_float(samples_lost) + self._samples_currputed: float = self.to_float(samples_corrupted) + self._sample_rate: float = self.to_float(acquisition_rate) + self._n_samples: int = self.to_int(n_samples) + self._measurement_time: float = self.to_float(measurement_time) + + @property + def samples_lost(self): + return self._samples_lost + + @samples_lost.setter + def samples_lost(self, value): + self._samples_lost = value + + @property + def samples_corrupted(self): + return self._samples_currputed + + @samples_corrupted.setter + def samples_corrupted(self, value): + self._samples_currputed = value + + @property + def n_samples(self): + return self._n_samples + + @n_samples.setter + def n_samples(self, value): + self._n_samples = value + + @property + def measurement_time(self): + return self._measurement_time + + @measurement_time.setter + def measurement_time(self, value): + self._measurement_time = value + + @property + def sample_rate(self): + return self._sample_rate + + @sample_rate.setter + def sample_rate(self, value): + self._sample_rate = value + + + def to_dict(self) -> dict: + return { + 'samples_lost': self.samples_lost, + 'samples_corrupted': self.samples_corrupted, + 'n_samples': self.n_samples, + 'measurement_time': self.measurement_time, + 'acquisition_rate': self.sample_rate + } + + @classmethod + def from_dict(cls, mat_struct): + return cls( + samples_lost=mat_struct['samples_lost'], + samples_corrupted=mat_struct['samples_corrupted'], + acquisition_rate=mat_struct['acquisition_rate'], + n_samples=mat_struct['n_samples'], + measurement_time=mat_struct['measurement_time'] + ) + + diff --git a/src/FlexSensor/MeasurementData/Properties/GenericProperties.py b/src/FlexSensor/MeasurementData/Properties/GenericProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..a112641f7fc64c3c074917318df0c7cf0fb0e047 --- /dev/null +++ b/src/FlexSensor/MeasurementData/Properties/GenericProperties.py @@ -0,0 +1,49 @@ +import pandas as pd +from PySide6.QtCore import QObject +from numpy import ndarray + +class GenericProperties(QObject,): + + def __init__(self): + + super().__init__() + + def to_str(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return self.to_str(value[0]) + else: + return str(value) + + def to_int(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return self.to_int(value[0]) + else: + return int(value) + + def to_float(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return self.to_float(value[0]) + else: + return float(value) + + def to_tuple(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return tuple(value[0]) + else: + return tuple(value) + + def to_dict(self) -> dict: + raise NotImplementedError + + @classmethod + def from_dict(self, data: dict): + raise NotImplementedError + + def to_sql(self, engine): + self.metadata.create_all(engine) + "Create a relational table in the database with the given engine" + with Session(engine) as session: + session.add(self) + session.commit() + # df = pd.DataFrame(self.to_dict()) + # df.to_sql(table_name, engine, if_exists='append', index=False) diff --git a/src/FlexSensor/MeasurementData/Properties/LaserProperties.py b/src/FlexSensor/MeasurementData/Properties/LaserProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..2b2947cbe02dac59c28b14a3e363be2686c51ab8 --- /dev/null +++ b/src/FlexSensor/MeasurementData/Properties/LaserProperties.py @@ -0,0 +1,68 @@ +import sys + +from MeasurementData.Properties.GenericProperties import GenericProperties +import mcpy + +sys.path.append('../mcpy/mcpy') +import mcpy + + +class LaserProperties(GenericProperties): + + def __init__(self, acceleration: mcpy.Uncertainty, deceleration: mcpy.Uncertainty, velocity: mcpy.Uncertainty, + wavelength_range: tuple): + super().__init__() + # Laser properties + self._acceleration: mcpy.Uncertainty = acceleration + self._deceleration: mcpy.Uncertainty = deceleration + self._velocity: mcpy.Uncertainty = velocity + self._wavelength_range: list | tuple = wavelength_range + + @property + def deceleration(self) -> mcpy.Uncertainty: + return self._deceleration + + @deceleration.setter + def deceleration(self, value): + self._deceleration = value + + @property + def velocity(self) -> mcpy.Uncertainty: + return self._velocity + + @velocity.setter + def velocity(self, value): + self._velocity = value + + @property + def wavelength_range(self) -> mcpy.Uncertainty: + return self._wavelength_range + + @wavelength_range.setter + def wavelength_range(self, value): + self._wavelength_range = value + + @property + def acceleration(self) -> mcpy.Uncertainty: + return self._acceleration + + @acceleration.setter + def acceleration(self, value): + self._acceleration = value + + def to_dict(self) -> dict: + return { + 'deceleration': 1.997,#float(self.deceleration), + 'velocity': 1.002,#float(self.velocity), + 'wavelength_range': [840, 860], # .to_tuple(), + 'acceleration': 1.997 #float(self.acceleration) + } + + @classmethod + def from_dict(cls, d): + return cls( + acceleration=mcpy.Uncertainty.from_dict(d['acceleration']), + deceleration=mcpy.Uncertainty.from_dict(d['deceleration']), + velocity=mcpy.Uncertainty.from_dict(d['deceleration']), + wavelength_range=() + ) diff --git a/src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py b/src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..12d544401fb913e439ae3a36cd30743c0472ca0c --- /dev/null +++ b/src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py @@ -0,0 +1,247 @@ +import numpy as np +from PySide6.QtCore import Signal + +import mcpy +from mcpy import Uncertainty, MCSamples + +from MeasurementData.Properties.GenericProperties import GenericProperties + + +class MPropertiesFindPeaks(GenericProperties): + + + properties_changed = Signal() + + def __init__(self, prominence: float | None, distance: float | None, height: float | None): + super().__init__() + self.set_properties(prominence, distance, height) + + def set_properties(self, prominence: float | None, distance: float | None, height: float | None): + self._prominence = prominence + self._distance = distance + self._height = height + self.properties_changed.emit() + + @property + def height(self): + return self._height + + @height.setter + def height(self, value): + self._height = value + self.properties_changed.emit() + + @property + def prominence(self): + return self._prominence + + @prominence.setter + def prominence(self, value): + self._prominence = value + self.properties_changed.emit() + + @property + def distance(self): + return self._distance + + @distance.setter + def distance(self, value): + self._distance = value + self.properties_changed.emit() + + def to_dict(self) -> dict: + return { + 'prominence': self.prominence if self.prominence is not None else np.NaN, + 'distance': self.distance if self.prominence is not None else np.NaN, + 'height': self.height if self.height is not None else np.NaN, + } + + @classmethod + def from_dict(cls, data: dict): + return cls( + data['prominence'] if not np.isnan(data['prominence']) else None, + data['distance'] if not np.isnan(data['distance']) else None, + data['height'] if not np.isnan(data['height']) else None + ) + + def __str__(self): + return f"h: {self.height} - d: {self.distance} - p: {self.prominence}" + + +class WaveguideProperties(GenericProperties): + + def __init__(self, length: Uncertainty, width: Uncertainty, height: Uncertainty): + super().__init__() + self._length: Uncertainty = length + self._width: Uncertainty = width + self._height: Uncertainty = height + + def group_index(self, lam0: MCSamples, FSR: MCSamples): + return (lam0 ** 2) / (FSR * self._length) + + @property + def height(self): + return self._height + + @height.setter + def height(self, value): + self._height = value + + @property + def length(self): + return self._length + + @length.setter + def length(self, value): + self._length = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + def to_dict(self) -> dict: + return { + 'width': self.width.to_dict(), + 'length': self.length.to_dict(), + 'height': self.height.to_dict(), + } + + @classmethod + def from_dict(cls, data: dict): + return cls( + Uncertainty.from_dict(data['length']), + Uncertainty.from_dict(data['width']), + Uncertainty.from_dict(data['height']) + ) + + +class WaveguidePropertiesMZI(WaveguideProperties): + + + def __init__(self, length1: Uncertainty, length2: Uncertainty, width: Uncertainty, height: Uncertainty): + self._arm1 = WaveguideProperties(length1, width, height) + self._arm2 = WaveguideProperties(length2, width, height) + super().__init__(mcpy.Uncertainty(float(self._arm1.length) - float(self._arm2.length)), width, height) + + def group_index(self, lam0: MCSamples, FSR: MCSamples): + return (lam0 ** 2) / (FSR * (self.arm2.length.rand(lam0.N) - + self.arm1.length.rand(lam0.N))) + + @property + def length_diff(self): + return self._length_diff + + @length_diff.setter + def length_diff(self, value): + self._length_diff = value + + @property + def arm1(self): + return self._arm1 + + @arm1.setter + def arm1(self, value): + self._arm1 = value + + @property + def arm2(self): + return self._arm2 + + @arm2.setter + def arm2(self, value): + self._arm2 = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + def to_dict(self) -> dict: + return { + 'width': self.width.to_dict(), + 'length': self.length.to_dict(), + 'arm1': self.arm1.to_dict(), + 'arm2': self.arm2.to_dict(), + 'height': self.height.to_dict(), + } + + @classmethod + def from_dict(cls, data: dict): + return cls( + length1=mcpy.Uncertainty.from_dict(data['arm1']['length']), + length2=Uncertainty.from_dict(data['arm2']['length']), + width=Uncertainty.from_dict(data['width']), + height=Uncertainty.from_dict(data['height']) + ) + + +class WaveguidePropertiesMRR(WaveguideProperties): + def __init__(self, length, width: float, radius, gap: float): + super().__init__() + super().__init__(length, width) + self._radius = radius + self._gap = gap + + @property + def length_diff(self): + return self._length_diff + + @length_diff.setter + def length_diff(self, value): + self._length_diff = value + + @property + def arm1(self): + return self._arm1 + + @arm1.setter + def arm1(self, value): + self._arm1 = value + + @property + def arm2(self): + return self._arm2 + + @arm2.setter + def arm2(self, value): + self._arm2 = value + + @property + def width(self): + return self._width + + @width.setter + def width(self, value): + self._width = value + + +class MeasurementProperties(GenericProperties): + def __init__(self, find_peaks_properties: MPropertiesFindPeaks): + super().__init__() + self._find_peaks = find_peaks_properties + + @property + def find_peaks(self): + return self._find_peaks + + @find_peaks.setter + def find_peaks(self, value): + self._find_peaks = value + + def to_dict(self) -> dict: + return { + 'find_peaks': self.find_peaks.to_dict(), + } + + @classmethod + def from_dict(cls, d: dict): + return cls( + find_peaks_properties=MPropertiesFindPeaks.from_dict(d['find_peaks']) + ) diff --git a/src/FlexSensor/MeasurementData/Properties/WaferProperties.py b/src/FlexSensor/MeasurementData/Properties/WaferProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..546de51e3e227faafd3c2a2b8e9f750eb8a95135 --- /dev/null +++ b/src/FlexSensor/MeasurementData/Properties/WaferProperties.py @@ -0,0 +1,108 @@ + + +from MeasurementData.Properties.GenericProperties import GenericProperties + + +class WaferProperties(GenericProperties): + + + def __init__(self, + wafer_number: str, structure_name: str, + die_nr: int, chuck_col: int, chuck_row: int, + structure_in: tuple, structure_out: tuple, + repetitions: int + ): + super().__init__() + self._structure_name = self.to_str(structure_name) + self._wafer_number = self.to_str(wafer_number) + + self._die_number = self.to_int(die_nr) + self._chuck_col = self.to_int(chuck_col) + self._chuck_row = self.to_int(chuck_row) + + self._structure_in = self.to_tuple(structure_in) + self._structure_out = self.to_tuple(structure_out) + self._structure_x_in = int(self._structure_in[0]) + self._structure_y_in = int(self._structure_in[1]) + self._structure_x_out = int(self._structure_out[0]) + self._structure_y_out = int(self._structure_out[1]) + + self._repetitions: int = self.to_int(repetitions) + + @property + def repetition(self): + return int(self._repetitions) + + @property + def chuck_col(self): + return int(self._chuck_col) + + @property + def chuck_row(self): + return int(self._chuck_row) + + @property + def wafer_number(self) -> str: + return str(self._wafer_number) + + @property + def structure_x_in(self): + return int(self._structure_x_in) + + @property + def structure_y_in(self): + return int(self._structure_y_in) + + @property + def structure_x_out(self): + return int(self._structure_x_out) + + @property + def structure_name(self): + return str(self._structure_name) + + @property + def die_number(self) -> int: + return int(self._die_number) + + @property + def structure_y_out(self): + return int(self._structure_y_out) + + @property + def structure_in(self): + return tuple(self._structure_in) + + @property + def structure_out(self): + return tuple(self._structure_out) + + @property + def chuck_row(self): + return int(self._chuck_row) + + def to_dict(self) -> dict: + return { + 'wafer_number': self.wafer_number, + 'die_number': self.die_number, + 'structure_name': self.structure_name, + 'repetition': self.repetition, + 'structure_in': self.structure_in, + 'structure_out': self.structure_out, + 'chuck_col': self.chuck_col, + 'chuck_row': self.chuck_row + + } + + @classmethod + def from_dict(cls, d: dict): + return cls( + wafer_number=d['wafer_number'], + die_nr=d['die_number'], + structure_name=d['structure_name'], + repetitions=d['repetition'], + structure_in=d['structure_in'], + structure_out=d['structure_out'], + chuck_col=d['chuck_col'], + chuck_row=d['chuck_row'] + ) \ No newline at end of file diff --git a/src/FlexSensor/MeasurementData/__init__.py b/src/FlexSensor/MeasurementData/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MeasurementData/tests/testfiles/load_all.m b/src/FlexSensor/MeasurementData/tests/testfiles/load_all.m new file mode 100644 index 0000000000000000000000000000000000000000..a9d12a2e008e05484775aafe784af9ec0083869d --- /dev/null +++ b/src/FlexSensor/MeasurementData/tests/testfiles/load_all.m @@ -0,0 +1 @@ +load('testfiles/load_all.m');data = readcsv('None'); \ No newline at end of file diff --git a/src/FlexSensor/MeasurementData/tests/tmp/load_all.m b/src/FlexSensor/MeasurementData/tests/tmp/load_all.m new file mode 100644 index 0000000000000000000000000000000000000000..284260549b90723aa2dbb4c94100899496cae33b --- /dev/null +++ b/src/FlexSensor/MeasurementData/tests/tmp/load_all.m @@ -0,0 +1 @@ +load('tmp/load_all.m');data = readcsv('None'); \ No newline at end of file diff --git a/src/FlexSensor/MeasurementData/tests/tmp/measurement_die_22_struct_mzi2_2_20220306_1908_rep_11_v2.mat b/src/FlexSensor/MeasurementData/tests/tmp/measurement_die_22_struct_mzi2_2_20220306_1908_rep_11_v2.mat new file mode 100644 index 0000000000000000000000000000000000000000..473d79a9bb81268364028c942632ce50b113c153 Binary files /dev/null and b/src/FlexSensor/MeasurementData/tests/tmp/measurement_die_22_struct_mzi2_2_20220306_1908_rep_11_v2.mat differ diff --git a/src/FlexSensor/MeasurementData/tests/tmp/measurement_v2.mat b/src/FlexSensor/MeasurementData/tests/tmp/measurement_v2.mat new file mode 100644 index 0000000000000000000000000000000000000000..8203321366c3ffb60ee771c18c3590fd34b3b80e Binary files /dev/null and b/src/FlexSensor/MeasurementData/tests/tmp/measurement_v2.mat differ diff --git a/src/FlexSensor/MeasurementEvaluation/__init__.py b/src/FlexSensor/MeasurementEvaluation/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MeasurementEvaluation/controller/MeasurementDataController.py b/src/FlexSensor/MeasurementEvaluation/controller/MeasurementDataController.py new file mode 100644 index 0000000000000000000000000000000000000000..73305f7e40f55557c8e46576c25139ebb344bfe7 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/controller/MeasurementDataController.py @@ -0,0 +1,60 @@ +import logging + +from MeasurementData.MeasuredData.MeasuredData import MeasuredData +from MeasurementData.MeasuredData.MultiMeasuredData import MultiMeasuredData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementData.MeasuredData.SupportClasses.MeasurementDataLoader import MeasurementDataLoader +from MeasurementEvaluation.model.MeasurementDataModel import MeasurementDataModel + + +class MeasurementDataController: + + def __init__(self, model: MeasurementDataModel, path): + self.logger = logging.getLogger("MeasurementDataController") + self._model = model + + self._model.path = path + self._md_loader = MeasurementDataLoader.from_folder(self._model.path) + + self._model.selected_measurements = [] + self._model.measurement_list = self._md_loader.sorted_files + + + @property + def consolidated_measurements(self): + return self._consolidated_measurements + + @consolidated_measurements.setter + def consolidated_measurements(self, value): + self._consolidated_measurements = value + + @property + def all_measurements(self): + return self._model.measurement_list + + @property + def list_of_measurements(self) -> list[SingleMeasuredData]: + return self._model.selected_measurements + + @property + def selected_measurement(self) -> SingleMeasuredData: + return self._model.display_measurement + + def select_measurement(self, selected_measurement: MeasuredData): + self._model.display_measurement = selected_measurement + + def consolidate_measurements(self, measurement_selection): + self._model.consolidated_measurement = MultiMeasuredData(measurement_selection) + self._model.selected_measurements = measurement_selection + self.select_measurement(self._model.consolidated_measurement) + + def recalculate_measurements(self, measurement_selection): + self.logger.info("Recalculating all measurements") + for md in measurement_selection: + md.calulate_all() + + def load_from_folder(self): + raise NotImplementedError + + def add_measurement(self): + pass \ No newline at end of file diff --git a/src/FlexSensor/MeasurementEvaluation/model/MeasurementDataModel.py b/src/FlexSensor/MeasurementEvaluation/model/MeasurementDataModel.py new file mode 100644 index 0000000000000000000000000000000000000000..5e55e292e0343f0eb2bda1a50bca42cff13b8950 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/model/MeasurementDataModel.py @@ -0,0 +1,85 @@ +from pathlib import Path + +from PySide6.QtCore import Signal, QObject + +from MeasurementData.MeasuredData.MultiMeasuredData import MultiMeasuredData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class MeasuredDataSignals(QObject): + path_changed = Signal(Path) + + list_of_measurements_changed = Signal(list) + all_measurements_changed = Signal(dict) + + num_of_measurements = Signal(int) + selected_measurement_changed = Signal(SingleMeasuredData) + consolidated_measurements_changed = Signal(MultiMeasuredData) + + +class MeasurementDataModel: + def __init__(self): + self.signals = MeasuredDataSignals() + + self._path: Path = None + self._measurement_list: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]] = None + + self._consolidated_measurement: MultiMeasuredData = None + self._display_measurement: SingleMeasuredData = None + self._selected_measurements: list[SingleMeasuredData] = [] + + self._num_of_measurements: int = 0 + + @property + def consolidated_measurement(self): + return self._consolidated_measurement + + @consolidated_measurement.setter + def consolidated_measurement(self, value): + self._consolidated_measurement = value + + @property + def path(self): + return self._path + + @path.setter + def path(self, value): + self._path = value + self.signals.path_changed.emit(self.path) + + @property + def measurement_list(self) -> dict[str, dict[int, dict[str, list[SingleMeasuredData]]]]: + return self._measurement_list + + @measurement_list.setter + def measurement_list(self, value: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]]) -> None: + self._measurement_list = value + self.signals.all_measurements_changed.emit(self.measurement_list) + + @property + def selected_measurements(self) -> list[SingleMeasuredData]: + return self._selected_measurements + + @selected_measurements.setter + def selected_measurements(self, value: list[SingleMeasuredData]) -> None: + self._selected_measurements = value + self.num_of_measurements = len(self.selected_measurements) + self.signals.list_of_measurements_changed.emit(self.selected_measurements) + + @property + def num_of_measurements(self) -> int: + return self._num_of_measurements + + @num_of_measurements.setter + def num_of_measurements(self, value: list[SingleMeasuredData]) -> None: + self._num_of_measurements = value + self.signals.num_of_measurements.emit(self.num_of_measurements) + + @property + def display_measurement(self) -> SingleMeasuredData: + return self._display_measurement + + @display_measurement.setter + def display_measurement(self, value: SingleMeasuredData) -> None: + self._display_measurement = value + self.signals.selected_measurement_changed.emit(self.display_measurement) diff --git a/src/FlexSensor/MeasurementEvaluation/model/PandasTableModel.py b/src/FlexSensor/MeasurementEvaluation/model/PandasTableModel.py new file mode 100644 index 0000000000000000000000000000000000000000..5c199832356abb7b39b9e08cf59a4ab742535720 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/model/PandasTableModel.py @@ -0,0 +1,30 @@ +from PySide6.QtCore import QAbstractTableModel, Qt +from PySide6.QtWidgets import QMenu + + +class PandasTableModel(QAbstractTableModel): + def __init__(self, df): + super().__init__() + self.df = df + + def rowCount(self, parent=None): + return self.df.shape[0] + + def columnCount(self, parent=None): + + return self.df.shape[1] + + def data(self, index, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + row = index.row() + col = index.column() + return str(self.df.iloc[row, col]) + return None + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + if orientation == Qt.Horizontal: + return str(self.df.columns[section]) + elif orientation == Qt.Vertical: + return str(self.df.index[section]) + return None diff --git a/src/FlexSensor/MeasurementEvaluation/view/MeasurementDataView.py b/src/FlexSensor/MeasurementEvaluation/view/MeasurementDataView.py new file mode 100644 index 0000000000000000000000000000000000000000..940431b847253567a469bca7de5931bc8539e0d7 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/view/MeasurementDataView.py @@ -0,0 +1,159 @@ +import sys + +import numpy as np +from PySide6.QtWidgets import QApplication, QWidget, QTableView, \ + QComboBox, QPushButton, QGridLayout + +import MeasurementData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementEvaluation.controller.MeasurementDataController import MeasurementDataController +from MeasurementEvaluation.model.MeasurementDataModel import MeasurementDataModel +from MeasurementEvaluation.model.PandasTableModel import PandasTableModel +from MeasurementData.MeasuredData.SupportClasses.MatplotlibPlottingHelpers import MPLPlottingHelper +from MeasurementEvaluation.view.ParameterAdjustmentView import ParameterAdjustmentWindow +from MeasurementEvaluation.view.widgets.MeasurementSelectionWidget import MeasurementSelectionWidget +from MeasurementEvaluation.view.widgets.PlotViewWidget import PlotViewWidget +from generics.logger import setup_logging + + +class MeasurementDataView(QWidget): + def __init__(self, model: MeasurementDataModel, controller: MeasurementDataController): + super().__init__() + self._model = model + self._controller = controller + self.layout = QGridLayout() + + self._model.signals.selected_measurement_changed.connect(self._on_selected_measurement_changed) + + self._init_ui() + + def _init_ui(self): + self.find_peaks_view = ParameterAdjustmentWindow() + + # Add a view for selecting the measurement + self.measurement_selection = MeasurementSelectionWidget(self._controller.all_measurements) + + self.measurement_selection.signals.open_find_peaks_window.connect(self._on_adapt_parameters_clicked) + self.measurement_selection.signals.on_consolidate_measurement_clicked.connect(self._on_consolidate_clicked) + self.measurement_selection.signals.on_recalculation_clicked.connect(self._on_recalculate_clicked) + self.measurement_selection.signals.on_show_item_click.connect(self._on_show_item_clicked) + + # self.measurement_selection.selection.selected_data_changed.connect(self._on_selection_changed) + self.layout.addWidget(self.measurement_selection, 0, 0, 2, 1) + + self.plot_widget = PlotViewWidget() # pg.PlotWidget() + self.layout.addWidget(self.plot_widget, 0, 1, 1, 1) + + # Display the data in an QTableWidget + self.table_view = QTableView() + self.layout.addWidget(self.table_view, 1, 1, 1, 1) + + # Add a dropdown + self.btn_consolidate = QPushButton('Consolidate all') + self.btn_consolidate.clicked.connect(self._on_consolidate_clicked) + self.layout.addWidget(self.btn_consolidate, 2, 0, 1, 1) + + self.dd_select_measurement_table = QComboBox() + self.dd_select_measurement_table.currentIndexChanged.connect(self._on_data_table_changed) + self.layout.addWidget(self.dd_select_measurement_table, 2, 1, 1, 1) + + self.setLayout(self.layout) + # self._controller.select_measurement(0) + + # ================================================================================================================== + # + # ================================================================================================================== + def _on_show_item_clicked(self, measurement_selection: SingleMeasuredData): + measurement_selection.calulate_all() + self._controller.select_measurement(measurement_selection) + + def _on_consolidate_clicked(self, measurement_selection): + self._controller.recalculate_measurements(measurement_selection) + self._controller.consolidate_measurements(measurement_selection) + # self._current_measurement = self._controller.consolidated_measurements + + def _on_recalculate_clicked(self, measurement_selection): + self._controller.recalculate_measurements(measurement_selection) + + def _on_adapt_parameters_clicked(self, measurement_selection): + self.find_peaks_view.measured_data_list = measurement_selection + self.find_peaks_view.show() + + def _on_selection_changed(self, it: int): + # self._controller.select_measurement(it) + self.measurement_selection.set_selected_data(self._controller.selected_measurement) + + def _on_data_table_changed(self, idx): + table_name = self.dd_select_measurement_table.itemData(idx) + print(f"{table_name} - {type(table_name)}") + # print(self._current_measurement.tables.get(table_name)) + table = self._controller.selected_measurement.tables.get(table_name) + # Define plt function here + self.table_view_model = PandasTableModel(table) + self.table_view.setModel(self.table_view_model) + + # This will be removed later and is only for quick and dirty hardcoded plotting + if table_name == "_measured_data": + pass + # self._plot_measurement_table(table_name) + elif table_name == "_wg_param": + self._controller.selected_measurement.tables.get_plot_function('ng (FSR)')(self.plot_widget) + + #self._plot_ng_table(table_name) + + def _on_selected_measurement_changed(self, measurement: MeasurementData): + self._current_measurement = measurement + # Populate the measurement ment selection + self.dd_select_measurement_table.clear() + for table in measurement.tables.to_list(): + # id in table -> table[2] = 'Friendly name', table[1] = 'table name' + self.dd_select_measurement_table.addItem(table[2], table[1]) + #self.dd_select_measurement_table.addItem( measurement.tables.to_list()[2][2], table[2][1]) + + # ================================================================================================================== + # + # ============================================================================================================= + def _plot_measurement_table(self, table_name, x_axis="wavelength", y_axis="detrend"): + self.plot_widget.ax.clear() + data = self._controller.selected_measurement.tables.get(table_name) + self.plot_widget.ax.plot(data[x_axis], data[y_axis], 'b-')[0] + self.plot_widget.ax.set_xlim(np.min(data[x_axis]), np.max(data[x_axis])) + self.plot_widget.ax.set_ylim(np.min(data[y_axis]), np.max(data[y_axis])) + # Scatter plot of the peaks + df_peaks = self._current_measurement.peaks + self.plot_widget.ax.scatter(df_peaks[x_axis], df_peaks[y_axis], marker='x', color='red') + self.plot_widget.ax.set_xlabel('Wavelength [nm]') + self.plot_widget.ax.set_ylabel('Amplitude [1]') + self.plot_widget.ax.set_title('Measured data') + self.plot_widget.ax.grid(True) + self.plot_widget.ax.legend([y_axis, 'Peaks']) + + self.plot_widget.canvas.draw() + + def _plot_ng_table(self, table_name, x_axis="lambda", y_axis="FSR"): + self.plot_widget.ax.clear() + data = self._controller.selected_measurement.tables.get(table_name) + self.plot_widget.ax.plot(data[x_axis], data[y_axis]) + self.plot_widget.ax.set_xlim(np.min(data[x_axis]), np.max(data[x_axis])) + self.plot_widget.ax.set_ylim(np.min(data[y_axis]), np.max(data[y_axis])) + # Scatter plot of the peaks + self.plot_widget.ax.set_xlabel('Wavelength [nm]') + self.plot_widget.ax.set_ylabel(f'{y_axis} [1]') + self.plot_widget.ax.grid(True) + + self.plot_widget.canvas.draw() + + +if __name__ == "__main__": + app = QApplication() + setup_logging() + + mypath = ( + r'E:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement') + + model = MeasurementDataModel() + controller = MeasurementDataController(model, mypath) + window = MeasurementDataView(model, controller) + window.show() + + sys.exit(app.exec()) diff --git a/src/FlexSensor/MeasurementEvaluation/view/ParameterAdjustmentView.py b/src/FlexSensor/MeasurementEvaluation/view/ParameterAdjustmentView.py new file mode 100644 index 0000000000000000000000000000000000000000..ef897e8942be25b5fd3f0eabbf37ca931e3071b7 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/view/ParameterAdjustmentView.py @@ -0,0 +1,167 @@ +from PySide6.QtWidgets import QLineEdit, QPushButton +from PySide6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, + QWidget, QLabel, QSlider, QComboBox) +from PySide6.QtCore import Qt, Signal + +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + +import pyqtgraph as pg + +from MeasurementEvaluation.view.widgets.MeasuredDataInformationWidget import MeasuredDataInformationWidget + + +class ParameterAdjustmentWindow(QMainWindow): + + def __init__(self): + super().__init__() + self._current_measurement = None + self._measured_data_list = None + + self.setWindowTitle("Find Peaks Demo") + + layout = QVBoxLayout() + self.measurement_selection = QComboBox() + layout.addWidget(self.measurement_selection) + + self._find_peaks_wdg = ParameterAdjustmentWidget() + self._find_peaks_wdg.apply_fp_param_to_all_clicked.connect(self._on_apply_to_all) + + layout.addWidget(self._find_peaks_wdg) + widget = QWidget() + widget.setLayout(layout) + + self.setCentralWidget(widget) + + @property + def current_measurement(self): + return self._current_measurement + + @current_measurement.setter + def current_measurement(self, value): + self._current_measurement = value + self._find_peaks_wdg.measured_data = self.current_measurement + + @property + def measured_data_list(self): + return self._measured_data_list + + @measured_data_list.setter + def measured_data_list(self, value): + self._measured_data_list = value + self.current_measurement = self._measured_data_list[0] + for i, md in enumerate(self._measured_data_list): + self.measurement_selection.addItem(str(md)) + self.measurement_selection.currentIndexChanged.connect(self._on_measurement_changed) + + def _on_apply_to_all(self, prominence, distance): + for md in self._measured_data_list: + md.measurement_properties.find_peaks.set_properties(prominence,distance,None) + + def _on_measurement_changed(self, index): + self.current_measurement = self._measured_data_list[index] + + +class ParameterAdjustmentWidget(QWidget): + apply_fp_param_to_all_clicked = Signal(float, float) + + def __init__(self): + super().__init__() + self._measured_data: SingleMeasuredData = None + # Create the numpy array + self._init_ui() + + @property + def measured_data(self): + return self._measured_data + + @measured_data.setter + def measured_data(self, value): + self._measured_data = value + self.x = self._measured_data.tables.get('_measured_data')['wavelength'] + self.y = self._measured_data.tables.get('_measured_data')['amplitude'] + self.prom_slider.setValue( + self._measured_data.measurement_properties.find_peaks.prominence * 100) + self.dist_slider.setValue( + int(self._measured_data.measurement_properties.find_peaks.distance/10)) + + self.dist_slider.setRange(1, len(self.x)) + self.update_plot() + + def _init_ui(self): + # Create the plot widget + self.plot_widget = pg.PlotWidget() + + # Create the sliders + self.prom_slider = QSlider(Qt.Horizontal) + self.prom_slider.setRange(0, 100) + # + self.prom_slider.setTickInterval(5) + self.prom_slider.setTickPosition(QSlider.TicksBelow) + self.prom_slider.sliderMoved.connect(self.update_plot) + self.edit_prom = QLineEdit(str(self.prom_slider.value())) + + self.dist_slider = QSlider(Qt.Horizontal) + + # + self.dist_slider.setTickInterval(100) + self.dist_slider.setTickPosition(QSlider.TicksBelow) + self.dist_slider.sliderMoved.connect(self.update_plot) + self.edit_dist = QLineEdit(str(self.dist_slider.value())) + + self.btn_apply_to_all = QPushButton('Apply to all') + self.btn_apply_to_all.clicked.connect( + lambda: self.apply_fp_param_to_all_clicked.emit( + self.prom_slider.value() / 100, + self.dist_slider.value() + ) + ) + # Create the layout + prom_layout = QHBoxLayout() + prom_layout.addWidget(QLabel("Prominence:")) + prom_layout.addWidget(self.prom_slider) + prom_layout.addWidget(self.edit_prom) + + dist_layout = QHBoxLayout() + dist_layout.addWidget(QLabel("Distance:")) + dist_layout.addWidget(self.dist_slider) + dist_layout.addWidget(self.edit_dist) + + layout = QVBoxLayout() + layout.addWidget(self.plot_widget) + self.wdg_measured_information = MeasuredDataInformationWidget(self._measured_data) + layout.addWidget(self.wdg_measured_information) + layout.addLayout(prom_layout) + layout.addLayout(dist_layout) + layout.addWidget(self.btn_apply_to_all) + self.setLayout(layout) + + def update_plot(self): + # Update the prominence and distance values + prom = self.prom_slider.value() / 100 + dist = self.dist_slider.value() + self.wdg_measured_information.measurement_data = self.measured_data + # Update the peaks + self._measured_data.measurement_properties.find_peaks.prominence = prom + self._measured_data.measurement_properties.find_peaks.distance = dist + + peaks_wl = self._measured_data.tables.get('_peaks')['wavelength'] + peaks_amplitude = self._measured_data.tables.get('_peaks')['amplitude'] + self.edit_dist.setText(str(dist)) + self.edit_prom.setText(str(prom)) + + self.plot_widget.clear() + self.plot_widget.plot(self.x.to_list(), self.y.to_list()) + self.plot_widget.plot(peaks_wl.to_list(), peaks_amplitude.to_list(), pen=None, symbol="o") + + +if __name__ == "__main__": + app = QApplication([]) + + mypath = r'E:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement_small' + mm_data = MeasurementDataLoader.from_folder(mypath) + # matfile = mm_data.get_measurement(repetition=1, structure_name='mzi2-2') + matfiles = mm_data.get_measurement_series(structure_name='mzi2-2') + # matfile = SingleMeasuredData.from_mat(Path(f"{mypath}\measurement_die_22_struct_mzi2_2_20220306_1908_rep_2.mat")) + window = ParameterAdjustmentWindow(matfiles) + window.show() + app.exec_() diff --git a/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasuredDataInformationWidget.py b/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasuredDataInformationWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..00e6ff908e2558e810e25810dc2b031a024c2bb1 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasuredDataInformationWidget.py @@ -0,0 +1,63 @@ +import numpy as np +from PySide6.QtWidgets import QWidget, QLabel, QVBoxLayout, QGroupBox, QHBoxLayout, QGridLayout + +from MeasurementData.MeasuredData.MeasuredData import MeasuredData + + +class MeasuredDataInformationWidget(QGroupBox): + def __init__(self, measured_data: MeasuredData): + super().__init__() + + self._wafer_number = "unknown" + self._die_number = "unknown" + self._structure_name = "unknown" + self._repetition = "unknown" + self._timestamp = "unknown" + self._measurement_time = 0 + self._init_ui() + self.measurement_data = measured_data + + def _init_ui(self): + # Create QLabel widgets to display the information + layout = QGridLayout() + self.wafer_label = QLabel() + self.die_label = QLabel() + self.structure_label = QLabel() + layout.addWidget(self.wafer_label, 0, 0) + layout.addWidget(self.die_label, 0, 1) + layout.addWidget(self.structure_label, 0, 2) + + self.repetition_label = QLabel() + self.timestamp_label = QLabel() + self.measurement_time_label = QLabel() + layout.addWidget(self.repetition_label, 1, 0) + layout.addWidget(self.timestamp_label, 1, 1) + layout.addWidget(self.measurement_time_label, 1, 2) + + # Create a vertical layout to arrange the QLabel widgets + + # Set the layout for the group box + self.setLayout(layout) + + @property + def measurement_data(self): + return self._measurement_data + + @measurement_data.setter + def measurement_data(self, value): + if value is not None: + self._measurement_data = value + self._wafer_number = self._measurement_data.wafer_properties.wafer_number + self._die_number = self._measurement_data.wafer_properties.die_number + self._structure_name = self._measurement_data.wafer_properties.structure_name + self._repetition = self._measurement_data.wafer_properties.repetition + self._timestamp = "none" + self._measurement_time = self._measurement_data.ad2_properties.measurement_time + + self.wafer_label.setText(f'Wafer Number: {self._wafer_number}') + self.die_label.setText(f'Die Number: {self._die_number}') + self.structure_label.setText(f'Structure Name: {self._structure_name}') + self.repetition_label.setText(f'Repetition: {self._repetition}') + self.timestamp_label.setText(f'Timestamp: {self._timestamp}') + self.measurement_time_label.setText(f'Measurement Time: {np.round(self._measurement_time, 3)}') + diff --git a/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasurementSelectionWidget.py b/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasurementSelectionWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..ab8b2fa889ed7bb1f34ae5a6048fdd5da72fafd1 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/view/widgets/MeasurementSelectionWidget.py @@ -0,0 +1,132 @@ +from PySide6.QtCore import Signal, Qt, QObject +from PySide6.QtGui import QStandardItem, QStandardItemModel, QAction +from PySide6.QtWidgets import (QTreeView, QVBoxLayout, QWidget, QTableView, QTableWidgetItem, QTableWidget, QMainWindow, + QAbstractItemView, QMenu) + +import MeasurementData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class MultipleMeasurementItem(QStandardItem): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def type(self, *args, **kwargs): + return 'Multi' + + +class SingleMeasurementItem(QStandardItem): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def type(self): + return 'Single' + + +class MeasurementSelectionWidgetSignals(QObject): + open_find_peaks_window = Signal(list) + on_consolidate_measurement_clicked = Signal(list) + on_recalculation_clicked = Signal(list) + on_show_item_click = Signal(SingleMeasuredData) + + +class MeasurementSelectionWidget(QMainWindow): + consolidate_data = Signal(SingleMeasuredData) + + def __init__(self, data): + super().__init__() + self.data: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]] = data + + self.signals = MeasurementSelectionWidgetSignals() + + self.tree_view = QTreeView(self) + self.model = QStandardItemModel() + self.tree_view.setModel(self.model) + + self.setup_model() + self.tree_view.setSelectionMode(QAbstractItemView.SingleSelection) + self.tree_view.setSelectionBehavior(QAbstractItemView.SelectRows) + self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu) + self.tree_view.customContextMenuRequested.connect(self.show_context_menu) + self.setCentralWidget(self.tree_view) + + def setup_model(self): + for k1, v1 in self.data.items(): + parent_item = QStandardItem(k1) + self.model.appendRow(parent_item) + for k2, v2 in v1.items(): + child_item = QStandardItem(str(k2)) + parent_item.appendRow(child_item) + for k3, v3 in v2.items(): + sub_child_item = MultipleMeasurementItem(k3) + child_item.appendRow(sub_child_item) + sub_child_item.setData(list(v2.values())[0]) + for measured_data in v3: + data_item = SingleMeasurementItem(str(measured_data)) + sub_child_item.appendRow(data_item) + data_item.setData(measured_data) + + def multi_selection_menu(self, pos): + menu = QMenu(self) + + action = QAction("Recalculate", self) + action.triggered.connect(self._on_recalculation_clicked) + menu.addAction(action) + + action = QAction("Consolidate Data", self) + action.triggered.connect(self._on_consolidate_data_clicked) + menu.addAction(action) + + action = QAction("Adapt 'FindPeaks' parameters", self) + action.triggered.connect(self._on_adapt_parameters_clicked) + menu.addAction(action) + + + menu.exec_(self.tree_view.viewport().mapToGlobal(pos)) + + def single_selection_menu(self, pos): + menu = QMenu(self) + action = QAction("Add to view", self) + action.triggered.connect(self._on_show_item_clicked) + menu.addAction(action) + menu.exec_(self.tree_view.viewport().mapToGlobal(pos)) + + def show_context_menu(self, pos): + selection = self.tree_view.selectionModel() + index = selection.currentIndex() + if index.isValid(): + item = self.model.itemFromIndex(index) + if item is not None: + if isinstance(item, SingleMeasurementItem): + self.single_selection_menu(pos) + elif isinstance(item, MultipleMeasurementItem): + self.multi_selection_menu(pos) + + def _on_show_item_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_show_item_click.emit(data) + + def _on_recalculation_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_recalculation_clicked.emit(data) + + def _on_adapt_parameters_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.open_find_peaks_window.emit(data) + + def _on_consolidate_data_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_consolidate_measurement_clicked.emit(data) + + def on_clicked_acquire_item_data(self, selection): + index = selection.currentIndex() + if index.isValid(): + item = self.model.itemFromIndex(index) + if item.parent() is not None: + return item.data() + return None \ No newline at end of file diff --git a/src/FlexSensor/MeasurementEvaluation/view/widgets/PlotViewWidget.py b/src/FlexSensor/MeasurementEvaluation/view/widgets/PlotViewWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..b40970ba56970d5f9a1d0f24346fcad1a400fb33 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluation/view/widgets/PlotViewWidget.py @@ -0,0 +1,31 @@ +import numpy as np +import pandas as pd + +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from PySide6.QtWidgets import QWidget, QVBoxLayout, QComboBox + +matplotlib.use('QT5Agg') + +class PlotViewWidget(QWidget): + def __init__(self, parent=None): + super().__init__(parent) + + # Create a Matplotlib figure and axes + self.figure = plt.figure() + self.canvas = FigureCanvas(self.figure) + self.ax = self.figure.add_subplot(111) + + self.plot_selection = "" + + # Add the canvas to this PySide6 widget + layout = QVBoxLayout(self) + layout.addWidget(self.canvas) + + # Set up the initial graph with no data + self.ax.set_xlabel('Wavelength') + self.ax.set_ylabel('Amplitude') + self.ax.set_xlim(0, 1) + self.ax.set_ylim(0, 1) + self.ax.grid(True) diff --git a/src/FlexSensor/MeasurementEvaluationTool/__init__.py b/src/FlexSensor/MeasurementEvaluationTool/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2f81a7ff401d6760f956df11385f3c7032a57c2c --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/__init__.py @@ -0,0 +1,6 @@ +from MeasurementEvaluationTool.view.MeasurementDataView import MeasurementDataView as View +from MeasurementEvaluationTool.model.MeasurementDataModel import MeasurementDataModel as Model +from MeasurementEvaluationTool.controller.MeasurementDataController import MeasurementDataController as Controller +from MeasurementEvaluationTool.controller.MeasurementDatabase import MeasurementDatabase as Database + +from MeasurementData.MeasuredData.SupportClasses.MeasurementDataLoader import MeasurementDataLoader as Loader diff --git a/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDataController.py b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDataController.py new file mode 100644 index 0000000000000000000000000000000000000000..5c0f2523e2240bfa97107c51bb57b68063f769e2 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDataController.py @@ -0,0 +1,70 @@ +import logging + +from MeasurementData.MeasuredData.MeasuredData import MeasuredData +from MeasurementData.MeasuredData.MultiMeasuredData import MultiMeasuredData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementData.MeasuredData.SupportClasses.MeasurementDataLoader import MeasurementDataLoader +from MeasurementEvaluationTool.controller.MeasurementDatabase import MeasurementDatabase +from MeasurementEvaluationTool.model.MeasurementDataModel import MeasurementDataModel + + +class MeasurementDataController: + + def __init__(self, model: MeasurementDataModel, path=None): + self.logger = logging.getLogger("MeasurementDataController") + self._model = model + + self._model.path = path + + + self._model.selected_measurements = [] + + if path is not None: + # Use the loader to load the data + self.db = MeasurementDatabase('data.db') + MeasurementDataLoader.from_folder(self._model.path, self.db) + #self._model.measurement_list = self._md_loader.sorted_files + else: + + self._model.measurement_list = {} + + + + @property + def consolidated_measurements(self): + return self._consolidated_measurements + + @consolidated_measurements.setter + def consolidated_measurements(self, value): + self._consolidated_measurements = value + + @property + def all_measurements(self): + return self._model.measurement_list + + @property + def list_of_measurements(self) -> list[SingleMeasuredData]: + return self._model.selected_measurements + + @property + def selected_measurement(self) -> SingleMeasuredData: + return self._model.display_measurement + + def select_measurement(self, selected_measurement: MeasuredData): + self._model.display_measurement = selected_measurement + + def consolidate_measurements(self, measurement_selection): + self._model.consolidated_measurement = MultiMeasuredData(measurement_selection) + self._model.selected_measurements = measurement_selection + self.select_measurement(self._model.consolidated_measurement) + + def recalculate_measurements(self, measurement_selection): + self.logger.info("Recalculating all measurements") + for md in measurement_selection: + md.calulate_all() + + def load_from_folder(self): + raise NotImplementedError + + def add_measurement(self): + pass \ No newline at end of file diff --git a/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py new file mode 100644 index 0000000000000000000000000000000000000000..b5c0d6e66f07c7f3d6726c96d8125b8f50e8aac3 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py @@ -0,0 +1,95 @@ +import pickle +import sqlite3 + +from PySide6.QtWidgets import QApplication + +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from generics.logger import setup_logging + + +class MeasurementDatabase: + def __init__(self, db_name): + self.db_name = db_name + self.conn = sqlite3.connect(db_name) + self.cursor = self.conn.cursor() + self.create_table() + + def create_table(self): + self.cursor.execute(''' + CREATE TABLE IF NOT EXISTS single_measured_data ( + wafer_number INTEGER, + die_number INTEGER, + structure_name TEXT, + rep INTEGER, + amplitude TEXT, + wavelength TEXT + ) + ''') + self.conn.commit() + + def add_data(self, data: SingleMeasuredData): + query = ''' + INSERT INTO single_measured_data ( + wafer_number, + die_number, + structure_name, + rep, + data_instance + ) VALUES (?, ?, ?, ?, ?) + ''' + values = ( + data.wafer_properties.wafer_number, + data.wafer_properties.die_number, + data.wafer_properties.structure_name, + data.wafer_properties.repetition, + pickle.dumps(data) + ) + self.cursor.execute(query, values) + self.conn.commit() + + def get_data(self, wafer_number, die_number): + query = ''' + SELECT * FROM single_measured_data + WHERE wafer_number = ? AND die_number = ? + ''' + values = (wafer_number, die_number) + self.cursor.execute(query, values) + rows = self.cursor.fetchall() + data_list = [] + for row in rows: + amplitude = list(map(float, row[4].split())) + wavelength = list(map(float, row[5].split())) + data = SingleMeasuredData(row[0], row[1], row[2], row[3], amplitude, wavelength) + data_list.append(data) + return data_list + + def delete_data(self, wafer_number, die_number): + query = ''' + DELETE FROM single_measured_data + WHERE wafer_number = ? AND die_number = ? + ''' + values = (wafer_number, die_number) + self.cursor.execute(query, values) + self.conn.commit() + + def close_connection(self): + self.conn.close() + + +if __name__ == "__main__": + app = QApplication() + setup_logging() + + db = MeasurementDatabase("data.db") + # Load a measurement data + file = (r'F:\measurements_v2_06032022\measurements_v2_06032022\mea_mrr1_1_2022_03_04\T40741W177G0\MaskARY1_Jakob\measurement\measurement_die_22_struct_mrr1_1_20220304_2249_rep_2_v2.mat') + + + data = SingleMeasuredData.from_mat_v2(file) + db.add_data(data) + data_list = db.get_data(1, 2) + print(data_list) + db.delete_data(1, 2) + data_list = db.get_data(1, 2) + print(data_list) + db.close_connection() \ No newline at end of file diff --git a/src/FlexSensor/MeasurementEvaluationTool/controller/data.db b/src/FlexSensor/MeasurementEvaluationTool/controller/data.db new file mode 100644 index 0000000000000000000000000000000000000000..70224a870b586f87c9dde89cee46921be7177ea0 Binary files /dev/null and b/src/FlexSensor/MeasurementEvaluationTool/controller/data.db differ diff --git a/src/FlexSensor/MeasurementEvaluationTool/model/MeasurementDataModel.py b/src/FlexSensor/MeasurementEvaluationTool/model/MeasurementDataModel.py new file mode 100644 index 0000000000000000000000000000000000000000..5e55e292e0343f0eb2bda1a50bca42cff13b8950 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/model/MeasurementDataModel.py @@ -0,0 +1,85 @@ +from pathlib import Path + +from PySide6.QtCore import Signal, QObject + +from MeasurementData.MeasuredData.MultiMeasuredData import MultiMeasuredData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class MeasuredDataSignals(QObject): + path_changed = Signal(Path) + + list_of_measurements_changed = Signal(list) + all_measurements_changed = Signal(dict) + + num_of_measurements = Signal(int) + selected_measurement_changed = Signal(SingleMeasuredData) + consolidated_measurements_changed = Signal(MultiMeasuredData) + + +class MeasurementDataModel: + def __init__(self): + self.signals = MeasuredDataSignals() + + self._path: Path = None + self._measurement_list: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]] = None + + self._consolidated_measurement: MultiMeasuredData = None + self._display_measurement: SingleMeasuredData = None + self._selected_measurements: list[SingleMeasuredData] = [] + + self._num_of_measurements: int = 0 + + @property + def consolidated_measurement(self): + return self._consolidated_measurement + + @consolidated_measurement.setter + def consolidated_measurement(self, value): + self._consolidated_measurement = value + + @property + def path(self): + return self._path + + @path.setter + def path(self, value): + self._path = value + self.signals.path_changed.emit(self.path) + + @property + def measurement_list(self) -> dict[str, dict[int, dict[str, list[SingleMeasuredData]]]]: + return self._measurement_list + + @measurement_list.setter + def measurement_list(self, value: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]]) -> None: + self._measurement_list = value + self.signals.all_measurements_changed.emit(self.measurement_list) + + @property + def selected_measurements(self) -> list[SingleMeasuredData]: + return self._selected_measurements + + @selected_measurements.setter + def selected_measurements(self, value: list[SingleMeasuredData]) -> None: + self._selected_measurements = value + self.num_of_measurements = len(self.selected_measurements) + self.signals.list_of_measurements_changed.emit(self.selected_measurements) + + @property + def num_of_measurements(self) -> int: + return self._num_of_measurements + + @num_of_measurements.setter + def num_of_measurements(self, value: list[SingleMeasuredData]) -> None: + self._num_of_measurements = value + self.signals.num_of_measurements.emit(self.num_of_measurements) + + @property + def display_measurement(self) -> SingleMeasuredData: + return self._display_measurement + + @display_measurement.setter + def display_measurement(self, value: SingleMeasuredData) -> None: + self._display_measurement = value + self.signals.selected_measurement_changed.emit(self.display_measurement) diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py b/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py new file mode 100644 index 0000000000000000000000000000000000000000..167996fda6b44efdc6e6879d1f0f82b028482aaa --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py @@ -0,0 +1,171 @@ +import sys + +import numpy as np +from PySide6.QtWidgets import QApplication, QWidget, QTableView, \ + QComboBox, QPushButton, QGridLayout + +import MeasurementData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementEvaluationTool.controller.MeasurementDataController import MeasurementDataController +from MeasurementEvaluationTool.model.MeasurementDataModel import MeasurementDataModel +from generics.PandasTableModel import PandasTableModel +from MeasurementEvaluationTool.view.ParameterAdjustmentView import ParameterAdjustmentWindow +from MeasurementEvaluationTool.view.widgets.MeasurementSelectionWidget import MeasurementSelectionWidget +from MeasurementEvaluationTool.view.widgets.PlotViewWidget import PlotViewWidget +from generics.logger import setup_logging + + +class MeasurementDataView(QWidget): + def __init__(self, model: MeasurementDataModel, controller: MeasurementDataController): + super().__init__() + self._model = model + self._controller = controller + self.layout = QGridLayout() + + self._model.signals.selected_measurement_changed.connect(self._on_selected_measurement_changed) + + self._init_ui() + + def _init_ui(self): + self.find_peaks_view = ParameterAdjustmentWindow() + + # Add a view for selecting the measurement + self.measurement_selection = MeasurementSelectionWidget(self._controller.all_measurements) + + self.measurement_selection.signals.open_find_peaks_window.connect(self._on_adapt_parameters_clicked) + self.measurement_selection.signals.on_consolidate_measurement_clicked.connect(self._on_consolidate_clicked) + self.measurement_selection.signals.on_recalculation_clicked.connect(self._on_recalculate_clicked) + self.measurement_selection.signals.on_show_item_click.connect(self._on_show_item_clicked) + + # self.measurement_selection.selection.selected_data_changed.connect(self._on_selection_changed) + self.layout.addWidget(self.measurement_selection, 0, 0, 2, 1) + + self.plot_widget = PlotViewWidget() # pg.PlotWidget() + self.layout.addWidget(self.plot_widget, 0, 1, 1, 1) + + # Display the data in an QTableWidget + self.table_view = QTableView() + self.layout.addWidget(self.table_view, 1, 1, 1, 1) + + # Add a dropdown + self.btn_consolidate = QPushButton('Consolidate all') + self.btn_consolidate.clicked.connect(self._on_consolidate_clicked) + self.layout.addWidget(self.btn_consolidate, 2, 0, 1, 1) + + self.dd_select_measurement_table = QComboBox() + self.dd_select_measurement_table.currentIndexChanged.connect(self._on_data_table_changed) + self.layout.addWidget(self.dd_select_measurement_table, 2, 1, 1, 1) + + self.setLayout(self.layout) + # self._controller.select_measurement(0) + + # ================================================================================================================== + # + # ================================================================================================================== + def _on_show_item_clicked(self, measurement_selection: SingleMeasuredData): + measurement_selection.calulate_all() + self._controller.select_measurement(measurement_selection) + + def _on_consolidate_clicked(self, measurement_selection): + self._controller.recalculate_measurements(measurement_selection) + self._controller.consolidate_measurements(measurement_selection) + # self._current_measurement = self._controller.consolidated_measurements + + def _on_recalculate_clicked(self, measurement_selection): + self._controller.recalculate_measurements(measurement_selection) + + def _on_adapt_parameters_clicked(self, measurement_selection): + self.find_peaks_view.measured_data_list = measurement_selection + self.find_peaks_view.show() + + def _on_selection_changed(self, it: int): + # self._controller.select_measurement(it) + self.measurement_selection.set_selected_data(self._controller.selected_measurement) + + def _on_data_table_changed(self, idx): + table_name = self.dd_select_measurement_table.itemData(idx) + print(f"{table_name} - {type(table_name)}") + # print(self._current_measurement.tables.get(table_name)) + table = self._controller.selected_measurement.tables.get(table_name) + # Define plt function here + self.table_view_model = PandasTableModel(table) + self.table_view.setModel(self.table_view_model) + + # This will be removed later and is only for quick and dirty hardcoded plotting + if table_name == "_measured_data": + pass + # self._plot_measurement_table(table_name) + elif table_name == "_wg_param": + self._controller.selected_measurement.tables.get_plot_function('ng (FSR)')(self.plot_widget) + + #self._plot_ng_table(table_name) + + def _on_selected_measurement_changed(self, measurement: MeasurementData): + self._current_measurement = measurement + # Populate the measurement ment selection + self.dd_select_measurement_table.clear() + for table in measurement.tables.to_list(): + # id in table -> table[2] = 'Friendly name', table[1] = 'table name' + self.dd_select_measurement_table.addItem(table[2], table[1]) + #self.dd_select_measurement_table.addItem( measurement.tables.to_list()[2][2], table[2][1]) + + # ================================================================================================================== + # + # ============================================================================================================= + def _plot_measurement_table(self, table_name, x_axis="wavelength", y_axis="detrend"): + self.plot_widget.ax.clear() + data = self._controller.selected_measurement.tables.get(table_name) + self.plot_widget.ax.plot(data[x_axis], data[y_axis], 'b-')[0] + self.plot_widget.ax.set_xlim(np.min(data[x_axis]), np.max(data[x_axis])) + self.plot_widget.ax.set_ylim(np.min(data[y_axis]), np.max(data[y_axis])) + # Scatter plot of the peaks + df_peaks = self._current_measurement.peaks + self.plot_widget.ax.scatter(df_peaks[x_axis], df_peaks[y_axis], marker='x', color='red') + self.plot_widget.ax.set_xlabel('Wavelength [nm]') + self.plot_widget.ax.set_ylabel('Amplitude [1]') + self.plot_widget.ax.set_title('Measured data') + self.plot_widget.ax.grid(True) + self.plot_widget.ax.legend([y_axis, 'Peaks']) + + self.plot_widget.canvas.draw() + + def _plot_ng_table(self, table_name, x_axis="lambda", y_axis="FSR"): + self.plot_widget.ax.clear() + data = self._controller.selected_measurement.tables.get(table_name) + self.plot_widget.ax.plot(data[x_axis], data[y_axis]) + self.plot_widget.ax.set_xlim(np.min(data[x_axis]), np.max(data[x_axis])) + self.plot_widget.ax.set_ylim(np.min(data[y_axis]), np.max(data[y_axis])) + # Scatter plot of the peaks + self.plot_widget.ax.set_xlabel('Wavelength [nm]') + self.plot_widget.ax.set_ylabel(f'{y_axis} [1]') + self.plot_widget.ax.grid(True) + + self.plot_widget.canvas.draw() + +def convert_mat(mypath): + #mypath = (r'F:\measurements_06032022') + md_loader = MeasurementDataLoader.glob_files(mypath, '*.mat') + #measurement_list = md_loader.sorted_files + + for measurement in md_loader: + SingleMeasuredData.convert(measurement) + print('done') + + +if __name__ == "__main__": + app = QApplication() + setup_logging() + + #mypath = (r'F:\measurements_06032022\measurements_06032022\mea_mzi1_2022_03_06\T40741W177G0') + #mypath = (r'F:\measurements_06032022') + #convert_mat(mypath) + #exit() + + mypath = (r'F:\measurements_v2_06032022') + + model = MeasurementDataModel() + controller = MeasurementDataController(model, mypath) + window = MeasurementDataView(model, controller) + window.show() + + sys.exit(app.exec()) diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/ParameterAdjustmentView.py b/src/FlexSensor/MeasurementEvaluationTool/view/ParameterAdjustmentView.py new file mode 100644 index 0000000000000000000000000000000000000000..3848db134407336f072d3b9999cc194dbe8599bc --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/ParameterAdjustmentView.py @@ -0,0 +1,169 @@ +from PySide6.QtWidgets import QLineEdit, QPushButton +from PySide6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, + QWidget, QLabel, QSlider, QComboBox) +from PySide6.QtCore import Qt, Signal + +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + +import pyqtgraph as pg + +from MeasurementEvaluationTool.view.widgets.MeasuredDataInformationWidget import MeasuredDataInformationWidget + + +class ParameterAdjustmentWindow(QMainWindow): + + def __init__(self): + super().__init__() + self._current_measurement = None + self._measured_data_list = None + + self.setWindowTitle("Find Peaks Demo") + + layout = QVBoxLayout() + self.measurement_selection = QComboBox() + layout.addWidget(self.measurement_selection) + + self._find_peaks_wdg = ParameterAdjustmentWidget() + self._find_peaks_wdg.apply_fp_param_to_all_clicked.connect(self._on_apply_to_all) + + layout.addWidget(self._find_peaks_wdg) + widget = QWidget() + widget.setLayout(layout) + + self.setCentralWidget(widget) + + @property + def current_measurement(self): + return self._current_measurement + + @current_measurement.setter + def current_measurement(self, value): + self._current_measurement = value + self._find_peaks_wdg.measured_data = self.current_measurement + + @property + def measured_data_list(self): + return self._measured_data_list + + @measured_data_list.setter + def measured_data_list(self, value): + self._measured_data_list = value + self.current_measurement = self._measured_data_list[0] + for i, md in enumerate(self._measured_data_list): + self.measurement_selection.addItem(str(md)) + self.measurement_selection.currentIndexChanged.connect(self._on_measurement_changed) + + def _on_apply_to_all(self, prominence, distance): + for md in self._measured_data_list: + md.measurement_properties.find_peaks.set_properties(prominence,distance,None) + + def _on_measurement_changed(self, index): + self.current_measurement = self._measured_data_list[index] + + +class ParameterAdjustmentWidget(QWidget): + apply_fp_param_to_all_clicked = Signal(float, float) + + def __init__(self): + super().__init__() + self._measured_data: SingleMeasuredData = None + # Create the numpy array + self._init_ui() + + @property + def measured_data(self): + return self._measured_data + + @measured_data.setter + def measured_data(self, value): + self._measured_data = value + self.x = self._measured_data.tables.get('_measured_data')['wavelength'] + self.y = self._measured_data.tables.get('_measured_data')['amplitude'] + self.prom_slider.setValue( + self._measured_data.measurement_properties.find_peaks.prominence * 100) + self.dist_slider.setValue( + int(self._measured_data.measurement_properties.find_peaks.distance/10)) + + self.dist_slider.setRange(1, len(self.x)) + self.update_plot() + + def _init_ui(self): + # Create the plot widget + self.plot_widget = pg.PlotWidget() + + # Create the sliders + self.prom_slider = QSlider(Qt.Horizontal) + self.prom_slider.setRange(0, 100) + # + self.prom_slider.setTickInterval(5) + self.prom_slider.setTickPosition(QSlider.TicksBelow) + self.prom_slider.sliderMoved.connect(self.update_plot) + self.edit_prom = QLineEdit(str(self.prom_slider.value())) + + self.dist_slider = QSlider(Qt.Horizontal) + + # + self.dist_slider.setTickInterval(100) + self.dist_slider.setTickPosition(QSlider.TicksBelow) + self.dist_slider.sliderMoved.connect(self.update_plot) + self.edit_dist = QLineEdit(str(self.dist_slider.value())) + + self.btn_apply_to_all = QPushButton('Apply to all') + self.btn_apply_to_all.clicked.connect( + lambda: self.apply_fp_param_to_all_clicked.emit( + self.prom_slider.value() / 100, + self.dist_slider.value() + ) + ) + # Create the layout + prom_layout = QHBoxLayout() + prom_layout.addWidget(QLabel("Prominence:")) + prom_layout.addWidget(self.prom_slider) + prom_layout.addWidget(self.edit_prom) + + dist_layout = QHBoxLayout() + dist_layout.addWidget(QLabel("Distance:")) + dist_layout.addWidget(self.dist_slider) + dist_layout.addWidget(self.edit_dist) + + layout = QVBoxLayout() + layout.addWidget(self.plot_widget) + self.wdg_measured_information = MeasuredDataInformationWidget(self._measured_data) + layout.addWidget(self.wdg_measured_information) + layout.addLayout(prom_layout) + layout.addLayout(dist_layout) + layout.addWidget(self.btn_apply_to_all) + self.setLayout(layout) + + def update_plot(self): + # Update the prominence and distance values + prom = self.prom_slider.value() / 100 + dist = self.dist_slider.value() + self.wdg_measured_information.measurement_data = self.measured_data + # Update the peaks + self._measured_data.measurement_properties.find_peaks.prominence = prom + self._measured_data.measurement_properties.find_peaks.distance = dist + + peaks_wl = self._measured_data.tables.get('_peaks')['wavelength'].compute() + peaks_amplitude = self._measured_data.tables.get('_peaks')['amplitude'].compute() + self.edit_dist.setText(str(dist)) + self.edit_prom.setText(str(prom)) + + self.plot_widget.clear() + x = self.x.compute() + y = self.y.compute() + self.plot_widget.plot(x.to_list(), y.to_list()) + self.plot_widget.plot(peaks_wl.to_list(), peaks_amplitude.to_list(), pen=None, symbol="o") + + +if __name__ == "__main__": + app = QApplication([]) + + mypath = r'E:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement_small' + mm_data = MeasurementDataLoader.from_folder(mypath) + # matfile = mm_data.get_measurement(repetition=1, structure_name='mzi2-2') + matfiles = mm_data.get_measurement_series(structure_name='mzi2-2') + # matfile = SingleMeasuredData.from_mat(Path(f"{mypath}\measurement_die_22_struct_mzi2_2_20220306_1908_rep_2.mat")) + window = ParameterAdjustmentWindow(matfiles) + window.show() + app.exec_() diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasuredDataInformationWidget.py b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasuredDataInformationWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..00e6ff908e2558e810e25810dc2b031a024c2bb1 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasuredDataInformationWidget.py @@ -0,0 +1,63 @@ +import numpy as np +from PySide6.QtWidgets import QWidget, QLabel, QVBoxLayout, QGroupBox, QHBoxLayout, QGridLayout + +from MeasurementData.MeasuredData.MeasuredData import MeasuredData + + +class MeasuredDataInformationWidget(QGroupBox): + def __init__(self, measured_data: MeasuredData): + super().__init__() + + self._wafer_number = "unknown" + self._die_number = "unknown" + self._structure_name = "unknown" + self._repetition = "unknown" + self._timestamp = "unknown" + self._measurement_time = 0 + self._init_ui() + self.measurement_data = measured_data + + def _init_ui(self): + # Create QLabel widgets to display the information + layout = QGridLayout() + self.wafer_label = QLabel() + self.die_label = QLabel() + self.structure_label = QLabel() + layout.addWidget(self.wafer_label, 0, 0) + layout.addWidget(self.die_label, 0, 1) + layout.addWidget(self.structure_label, 0, 2) + + self.repetition_label = QLabel() + self.timestamp_label = QLabel() + self.measurement_time_label = QLabel() + layout.addWidget(self.repetition_label, 1, 0) + layout.addWidget(self.timestamp_label, 1, 1) + layout.addWidget(self.measurement_time_label, 1, 2) + + # Create a vertical layout to arrange the QLabel widgets + + # Set the layout for the group box + self.setLayout(layout) + + @property + def measurement_data(self): + return self._measurement_data + + @measurement_data.setter + def measurement_data(self, value): + if value is not None: + self._measurement_data = value + self._wafer_number = self._measurement_data.wafer_properties.wafer_number + self._die_number = self._measurement_data.wafer_properties.die_number + self._structure_name = self._measurement_data.wafer_properties.structure_name + self._repetition = self._measurement_data.wafer_properties.repetition + self._timestamp = "none" + self._measurement_time = self._measurement_data.ad2_properties.measurement_time + + self.wafer_label.setText(f'Wafer Number: {self._wafer_number}') + self.die_label.setText(f'Die Number: {self._die_number}') + self.structure_label.setText(f'Structure Name: {self._structure_name}') + self.repetition_label.setText(f'Repetition: {self._repetition}') + self.timestamp_label.setText(f'Timestamp: {self._timestamp}') + self.measurement_time_label.setText(f'Measurement Time: {np.round(self._measurement_time, 3)}') + diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasurementSelectionWidget.py b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasurementSelectionWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..ab8b2fa889ed7bb1f34ae5a6048fdd5da72fafd1 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MeasurementSelectionWidget.py @@ -0,0 +1,132 @@ +from PySide6.QtCore import Signal, Qt, QObject +from PySide6.QtGui import QStandardItem, QStandardItemModel, QAction +from PySide6.QtWidgets import (QTreeView, QVBoxLayout, QWidget, QTableView, QTableWidgetItem, QTableWidget, QMainWindow, + QAbstractItemView, QMenu) + +import MeasurementData +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class MultipleMeasurementItem(QStandardItem): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def type(self, *args, **kwargs): + return 'Multi' + + +class SingleMeasurementItem(QStandardItem): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def type(self): + return 'Single' + + +class MeasurementSelectionWidgetSignals(QObject): + open_find_peaks_window = Signal(list) + on_consolidate_measurement_clicked = Signal(list) + on_recalculation_clicked = Signal(list) + on_show_item_click = Signal(SingleMeasuredData) + + +class MeasurementSelectionWidget(QMainWindow): + consolidate_data = Signal(SingleMeasuredData) + + def __init__(self, data): + super().__init__() + self.data: dict[str, dict[int, dict[str, list[SingleMeasuredData]]]] = data + + self.signals = MeasurementSelectionWidgetSignals() + + self.tree_view = QTreeView(self) + self.model = QStandardItemModel() + self.tree_view.setModel(self.model) + + self.setup_model() + self.tree_view.setSelectionMode(QAbstractItemView.SingleSelection) + self.tree_view.setSelectionBehavior(QAbstractItemView.SelectRows) + self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu) + self.tree_view.customContextMenuRequested.connect(self.show_context_menu) + self.setCentralWidget(self.tree_view) + + def setup_model(self): + for k1, v1 in self.data.items(): + parent_item = QStandardItem(k1) + self.model.appendRow(parent_item) + for k2, v2 in v1.items(): + child_item = QStandardItem(str(k2)) + parent_item.appendRow(child_item) + for k3, v3 in v2.items(): + sub_child_item = MultipleMeasurementItem(k3) + child_item.appendRow(sub_child_item) + sub_child_item.setData(list(v2.values())[0]) + for measured_data in v3: + data_item = SingleMeasurementItem(str(measured_data)) + sub_child_item.appendRow(data_item) + data_item.setData(measured_data) + + def multi_selection_menu(self, pos): + menu = QMenu(self) + + action = QAction("Recalculate", self) + action.triggered.connect(self._on_recalculation_clicked) + menu.addAction(action) + + action = QAction("Consolidate Data", self) + action.triggered.connect(self._on_consolidate_data_clicked) + menu.addAction(action) + + action = QAction("Adapt 'FindPeaks' parameters", self) + action.triggered.connect(self._on_adapt_parameters_clicked) + menu.addAction(action) + + + menu.exec_(self.tree_view.viewport().mapToGlobal(pos)) + + def single_selection_menu(self, pos): + menu = QMenu(self) + action = QAction("Add to view", self) + action.triggered.connect(self._on_show_item_clicked) + menu.addAction(action) + menu.exec_(self.tree_view.viewport().mapToGlobal(pos)) + + def show_context_menu(self, pos): + selection = self.tree_view.selectionModel() + index = selection.currentIndex() + if index.isValid(): + item = self.model.itemFromIndex(index) + if item is not None: + if isinstance(item, SingleMeasurementItem): + self.single_selection_menu(pos) + elif isinstance(item, MultipleMeasurementItem): + self.multi_selection_menu(pos) + + def _on_show_item_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_show_item_click.emit(data) + + def _on_recalculation_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_recalculation_clicked.emit(data) + + def _on_adapt_parameters_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.open_find_peaks_window.emit(data) + + def _on_consolidate_data_clicked(self): + selection = self.tree_view.selectionModel() + data = self.on_clicked_acquire_item_data(selection) + self.signals.on_consolidate_measurement_clicked.emit(data) + + def on_clicked_acquire_item_data(self, selection): + index = selection.currentIndex() + if index.isValid(): + item = self.model.itemFromIndex(index) + if item.parent() is not None: + return item.data() + return None \ No newline at end of file diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py new file mode 100644 index 0000000000000000000000000000000000000000..7ff8638994e2b9b0ee4ac9880aed97c31014e2be --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py @@ -0,0 +1,50 @@ +from PySide6.QtGui import QIcon, QAction +from PySide6.QtWidgets import QGroupBox, QWidget + +from MainWindow.controller.MainThreadController import MainThreadController +from MainWindow.view import MainThreadView +from pathes import image_root + + +class MenuBarDefinition(QWidget): + + def __init__(self, view: MainThreadView): + super().__init__() + self._view = view + + # self.menubar = self.menuBar() + self.init_menu_file() + self.init_menu_edit() + self.init_menu_run() + # help_menu = menubar.addMenu("Help") + # help_menu.addAction("About", self.on_about_clicked) + + + + def init_menu_file(self): + exit_action = QAction(QIcon('exit.png'), '&Exit ', self) + exit_action.setShortcut('Ctrl+Q') + exit_action.setStatusTip('Exit application') + exit_action.triggered.connect(lambda: exit()) + self._view._ui.menu_file.addAction(exit_action) + + def init_menu_edit(self): + pass + + def init_menu_run(self): + # self.menu_run = self.menubar.addMenu("Run") + self.open_step_trough = QAction('Open &Step Through Window', self) + self.open_step_trough.setShortcut('Ctrl+W') + self.open_step_trough.setStatusTip('Open Step Through Window') + self.open_step_trough.triggered.connect(self._view._on_open_step_through) + self._view._ui.menu_run.addAction(self.open_step_trough) + + self.open_train_home_wizard = QAction('&Initial Setup Wizard', self) + self.open_train_home_wizard.setShortcut('Ctrl+I') + self.open_train_home_wizard.setStatusTip('Open Initial Setup Wizard') + self.open_train_home_wizard.setIcon(QIcon(f"{image_root}/icons/setup_wizard.png")) + self.open_train_home_wizard.triggered.connect(self._view._on_open_initial_setup_wizard) + self._view._ui.menu_run.addAction(self.open_train_home_wizard) + + + diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/PlotViewWidget.py b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/PlotViewWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..b40970ba56970d5f9a1d0f24346fcad1a400fb33 --- /dev/null +++ b/src/FlexSensor/MeasurementEvaluationTool/view/widgets/PlotViewWidget.py @@ -0,0 +1,31 @@ +import numpy as np +import pandas as pd + +import matplotlib +import matplotlib.pyplot as plt +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +from PySide6.QtWidgets import QWidget, QVBoxLayout, QComboBox + +matplotlib.use('QT5Agg') + +class PlotViewWidget(QWidget): + def __init__(self, parent=None): + super().__init__(parent) + + # Create a Matplotlib figure and axes + self.figure = plt.figure() + self.canvas = FigureCanvas(self.figure) + self.ax = self.figure.add_subplot(111) + + self.plot_selection = "" + + # Add the canvas to this PySide6 widget + layout = QVBoxLayout(self) + layout.addWidget(self.canvas) + + # Set up the initial graph with no data + self.ax.set_xlabel('Wavelength') + self.ax.set_ylabel('Amplitude') + self.ax.set_xlim(0, 1) + self.ax.set_ylim(0, 1) + self.ax.grid(True) diff --git a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py new file mode 100644 index 0000000000000000000000000000000000000000..5b7bba703a6d25f20070acad74b4ac0e9bf3ca1b --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py @@ -0,0 +1,108 @@ +import logging + +from PySide6.QtCore import QObject, QThread, Slot + +from AD2CaptDevice.controller.AD2CaptDeviceController import AD2CaptDeviceController +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from Laser.LaserControl.controller import BaseLaserController +from Prober.controller.ProberController import ProberController +from MeasurementRoutines.WorkerSignals import WorkerSignals + + +class BaseMeasurementRoutine(QObject): + + def __init__(self, laser: BaseLaserController, ad2device: AD2CaptDeviceController, prober: ProberController, + vaut_config: VAutomatorConfig): + super().__init__() + self.logger = logging.getLogger("Base Measurement Routine") + self.vaut_config = vaut_config + + self.ad2device: AD2CaptDeviceController = ad2device + self.laser: BaseLaserController = laser + self.prober: ProberController = prober + self.logger.debug(f"{self.prober.report_kernel_version()}") + print(self.prober) + + self.prober_thread = QThread() + + self.signals = WorkerSignals() + + @Slot() + def run(self): + raise NotImplementedError() + + def _routine(self): + raise NotImplementedError() + + def _init_prober_signals(self): + ''' + Connect the signals and disable that a new log is printed (in order to prevent double occuring lines + ''' + self.prober.signals.log_debug.connect(lambda title, desc, details: self._write_debug(desc, print_log=False)) + self.prober.signals.log_info.connect(lambda title, desc, details: self._write_info(desc, print_log=False)) + self.prober.signals.log_warning.connect(lambda title, desc, details: self._write_warning(desc, print_log=False)) + self.prober.signals.log_error.connect( + lambda title, desc, details: self._write_error(title, desc, details, print_log=False)) + + def _write_debug(self, *msg, print_log=True, **kwargs): + if print_log: + self.logger.debug(*msg) + self.signals.write_log.emit("debug", *msg) + + def _write_info(self, *msg, print_log=True, **kwargs): + if print_log: + self.logger.info(*msg) + self.signals.write_log.emit("info", *msg) + + def _write_warning(self, title, msg, desc, err=None, tb=None, print_log=True, *args, **kwargs): + if err is None and tb is None: + logmsg_short = f"{desc}." + logmsg_full = f"{logmsg_short}" + else: + logmsg_short = f"{desc}: {err}." + logmsg_traceback = f"=== TRACEBACK ===\n{tb.format_exc()}" + logmsg_full = f"{logmsg_short}\n\n{logmsg_traceback}" + if print_log: + self.logger.warning(logmsg_full) + self.signals.warning.emit((title, logmsg_short, logmsg_full)) + + def _write_error(self, title, desc, e=None, tb=None, print_log=True, *args, **kwargs): + if e is None and tb is None: + logmsg_short = f"{desc}." + logmsg_full = f"{logmsg_short}" + else: + logmsg_short = f"{desc}: {e}." + logmsg_traceback = f"=== TRACEBACK ===\n{tb.format_exc()}" + logmsg_full = f"{logmsg_short}\n\n{logmsg_traceback}" + if print_log: + self.logger.error(logmsg_full) + self.signals.error.emit((title, logmsg_short, logmsg_full)) + + def write_log(self, msg_type, *args, **kwargs): + if msg_type == "debug": + self.logger.debug(*args) + elif msg_type == "warning": + self.logger.warning(*args) + elif msg_type == "error": + self.logger.error(*args) + elif msg_type == "fatal": + self.logger.fatal(*args) + else: + self.logger.info(*args) + + self.signals.write_log.emit(msg_type, *args) + + def register_step(*args, **kwargs): + step_name = "Step" + if 'step_name' in kwargs: + step_name = kwargs['step_name'] + + def inner(func): + ''' + do operations with func + ''' + print(f"Registering step for function {func} - {step_name}") + return func + + return inner # this is the fun_obj mentioned in the above content + diff --git a/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py new file mode 100644 index 0000000000000000000000000000000000000000..ea4d3d963f407a4cfdbccc1a2bc5004e284a6ac2 --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py @@ -0,0 +1,389 @@ +import logging +import time +import traceback +from datetime import datetime + +import pandas as pd +from PySide6.QtCore import Slot + +import mcpy +from AD2CaptDevice.controller.AD2CaptDeviceController import AD2CaptDeviceController +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from ConfigHandler.controller.VFSObject import VFSObject +from ConfigHandler.controller.VASInputFileParser import VASInputFileParser, Structure +from Laser.LaserControl.controller import BaseLaserController +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from MeasurementData.Properties.MeasurementProperties import MPropertiesFindPeaks, \ + MeasurementProperties, WaveguidePropertiesMZI +from MeasurementRoutines.BasemeasurementRoutine import BaseMeasurementRoutine +from Prober.controller.ProberController import ProberController +from MeasurementData.Properties.WaferProperties import WaferProperties +from constants.FlexsensorConstants import Probe +from generics.generics import pch + + +class MeasurementRoutine(BaseMeasurementRoutine): + + def __init__(self, laser: BaseLaserController, ad2device: AD2CaptDeviceController, prober: ProberController, + vaut_config: VAutomatorConfig): + super().__init__(laser, ad2device, prober, vaut_config) + + self.logger = logging.getLogger("Measurement Routine") + # The signals for connecting to the UI + + self.parsed_file = VASInputFileParser() + + self.grouped_structures, self.bookmarks = self.parsed_file.read_file( + input_file=self.vaut_config.wafer_config.get_structure_file().absolute + ) + self.number_of_structures = self.parsed_file.num_of_structs + self.number_of_runs = self.parsed_file.num_of_runs + + # We need to connect two signals: + # Connect the signal if a wavelength sweep starts (from the laser) to a signal that tells our oscilloscope + # to start capturing! + # self.laser.signals.wavelength_sweep_running.connect(self.ad2device.on_ad2_set_acquisition_changed) + + # Some intermediate Data + self.columns = ["wafer_nr", "die_nr", "chuck_col", "chuck_row", "timestamp", "structure_name", + "reps", "structure_x_in", "structure_y_in", "structure_x_out", + "structure_y_out", "measure_time", "timestamps", "captured_values"] + self.siph_data = pd.DataFrame(columns=self.columns) + self.siph_data['captured_values'] = self.siph_data['captured_values'].astype(object) + + self.initialization() + + def initialization(self): + self.probe_height = 80 + + self.logger.info( + f"Init Prober Class. Number of runs per die: {self.number_of_runs}, dies {self.vaut_config.wafer_config.dies}\n" + f"Measurement CVS File = {self.vaut_config.wafer_config.measurement_output}\n" + f"Measurement Mat File = {self.vaut_config.wafer_config.measurement_mat_file}") + + @Slot() + def run(self): + self.logger.info(f"<< Input file {self.vaut_config.wafer_config.get_structure_file().relative}") + self.logger.info(f">> Working directory {self.vaut_config.get_output_directory().relative}") + self.logger.info(f">> Log File {self.vaut_config.wafer_config.get_log_file().relative}") + self.logger.info(f">> Measurments CVS File {self.vaut_config.wafer_config.get_measurement_output().relative}") + self.logger.info(f">> Measurments Mat File {self.vaut_config.wafer_config.get_measurement_mat_file().relative}") + self.logger.info(f">> KLayout Bookmark file {self.vaut_config.wafer_config.get_bookmark_file().relative}") + self.logger.info(f">> Scope Image File {self.vaut_config.wafer_config.get_scope_image_file().relative}") + + # as long as the connection was successful, we can send some commands. + # if it was not successful, an exception is thrown. + + self.logger.warning("*** Check safe height. Contact height must be set.***") + # SCI commands return a namedtuple if multiple values are returned. + # ReportKernelVersion returns a version number and a description. + # You can acess the return values by name or by indexing the tuple. + self.logger.info("Everything is set up, starting measuring.") + + self._routine() + + def _routine(self): + try: + # Initialize the devices + self._init_prober_signals() + # self._init_laser_signals() + # self._init_ad2device_signals() + + self._write_info( + f"{pch('=', 50)} Starting measurement {pch('=', 50)}") + + # === Check contact height + print(self.prober) + contact, overtravel, align_dist, sep_dis, search_gap = self.prober.check_contact_height_set() + + for die_idx, die_no in enumerate(self.vaut_config.wafer_config.dies): + # Move to die + self.write_log("info", f"Processing die {die_no} (#{die_idx})") + self.die_no, self.chuck_col, self.chuck_row = self.prober.move_to_die(die_no) + + if self.die_no is not None and self.chuck_col is not None and self.chuck_row is not None: + self.write_log("info", f"Chuck moved to home position. Die {self.die_no} " + f"(Col: {self.chuck_col}, Row: {self.chuck_row})") + else: + # STOP SiPh-Tools + self.write_log("fatal", "Chuck could not be moved to home position. Script will be stopped!") + raise Exception("Chuck could not be moved to home position. Script will be stopped!") + + # Go to the home position + self.write_log("info", "Move chuck to home position (0, 0)") + self.prober.move_chuck(0, 0) + + # Iterate through the list of structures + for idx_groups, self.groups in enumerate(self.grouped_structures): + + structures: dict = self.grouped_structures[self.groups] + idx_struct = 0 + self.write_log("info", f"New structure group ({idx_groups}): " + f"{self.groups}. {len(structures)} structures in group.") + + while idx_struct < len(structures): + structure = list(structures.values())[idx_struct] + self._measure_structure(die_no, structure, idx_struct) + idx_struct += 1 + continue + + + except Exception as e: + self._write_error(title="Prober initialization error", desc="Could not connect or initialize prober", + e=e, tb=traceback) + + # ================================================================================================================== + # The individual steps for the Measurement Routine + # If implementing multiple routines, and the steps may occure multiple times, move them to + # the base class instead of reimplementing/copying! + # ================================================================================================================== + def _step_place_input_probe(self, structure: Structure, fmt): + """ + Places the chuck, thus the input probe, such that the probe is on the correct position. + Move the chuck to the given position. Since the input probe stays on the same position, + the probe is therefore on the correct input position. + """ + x, y = (structure.x_in, structure.y_in) + self.write_log("info", f"{fmt} Move input probe/chuck to X: {x}, Y: {y}.") + self.prober.move_chuck(x, y) + chuck_x, chuck_y, chuck_z = self.prober.read_chuck_position(unit="Microns", pos_ref="Home") + self.write_log("info", f"{fmt} Input probe/chuck at position X: {chuck_x}, Y: {chuck_y}, Z: {chuck_z}.") + return chuck_x, chuck_y, chuck_z + + def _step_place_output_probe(self, structure, fmt, safe_dist: float = 50): + x, y = (structure.x_out, structure.y_out) + diff_x, diff_y = (structure.in_out_diff_x, structure.in_out_diff_y) + self.write_log("info", f"{fmt} Move second probe to x: {x}, y: {y}) - Difference x: {diff_x}, y: {diff_y}") + + # TODO: CHeck if the structure require a reposition of the probe + move_probe2 = True + + if self.structure.in_out_diff_x > safe_dist and move_probe2: + self.write_log("debug", + f"{fmt} Optical probes in safe distance {x > safe_dist}. Moving output probe x:{diff_x}, y: {diff_y}.") + self.prober.opt_if.move_optical_probe(Probe.OUTPUT, diff_x, diff_y) + elif self.structure.in_out_diff_x < safe_dist: + raise Exception(f"Optical Probe Home not safe! Difference in x-direction < {safe_dist} um.") + else: + self.write_log("warning", f"Optical Probe not moved. Movement for probe disabled: {move_probe2}") + + def _step_set_probes_to_measurement_height(self, height, fmt): + try: + self.write_log("info", f"{fmt} Setting probe heights to {height} um") + self.prober.opt_if.set_probe_height(Probe.INPUT, height) + self.prober.opt_if.set_probe_height(Probe.OUTPUT, height) + # self.msg_server.sendSciCommand("FindOpticalProbeHeight", + # rparams='0 %s' % self.probe_height) + # self.msg_server.sendSciCommand("FindOpticalProbeHeight", + # rparams='1 %s' % self.probe_height) + except Exception as e: + self.write_log("error", + f"{fmt} Cannot set probe height to {height}. {e}") + self.signals.error.emit(( + type(e), f"Cannot set probe height to {height}. {e}", + traceback.format_exc() + )) + raise e + + def _step_snap_image(self, scope_file: VFSObject, fmt): + # Here we adapt filename of the scope by passing the correct keywords + try: + self.write_log("info", f"{fmt} Saving scope image to {scope_file.relative}") + self.prober.snap_image("eVue2", scope_file.absolute, 2) + except Exception as e: + self.logger.warning(f"{fmt} Cannot save scope image to {scope_file.relative}: {e}\n\n" + f"{traceback.format_exc()}") + + self.signals.warning.emit(type(e), + f"Cannot save scope image to {scope_file.relative}. {e}", + traceback.format_exc()) + + def _step_search_for_light(self, fmt): + # TODO: Handle if we cannot find the light + self.logger.info(f"{fmt} Searching for light.") + self.signals.write_log.emit("info", "Searching for light.") + input_power, output_power = self.prober.opt_if.search_for_light() + if input_power is None or output_power is None: + self.logger.warning(f"{fmt} Cannot find light. Something went wrong.") + self.signals.warning.emit("warning", "Cannot find light. Something went wrong.", "") + raise Exception('Cannot find light.') + else: + self.logger.info(f"{fmt} Light found. Input Power: {input_power} dBm. Output Power: {output_power} dBm") + self.logger.info(f"{fmt} Light found. Input Power: {input_power} dBm. Output Power: {output_power} dBm") + self.signals.write_log.emit("info", + "Light found. Input Power: {input_power} dBm. Output Power: {output_power} dBm") + + def _step_capture_transmission(self, rep, fmt): + self.logger.info(f"{fmt} Setting up AD2. This may take a while, please wait...") + self.signals.write_log.emit("info", "Setting up oscilloscope.") + + #if not self.ad2device.connect_device(0): + # self.logger.error(f"{fmt} Could not setup ad2 device.") + # self.signals.error.emit("error", "Could not setup ad2 device.", "") + # raise Exception("Could not setup ad2 device. Script will be stopped!") + + # ******************* + # Start the measurement + #self.laser.start_wavelength_sweep() + #time.sleep(1) + #while self.ad2device.model.capturing_finished == False: + # print(f"awaiting: {self.ad2device.model.capturing_finished}") + # time.sleep(1) + + #captured_values = self.ad2device.model.recorded_samples # Just starts an endless loop + #print(len(captured_values)) + #measure_time = self.ad2device.model.recording_time + captured_values, measure_time = self.laser.sweep_and_measure() + + self.write_log("info", f"{self.formatter} Finished data acquisition: {len(captured_values)}. Took {round(measure_time, 5)} seconds.") + return measure_time, captured_values + + def _step_create_MeasuredSignal(self, data: pd.DataFrame, data_raw: list, wafer_properties: WaferProperties): + # timestamp, measure_time, time_stamps, amplitude + + try: + cur_measured_signal = SingleMeasuredData( + laser_properties=self.laser.model.laser_properties, + ad2_properties=self.ad2device.model.ad2_properties, + wafer_properties=wafer_properties, + waveguide_properties=WaveguidePropertiesMZI( + length1=mcpy.Rectangular(10e6, 20, unit='nm'), + length2=mcpy.Rectangular(10.38e6, 20, unit='nm'), + width=mcpy.Rectangular(550, 20, unit='nm'), + height=mcpy.Rectangular(625, 2.405, unit='nm')), + measurement_properties=MeasurementProperties( + MPropertiesFindPeaks(0.1, 10000, None) + ), + timestamp=data['timestamp'], + measurement_data=data_raw + ) + + # cur_measured_signal.set_prober_properties( + # self.vaut_config.wafer_nr, + # self.die_no, + # self.chuck_col, + # self.chuck_row + # ) + # cur_measured_signal.set_structure_properties(self.structure) + # cur_measured_signal.set_ad2_properties( + # self.vaut_config.ad2_device_config.get_sample_rate(), + # self.vaut_config.ad2_device_config.get_total_samples()) + # + # cur_measured_signal.set_laser_properties( + # self.vaut_config.laser_config.get_wavelength_range(), + # self.vaut_config.laser_config.get_velocity(), + # self.vaut_config.laser_config.get_acceleration()) + + return cur_measured_signal + + except Exception as e: + self.write_log("error", f"Could not create MeasuredSignal instance from data: {e}") + self.signals.error.emit((type(e), + f"Could not create MeasuredSignal instance from data: {e}", + traceback.format_exc())) + raise e + + # Routine for measuring one structure + def _measure_structure(self, die_no: int, structure: Structure, structure_idx: int): + """Routine for measuring one structure + + """ + self.structure: Structure = structure + self.formatter = f"[Measurement. Die {die_no}]: {self.structure.name} |" + timestamp = datetime.now().strftime('%d/%m/%Y %H:%M:%S.%f') + + if not self.structure.enabled: + self.write_log("info", f"Structure {self.structure.name} is disabled, skipping!") + return + + self.write_log("info", f"{self.formatter} Processing structure {self.structure.name}.") + # Report the current structure information to the frontend + self.signals.report_info.emit({ + "die_no": self.die_no, "chuck_col": self.chuck_col, + "chuck_row": self.chuck_row, "structure": self.structure.name, + "repetition": self.structure.repetitions + }) + self.write_log("info", f"{self.formatter} " + f"die_no: {self.die_no}, chuck_col: {self.chuck_col}, " + f"chuck_row: {self.chuck_row}, structure: {self.structure.name}, " + f"repetition: {self.structure.repetitions}" + ) + + # 1. Move the first probe/chuck + self._step_place_input_probe(self.structure, self.formatter) + + # 2. Move the second probe + self._step_place_output_probe(self.structure, self.formatter) + + # 3. Setting the probe height to 80 um + self._step_set_probes_to_measurement_height(80, self.formatter) + + # 4. Snap an image + # Create the correct file for the scope image + # self.vaut_config.wafer_config.get_scope_image_file().set_obj( + # keywords={"{die}": self.die_no, "{structure}": self.structure.name, "{it}": 1}) + self._step_snap_image(self.vaut_config.wafer_config.get_scope_image_file( + keywords={"{die}": self.die_no, "{structure}": self.structure.name}), self.formatter) + + # Search for the light + self._step_search_for_light(self.formatter) + + amplitude = [] + time_stamps = [] + rep = 1 + + while rep <= self.structure.repetitions: + # ******************* + # Stop the measurement + # For displaying the data in the GUI + measure_time, captured_values = self._step_capture_transmission(rep, self.formatter) + data = [[ + self.vaut_config.wafer_nr, self.die_no, self.chuck_col, + self.chuck_row, timestamp, str(self.structure), rep, + self.structure.x_in, self.structure.y_in, + self.structure.x_out, self.structure.y_out, + measure_time, str(time_stamps), captured_values + ]] + self.siph_data = pd.concat([self.siph_data, pd.DataFrame(data, columns=self.columns)]) + + try: + self.siph_data.to_csv(str(self.vaut_config.wafer_config.get_measurement_output())) + self.siph_data.to_excel( + str(self.vaut_config.wafer_config.get_measurement_output()).replace('csv', 'xlsx')) + except Exception as e: + self._write_error("Write SiPh", f"Could not write sphi data to file " + f"{self.vaut_config.wafer_config.get_measurement_output()}", e, + traceback) + self.signals.error.emit((type(e), + f"Could not write sphi data to file " + f"{self.vaut_config.wafer_config.get_measurement_output()}: {e}", + traceback.format_exc())) + + wafer_properties = WaferProperties( + wafer_number=self.vaut_config.wafer_nr, + structure_name=self.structure.name, + die_nr=self.die_no, + chuck_col=self.chuck_col, + chuck_row=self.chuck_row, + structure_in=(self.structure.x_in, self.structure.y_in), + structure_out=(self.structure.x_out, self.structure.y_out), + repetitions=rep) + + cur_measured_signal = self._step_create_MeasuredSignal( + self.siph_data, + captured_values, + wafer_properties) + + cur_measured_signal._save_mat_file( + filename=self.vaut_config.wafer_config.get_measurement_mat_file(keywords={"{die}": self.die_no, + "{structure}": self.structure.name, + "{it}": f"rep_{rep + 1}"}).absolute + ) + + + rep += 1 + self.logger.info(f"Repetition {rep}/{self.structure.repetitions} measured successfully!") + self.signals.routine_iteration_finished.emit(cur_measured_signal, rep) + # Report the progress to the frontend + self.write_log("info", "[OK] Continuing with next structure.") + # idx_struct = idx_struct + 1 diff --git a/src/FlexSensor/MeasurementRoutines/WorkerSignals.py b/src/FlexSensor/MeasurementRoutines/WorkerSignals.py new file mode 100644 index 0000000000000000000000000000000000000000..50eda1e84b4859872c1b22f55582d5a0642f22b6 --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/WorkerSignals.py @@ -0,0 +1,23 @@ +from PySide6.QtCore import QObject, Signal + +from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData + + +class WorkerSignals(QObject): + + finished = Signal() + + error = Signal(tuple) + + warning = Signal(tuple) + + result = Signal(object) + + progress = Signal(float) + + # Reports the measured data and the iteration number + routine_iteration_finished = Signal(SingleMeasuredData, int) + + write_log = Signal(str, str) + + report_info = Signal(dict) diff --git a/src/FlexSensor/MeasurementRoutines/__init__.py b/src/FlexSensor/MeasurementRoutines/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/MeasurementRoutines/ressources/MeasurementControlFlow.ui b/src/FlexSensor/MeasurementRoutines/ressources/MeasurementControlFlow.ui new file mode 100644 index 0000000000000000000000000000000000000000..8cae92507faa3ed421f4ea9019cfe5552ca16be0 --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/ressources/MeasurementControlFlow.ui @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MeasurementControlFlow</class> + <widget class="QWidget" name="MeasurementControlFlow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QListView" name="listView_control_flow"/> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/FlexSensor/MeasurementRoutines/ressources/convert.sh b/src/FlexSensor/MeasurementRoutines/ressources/convert.sh new file mode 100644 index 0000000000000000000000000000000000000000..c317f21e29daef33cbd1dba83f08f1e10c242004 --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/ressources/convert.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Convert .ui files to .py files +for ui in *.ui; do + pyside6-uic $ui > ../view/Ui_${ui%.*}.py +done + pyside6-rcc ../../resources.qrc -o ../../resources_rc.py diff --git a/src/FlexSensor/MeasurementRoutines/view/MeasurementControlFlow.py b/src/FlexSensor/MeasurementRoutines/view/MeasurementControlFlow.py new file mode 100644 index 0000000000000000000000000000000000000000..7ec6b4ba0aae77f186b423b109b20db74583d0fa --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/view/MeasurementControlFlow.py @@ -0,0 +1,9 @@ +from MeasurementRoutines.view.Ui_MeasurementControlFlow import Ui_MeasurementControlFlow + + +class MeasurementControlFlow(): + def __init__(self, measurementRoutine: BaseMeasurementRoutine): + # Init the UI file + self._ui = Ui_MeasurementControlFlow() + self._ui.setupUi(self) + diff --git a/src/FlexSensor/MeasurementRoutines/view/Ui_MeasurementControlFlow.py b/src/FlexSensor/MeasurementRoutines/view/Ui_MeasurementControlFlow.py new file mode 100644 index 0000000000000000000000000000000000000000..eb1b0e958f3426e2f913b70b87cb3e284891723b --- /dev/null +++ b/src/FlexSensor/MeasurementRoutines/view/Ui_MeasurementControlFlow.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'MeasurementControlFlow.ui' +## +## Created by: Qt User Interface Compiler version 6.5.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QGridLayout, QListView, QSizePolicy, + QWidget) + +class Ui_MeasurementControlFlow(object): + def setupUi(self, MeasurementControlFlow): + if not MeasurementControlFlow.objectName(): + MeasurementControlFlow.setObjectName(u"MeasurementControlFlow") + MeasurementControlFlow.resize(400, 300) + self.gridLayout_2 = QGridLayout(MeasurementControlFlow) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.listView_control_flow = QListView(MeasurementControlFlow) + self.listView_control_flow.setObjectName(u"listView_control_flow") + + self.gridLayout.addWidget(self.listView_control_flow, 0, 0, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + + self.retranslateUi(MeasurementControlFlow) + + QMetaObject.connectSlotsByName(MeasurementControlFlow) + # setupUi + + def retranslateUi(self, MeasurementControlFlow): + MeasurementControlFlow.setWindowTitle(QCoreApplication.translate("MeasurementControlFlow", u"Form", None)) + # retranslateUi + diff --git a/src/FlexSensor/Prober/__init__.py b/src/FlexSensor/Prober/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a9885c767677d0fc7299511b1dfe724dd43e186d --- /dev/null +++ b/src/FlexSensor/Prober/__init__.py @@ -0,0 +1,20 @@ +import os + +if os.environ.get('VELOX_SIM') is not None: + print("Velox Simulator") + from Prober.velox_api.simulator import VeloxSimulator as velox_api + from Prober.velox_api.simulator.VeloxSimulator import (MessageServerInterface, SetChuckHome, SetMapHome, + ReadChuckPosition, ReadChuckHeights, MoveChuck, + SnapImage, GetDieDataAsColRow, StepToDie, ReportKernelVersion) +else: + import Prober.velox_api.velox as velox_api + from Prober.velox_api.velox import (MessageServerInterface, SetChuckHome, SetMapHome, + ReadChuckPosition, ReadChuckHeights, MoveChuck, + SnapImage, GetDieDataAsColRow, StepToDie, ReportKernelVersion) + +from Prober.model.ProberModel import ProberModel as Model +from Prober.view.ProberControlWindow import ProberControlWindow as ControlWindow +from Prober.model.ProberModel import ProberSignals as Signals +from Prober.controller.ProberController import ProberController as Controller +from Prober.controller.ProberController import Probe as Probe +from Prober.controller.OpticalProbesPosition import OpticalProbesPosition as ProbePosition diff --git a/src/FlexSensor/Prober/controller/MapFileParser.py b/src/FlexSensor/Prober/controller/MapFileParser.py new file mode 100644 index 0000000000000000000000000000000000000000..570944889faa3228452576403bfa3f93a8857ddf --- /dev/null +++ b/src/FlexSensor/Prober/controller/MapFileParser.py @@ -0,0 +1,33 @@ +from pathlib import Path + + +class MapFileParser: + + def __init__(self, path: str): + print(path) + self._map_path = Path(path) + with open(self._map_path, 'r') as file: + self.result = self.parse_content(file.read()) + + def parse_content(self, content): + result = {} + current_section = None + + lines = content.split("\n") + for line in lines: + line = line.strip() + if line.startswith("[") and line.endswith("]"): + current_section = line[1:-1] + elif "=" in line and current_section is not None: + key, value = line.split("=", 1) + result.setdefault(current_section, {}) + result[current_section][key] = value + + return result + + +if __name__ == "__main__": + parsed_map = MapFileParser("../Wafermapary1_48dies.map") + print(parsed_map.result["Header"]["Description"]) # Output: Wafer Map File + print(parsed_map.result["Wafer"]["Diameter"]) # Output: 200 + print(parsed_map.result["Bin"]["0"]) # Output: 1,a0,00C000,1,0,0,0,0 \ No newline at end of file diff --git a/src/FlexSensor/Prober/controller/OpticalInterface.py b/src/FlexSensor/Prober/controller/OpticalInterface.py new file mode 100644 index 0000000000000000000000000000000000000000..4d1cb934953988128ad9365d85a7de13305083b2 --- /dev/null +++ b/src/FlexSensor/Prober/controller/OpticalInterface.py @@ -0,0 +1,277 @@ +import logging + +from Prober.model.OpticalInterfaceModel import OpticalInterfaceModel +from Prober.model.OpticalInterfaceStoredData import OpticalInterfaceStoredData +from constants.FlexsensorConstants import Probe +from generics.generics import pch + + + + + + + + + + + + + +class OpticalInterface(object): + + def __init__(self, prober_signals, msg_server): + self.stored = OpticalInterfaceStoredData() + self.signals = prober_signals + self.msg_server = msg_server + self.logger = logging.getLogger("Optical Interface") + self.logger.info("Optical Interface initialized") + + # ================================================================================================================== + # pythonized api calls + # ================================================================================================================== + + def enable_flight_height_control(self, enable_in=True, enable_out=True): + # Disable Flight Height Control + for probe_num, val in enumerate((int(enable_in), int(enable_out))): + cmd = 'TrackOpticalProbeHeight' + rparams = f"{probe_num} {val}" + + enable = bool(val) + enable_desc = 'Enable' if enable else 'Disable' + probe_desc = 'first probe/input probe' if probe_num == 0 else 'second probe/output probe' + command_desc = f'{cmd}({rparams})' + self.logger.info(f"[OptIF Task] - {enable_desc} `Flight Height Control` " + f"for {probe_desc}. Issuing command '{command_desc}'") + self.signals.log_info.emit("OptIF", f" {enable_desc} 'Flight Height Control' " + f"for {probe_desc}.", None) + self.msg_server.sendSciCommand(cmd, rparams=rparams) + + def set_probe_height(self, probe: int, height): + cmd = 'FindOpticalProbeHeight' + rparams = f"{probe} {height}" + + probe_desc = 'first probe/input probe' if probe == 0 else 'second probe/output probe' + command_desc = f'{cmd}({rparams})' + + self.logger.info(f"[OptIF Task] - Move {probe_desc} height to {height} um. " + f"Issuing command '{command_desc}'") + self.signals.log_info.emit("OptIF Task", f" Move {probe_desc} height to {height} um.", None) + self.msg_server.sendSciCommand(cmd, rparams=rparams) + + def move_optical_probe(self, probe: int, x, y, pos_ref='H'): + """ + Move selected probe motor in XY. + :param probe 0=Input, 1=Output (I) + :param x motor command [um] (D) + :param y motor command [um] (D) + :param pos_ref R=Relative, H=Home, Z=Zero (C) + """ + cmd = 'MoveOpticalProbe' + rparams = f"{probe} {x} {y} {pos_ref}" + command_desc = f'{cmd}({rparams})' + self.logger.info(f"[OptIF Task] - Move selected probe motor. " + f"Issuing command '{command_desc}'") + self.msg_server.sendSciCommand(cmd, rparams=rparams) + + def move_pzt(self, probe: int, x, y, z, pos_ref='H'): + """ + Pythonized command for SiP Remote Interface 'MovePZT' + Move selected PZT. + :param probe: 0=Input, 1=Output (I) + :param x: x PZT command [um] (D) + :param y: y PZT command [um] (D) + :param z: z PZT command [um] (D) + :param pos_ref: PosRef R=Relative, H=Home, Z=Zero (C) + """ + cmd = "MovePZT" + rparams = f"{probe} {x} {y} {z} {pos_ref}" + self.logger.info(f"[OptIF Task] - Move selected PZT.") + return self._send_command(cmd, rparams=rparams, + desc=f"{cmd}(probe={probe}, x={x}, y={y}, z={z}, posref={pos_ref})") + + def recenter_optical_probe(self, probe: int): + cmd = 'RecenterOpticalProbe' + rparams = f"{probe}" + + probe_desc = 'first probe/input probe' if probe == 0 else 'second probe/output probe' + command_desc = f'{cmd}({rparams})' + + self.logger.info(f"[OptIF Task] - Recenter {probe_desc}. " + f"Issuing command '{command_desc}'") + self.signals.log_info.emit("OptIF Task", f"Recenter {probe_desc}.", None) + + self.msg_server.sendSciCommand(cmd, rparams=rparams) + + def area_scan(self, probe_in: bool = True, probe_out: bool = True): + cmd = 'AreaScan' + probe_in, probe_out = (int(probe_in), int(probe_out)) + rparams = f"{probe_in} {probe_out}" + + if probe_in == 1 and probe_out == 1: + probe_desc = 'input and output probe' + elif probe_in == 1 and probe_out == 0: + probe_desc = 'first probe/input probe' + elif probe_in == 0 and probe_out == 1: + probe_desc = 'second probe/output probe' + else: + raise ValueError("area_scan requires at least one probe to be selected.") + + command_desc = f'{cmd}({rparams})' + + self.logger.info(f"[OptIF Task] - Performing area scan on {probe_desc}. " + f"Issuing command '{command_desc}'") + self.signals.log_info.emit("OptIF Task", f"Performing area scan on {probe_desc}", None) + + x_1, x_2, y_1, y_2, input_power, output_power = self.msg_server.sendSciCommand(cmd, rparams=rparams) + return x_1, x_2, y_1, y_2, self.conv_pwr(input_power), self.conv_pwr(output_power) + + def set_optical_probe_home(self, probe: int) -> (int, int, int, int, int, int): + cmd = 'SetOpticalProbeHome' + rparams = f"{probe}" + return self.msg_server.sendSciCommand(cmd, rparams=rparams) + + def read_optical_probe_pos(self, probe, pos_ref='H') -> (float, float, float, float, float, float): + """ + Pythonized command for SiP Remote Interface 'ReadOpticalProbePos' + Read optical probe position. + :param probe: 0=Input, 1=Output (I) + :param pos_ref: H=Home, Z=Zero (C) + :return: + x1: x motor position [um] + y1: y motor position [um] + z1: z motor position [um] + x2: x motor PZT [um] + y2: y PZT position [um] + z2: x PZT position [um] + """ + cmd = "ReadOpticalProbePos" + rparams = f"{probe} {pos_ref}" + self.logger.info(f"[OptIF Task] - Reading optical probe position. ") + return self._send_command(cmd, rparams=rparams, desc=f"{cmd}(probe={probe}, posref={pos_ref})") + + + # ================================================================================================================== + # Custom implementations I + # ================================================================================================================== + def _send_command(self, cmd: str, rparams: str = None, desc: str = None): + + issuing_command = f'{cmd}({rparams})' + if desc is not None: + self.logger.debug(f"Issuing command {desc} -> '{issuing_command}'") + else: + self.logger.debug(f"Issuing command '{issuing_command}'") + + self.signals.log_info.emit("OptIF Task", f"Issuing command '{issuing_command}'", None) + r = self.msg_server.sendSciCommand(cmd, rparams=rparams) + self.logger.debug(f"Command returned '{r}'") + return r + + # ================================================================================================================== + # Custom implementations II + # ================================================================================================================== + def conv_pwr(self, power: list | str | float | int) -> float: + """ + Area scan return different types for the power values, this function can convert it. + """ + try: + if isinstance(power, list): + power = float(power[0]) + elif isinstance(power, str): + if "na" == power.lower: + power = -80 + else: + power = float(power) + else: + power = float(power) + except Exception as e: + power = -80 + print(f"Cant convert <{power}>: {e}") + return float(power) + + def _recenter_and_scan(self) -> (float, float, float, float, float, float): + self.recenter_optical_probe(Probe.INPUT) + self.recenter_optical_probe(Probe.OUTPUT) + x_1, x_2, y_1, y_2, input_power, output_power = self.area_scan(True, True) + return float(x_1), float(x_2), float(y_1), float(y_2), self.conv_pwr(input_power), self.conv_pwr( + output_power) + + def search_for_light(self, threshold: float = -70, threshold_areascan: float = -60, retries: float = 3): + self.logger.debug(f"[OptIF Task] - {pch('*', 20)} Search for light {pch('*', 20)}") + self.signals.log_debug.emit("OptIF Task", f"*** Search for light ***", None) + + # Recenter the probes, perform an area scan, recenter again. + self.logger.info(f"[OptIF Task] - Recenter optical probes and performing area scan (1/2).") + self.signals.log_info.emit("OptIF Task", f"Recenter optical probes (1/2).", None) + self._recenter_and_scan() + + self.logger.info(f"[OptIF Task] - Recenter optical probes and performing area scan (2/2).") + self.signals.log_info.emit("OptIF Task", f"Recenter optical probes (2/2).", None) + x_1, x_2, y_1, y_2, input_power, output_power = self._recenter_and_scan() + + # Now we need to verify the power + self.logger.info(f"[OptIF Task] - Verifying power. Probe input power: {input_power}. " + f"Probe output power {output_power}. " + f"Abortion criteria is {threshold}/{threshold_areascan} or {retries} retries.") + self.signals.log_info.emit("OptIF Task", f"Probe input power: {input_power}. " + f"Probe output power {output_power}.", None) + while ( + ((input_power < threshold_areascan and output_power >= threshold) or + (output_power < threshold_areascan and input_power >= threshold)) and + retries > 0 + ): + self.logger.info(f"[OptIF Task] - Input power ({input_power}) or output power ({output_power}) " + f"too low but signal found. Trying area scan again ({retries - 1} " + f"retrie(s) left). Threshold is {threshold_areascan}") + self.signals.log_info.emit("OptIF Task", + f"Input power ({input_power}) or output power ({output_power}) " + f"too low but signal found. ", None) + x_1, x_2, y_1, y_2, input_power, output_power = self._recenter_and_scan() + retries -= 1 + + self.logger.debug(f"[OptIF Task] - {pch('*', 20)} Search for light completed {pch('*', 20)}") + self.signals.log_debug.emit("OptIF Task", f"*** Search for light completed***", None) + return input_power, output_power + + # ================================================================================================================== + # Store and load functions + # ================================================================================================================== + def store_optical_probe_motor_pos(self) -> (float, float, float, float, float, float): + """ + Stores the current motor position of the optical probe . + """ + self.stored.motor_in_x, self.stored.motor_in_y, self.stored.motor_in_z, \ + _, _, _ = self.read_optical_probe_pos(0) + + self.stored.motor_out_x, self.stored.motor_out_y, self.stored.motor_out_z, \ + _, _, _ = self.read_optical_probe_pos(1) + + def store_optical_probe_pzt_pos(self) -> (float, float, float, float, float, float): + """ + Stores the current PZT position of the optical probe . + """ + _, _, _, self.stored.pzt_in_x, self.stored.pzt_in_y, self.stored.pzt_in_z = self.read_optical_probe_pos(0) + + _, _, _, self.stored.pzt_out_x, self.stored.pzt_out_y, self.stored.pzt_out_z = self.read_optical_probe_pos(1) + + def store_optical_probe_pos(self) -> (float, float, float, float, float, float): + """ + Stores the current motor position of the optical probe . + """ + self.stored.motor_in_x, self.stored.motor_in_y, self.stored.motor_in_z, \ + self.stored.pzt_in_x, self.stored.pzt_in_y, self.stored.pzt_in_z = self.read_optical_probe_pos(0) + + self.stored.motor_out_x, self.stored.motor_out_y, self.stored.motor_out_z, \ + self.stored.pzt_out_x, self.stored.pzt_out_y, self.stored.pzt_out_z = self.read_optical_probe_pos(1) + + def restore_optical_probe_motor_pos(self, probe: int) -> (float, float, float, float, float, float): + self.move_optical_probe(probe, self.stored.motor_in_x, self.stored.motor_in_y, pos_ref='H') + return self.read_optical_probe_pos(probe) + + def restore_optical_probe_pzt_pos(self, probe: int) -> (float, float, float, float, float, float): + self.move_pzt(probe, self.stored.pzt_in_x, self.stored.pzt_in_y, self.stored.pzt_in_z, pos_ref='H') + return self.read_optical_probe_pos(probe) + + # ================================================================================================================== + # Store and load functions + # ================================================================================================================== + diff --git a/src/FlexSensor/Prober/controller/OpticalProbesPosition.py b/src/FlexSensor/Prober/controller/OpticalProbesPosition.py new file mode 100644 index 0000000000000000000000000000000000000000..19e061486ebbf6887f9f7ad90bfd226d4b8d5b34 --- /dev/null +++ b/src/FlexSensor/Prober/controller/OpticalProbesPosition.py @@ -0,0 +1,27 @@ +import sys +import logging + + +class OpticalProbesPosition: + + def __init__(self, input: tuple, output: tuple): + self.INPUT: ProbePosition = ProbePosition(input) + self.OUT: ProbePosition = ProbePosition(output) + self.logger = logging.getLogger('OpticalProbesPosition') + + + def __str__(self): + return f"INPUT: {self.INPUT} | OUT: {self.OUT}" + + +class ProbePosition: + + def __init__(self, position: tuple): + self.x, self.y, self.z = position + + def __str__(self): + return f"x:{self.x} - y:{self.y} - z:{self.z}" + + def __substract__(self, other): + pass + diff --git a/src/FlexSensor/Prober/controller/ProberController.py b/src/FlexSensor/Prober/controller/ProberController.py new file mode 100644 index 0000000000000000000000000000000000000000..7486b757787535dd513f8cdd5fdc2d9c975cb130 --- /dev/null +++ b/src/FlexSensor/Prober/controller/ProberController.py @@ -0,0 +1,411 @@ +import logging + +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from Prober.controller.OpticalInterface import OpticalInterface +import Prober +from Prober.model.ProberModel import ProberModel +from constants.FlexsensorConstants import Probe +from generics.generics import pch + + +class ProberController: + def __init__(self, model: ProberModel, vaut_config: VAutomatorConfig, *args, **kwargs): + + self.vaut_config = vaut_config + self.model = model + + self.model.wafer_map = self.vaut_config.wafer_config.wafermap_file + + self.logger = logging.getLogger("Prober") + self.signals = Prober.Signals() + self.msg_server = Prober.MessageServerInterface() + + # Optical Interface Control hexapods and piezos + self.opt_if = OpticalInterface(self.signals, self.msg_server) + self.logger.info("Prober initialized") + + self.model.version = self.report_kernel_version() + self.get_die_as_col_row() + self.read_chuck_position() + self.model.connected = True + + # ================================================================================================================== + # Velox API Calls. + # Some Wrappers to the official Velox API calls + # ================================================================================================================== + def set_chuck_home(self, mode: str = '0', unit: str = 'Y', x_value: float = 0, y_value: float = 0): + """ Velox API Call. Sets wafer and die home position, which can be used later as coordinate system + for movements. + Keyword arguments: + mode: str -- '0' use the current position or the given value otherwise. (default "0") + unit: str -- Sets the unit (Y: 'Microns' or I 'Mils'). Required if mode is not set to default (Y). + (default 'Microns') + x_value: float -- Required if mode is not set to V. (default 0) + y_value: float -- Required if mode is not set to V. (default 0) + Command Timeout: 5000 + """ + self.logger.info(f"[Prober Task] - Set Chuck home. Issuing command 'SetChuckHome({mode})'") + self.signals.log_info.emit("Prober Report", f"Set Chuck Home.", None) + Prober.SetChuckHome(str(mode), str(unit), x_value, y_value) + + def set_map_home(self, col=0, row=0): + """ Velox API Call. If the command has no parameters it sets the current position as home position + both for the wafer map and for the chuck. Otherwise, it changes the wafer map + home position using the given die coordinates. + Keyword arguments: + col: int -- Column (optional). (default 0) + row: int -- Row (optional). (default 0) + Command Timeout: 10000 + """ + self.logger.info(f"[Prober Task] - Set Map home to col {col} and row {row}. " + f"Issuing command 'SetMapHome({col}, {row})'") + self.signals.log_info.emit("Prober Report", f"Map Home set to {col}, {row}.", None) + Prober.SetMapHome(col, row) + + def read_chuck_position(self, unit: str = "Microns", pos_ref: str = "Home", comp: str = "Default") -> (float, float, float): + """ Velox API Call. Returns the current chuck stage position in X, Y and Z. + Args: + unit:str = "Microns" + pos_ref:str = "Home" + comp:str = "Default" + Returns: + X:float + Y:float + Z:float + Command Timeout: 5000 + """ + self.model._chuck_x, self.model._chuck_y, self.model._chuck_z = Prober.ReadChuckPosition(Unit=unit, PosRef=pos_ref) + self.logger.info(f"[Prober Report] - " + f"Current Chuck position X:{self.model._chuck_x} Y:{ self.model._chuck_y} Z:{self.model._chuck_z}") + self.signals.log_info.emit("Prober Report", + f"Current Chuck position " + f"X:{self.model._chuck_x} " + f"Y:{ self.model._chuck_y} " + f"Z:{self.model._chuck_z}", None) + return float(self.model._chuck_x), float(self.model._chuck_y), float(self.model._chuck_z) + + def check_contact_height_set(self) -> (float, float, float, float, float): + """ Velox API Call. Returns the current settings used for the chuck Z movement. `Contact` is the + contact-height from zero in default compensation. The other heights are relative + to this. If no contact is set, an error will be raised. + API Status: published + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + SearchGap:Decimal + Command Timeout: 5000 + """ + self.logger.debug("[Prober Task] - Check if contact height is set. Issuing command 'ReadChuckHeights'") + self.signals.log_debug.emit("Prober Task", "Check if contact height is set. Issuing command 'ReadChuckHeights'", + None) + contact, overtravel, align_dist, sep_dis, search_gap = Prober.ReadChuckHeights() + + if contact == -1: + self.logger.error("[Prober Task] - Contact height not set, please set it before running this script. " + "Script will be stopped.") + raise Exception("Contact height not set, please set it before running this script. Script will be stopped.") + + self.logger.debug(f"[Prober Task] - Contact height set to {contact}") + self.signals.log_debug.emit("Prober Task", f"Contact height set to {contact}", None) + + return float(contact), float(overtravel), float(align_dist), float(sep_dis), float(search_gap) + + def move_chuck(self, x_value: float = 0, y_value: float = 0, + pos_ref: str = "H", unit: str = "Y", velocity: float = 100, comp: str = "D"): + """ Velox API Call. Moves the chuck stage to the specified X,Y position. If chuck Z is in contact + height or higher, Interlock and Auto Z flags will be analyzed and stage will + behave correspondingly - can move to separation first or return an error: + Keyword arguments: + x_value:float -- X Value (optional). (default 0) + y_value:float -- Y Value (optional). (default 0) + pos_ref:str -- "H: Home", "Z: Zero", "C: Center", "R: Current Position". (default "H: Home") + unit:str -- "Y: Microns", "I: Mils", "X: Index", "J: Jog". (default "M: Microns") + velocity:float -- Velocity in percent. (default 100) + comp:str + "D: Default": Use the default compensation. Uses "Technology" by default. + "T: Technology": Use Prober, offset and Technology compensation. (default) + "O: Offset": Use Prober and Offset compensation. + "P: Prober" Use only Prober compensation. + "N: None": Does not use compensation. + (default "D: Default") + Command Timeout: 30000 + """ + self.logger.debug(f"[Prober Task] - Move Chuck to x: {x_value} y: {y_value}. " + f"Issuing command 'MoveChuck({x_value}, {y_value}, {pos_ref}, {unit}, {velocity}, {comp})'") + self.signals.log_debug.emit("Prober Task", f"Move Chuck to x: {x_value} y: {y_value}", None) + Prober.MoveChuck(x_value, y_value, pos_ref, unit, velocity, comp) + + def snap_image(self, mount_pos: str = "eVue2", full_path: str = "./Image.bmp", snap_shot_mode: int = 2): + """ + Velox API Call. Saves the currently displayed image to the specified file. The image is stored + in the requested file format (bmp, jpg or png). By default. it will save the raw + camera image and an image with the overlays that are currently visible on the + camera view. Using a parameter, one can decide to only save either raw image, + overlay image or both. By Specifying 'ALL' as the mount position, the captured + screenshot will consist of the currently selected camera layout without + providing the raw image. If MountPos and FullPath are empty then the current + camera view with overlays is copied to the clipboard. + API Status: published + Args: + mount_pos:str -- Mount position of camera from which the image will be taken: + 'Scope', 'eVue1', 'eVue2', 'eVue3', 'Chuck', 'Platen', 'ContactView', or 'All'. + (default "eVue2") + + (If you use ‘Scope’ on a system with eVue, the image will be from eVue2). + If set to ‘All’ the currently visible camera layout will be captured in the screenshot + "eVue2". + full_path:str -- Path where the image will be stored. (default: "./Image.bmp") + snap_shot_mode:int -- Type of snapshot (default 2) + 0 – Raw Image from camera + 1 – Screenshot of camera window including overlays; + 2 – Both images + Example:SnapImage Scope C:/Temp/Image.bmp + """ + self.logger.debug(f"[Prober Task] - Save scope image {mount_pos} to {full_path} (mode: {snap_shot_mode}). " + f"Issuing command 'SnapImage({mount_pos}, {full_path}, {snap_shot_mode})'") + self.signals.log_debug.emit("Prober Task", + f"Save scope image {mount_pos} to {full_path} (mode: {snap_shot_mode}).", None) + Prober.SnapImage(mount_pos, full_path, snap_shot_mode) + + def report_kernel_version(self): + v = Prober.ReportKernelVersion() + self.model.kernel_version = str(v.Version) + "." + str(v.Description) + return str(v.Version) + "." + str(v.Description) + + def get_die_as_col_row(self): + # Read the die data: die number, col, row + self.model.die, self.model.die_col, self.model.die_row, bin, res = Prober.GetDieDataAsColRow() + self.logger.info(f"[Prober Report] - Current die number: {self.model.die} " + f"(col: {self.model.die_col}, row: {self.model.die_row})") + self.signals.log_info.emit("Prober Report", f"Current die number: {self.model.die} " + f"(col: {self.model.die_col}, row: {self.model.die_row})", None) + return self.model.die, self.model.die_col, self.model.die_row + # ================================================================================================================== + # + # ================================================================================================================== + def move_to_die(self, die_num=0) -> (float, float, float): + ''' + Move to the specified die and sets the home position accordingly + ''' + + # TODO: check if die is in the correct position and check if height is correct + self.logger.debug(f"[Prober Task] - {pch('*', 20)} Moving to die {die_num} {pch('*', 20)}") + self.signals.log_debug.emit("Prober Task", f"*** Moving to die {die_num} ***", None) + + # We need to make sure that our fiber height is correct + # TODO: Check fiber height - this is important! IMPLEMENT HERE + # ... + # ... + # raise NotImplementedError("Check fiber hight not implemented yet") + + # Move to die + # Disable the flight height control + self.opt_if.enable_flight_height_control(enable_in=False, enable_out=False) + + # FindOpticalProbeHeight(0, 100) + # FindOpticalProbeHeight(1, 100) + + # Step to the specified die + self.logger.info(f"[Prober Task] - Step to the specified die {die_num}. Issuing command 'StepToDie({die_num})'") + self.signals.log_info.emit("Prober Task", f"Step to the specified die {die_num}", None) + Prober.StepToDie(die_num) + + # Move hexapod and nano to height 50 um + height = 80 + self.opt_if.set_probe_height(Probe.INPUT, height) + self.opt_if.set_probe_height(Probe.OUTPUT, height) + + # Read the die data: die number, col, row + self.model.die, self.model.die_col, self.model.die_row = self.get_die_as_col_row() + + # Set the current chuck and map to home + self.set_chuck_home() + self.set_map_home(self.model.die_col, self.model.die_row) + + # For reducing errors, read the chuck position + self.model._chuck_x, self.model._chuck_y, self.model._chuck_z = self.read_chuck_position(unit="Microns", pos_ref="Home") + + self.logger.info(f"[Prober Task] - {pch('*', 20)} MOVING TO DIE COMPLETE {pch('*', 20)}") + self.signals.log_info.emit("Prober Report", f"MOVING TO DIE COMPLETE", None) + return self.model.die, self.model.die_col, self.model.die_row + + # ================================================================================================================== + # + # ================================================================================================================== + + def try_finding_light(self, input_power, output_power, threshold=-70): + ran_in = [0, 5, -5, 10, -10, 15, -15, 20, -20, 25, 30, 35, 40, -25, -30, -35, -40] + ran_out = ran_in + # steps = 5 + + input_power = self.msg_server.sendSciCommand("ReadOpticalProbePowerMeter", rparams='0') + input_power = self.conv_result_power(input_power) + + output_power = self.msg_server.sendSciCommand("ReadOpticalProbePowerMeter", rparams='1') + output_power = self.conv_result_power(output_power) + + for x_pos_1 in ran_in: + for y_pos_1 in ran_in: + try: + self.msg_server.sendSciCommand("MoveOpticalProbe", + rparams='0 %s %s R' % ((float(x_pos_1)), (float(y_pos_1)))) + except Exception as e: + self.write_log("error", "Can't move probe to (%s, %s)" % (x_pos_1, y_pos_1)) + self.write_log("error", e) + continue + + for x_pos_2 in ran_out: + for y_pos_2 in ran_out: + self.write_log("debug", + f"{self.formatter} Moving realtivly: Probe 1 X({float(x_pos_1)}) Y({float(y_pos_1)}) " + f"| Probe 2 X({float(x_pos_2)}) Y({float(y_pos_2)}) | Power I:{input_power} O:{output_power}") + + self.msg_server.sendSciCommand("MoveOpticalProbe", + rparams='1 %s %s R' % ((float(x_pos_2)), (float(y_pos_2)))) + + input_power = self.msg_server.sendSciCommand("ReadOpticalProbePowerMeter", rparams='0') + output_power = self.msg_server.sendSciCommand("ReadOpticalProbePowerMeter", rparams='1') + input_power = self.conv_result_power(input_power) + output_power = self.conv_result_power(output_power) + + if (float(input_power) > -72) or (float(output_power) > -72): + try: + self.msg_server.sendSciCommand("AreaScan", rparams='1 1') + self.msg_server.sendSciCommand("RecenterOpticalProbe", rparams='0') + self.msg_server.sendSciCommand("RecenterOpticalProbe", rparams='1') + self.msg_server.sendSciCommand("AreaScan", rparams='1 1') + self.msg_server.sendSciCommand("RecenterOpticalProbe", rparams='0') + self.msg_server.sendSciCommand("RecenterOpticalProbe", rparams='1') + self.msg_server.sendSciCommand("AreaScan", rparams='1 1') + if (float(input_power) > threshold) or (float(output_power) > threshold): + self.write_log("debug", f"Power I:{input_power} O:{output_power}. Continuing.") + return True + except Exception as e: + self.write_log(f"warning {e}") + + self.write_log("debug", + f"{self.formatter} Moving back: Probe 1 X({(-1) * float(x_pos_1)}) Y({(-1) * float(y_pos_1)}) " + f"| Probe 2 X({(-1) * float(x_pos_2)}) Y({(-1) * float(y_pos_2)}) | Power I:{input_power} O:{output_power}") + self.msg_server.sendSciCommand("MoveOpticalProbe", rparams='0 %s %s R' % ( + ((-1) * float(x_pos_1)), ((-1) * float(y_pos_1)))) + self.msg_server.sendSciCommand("MoveOpticalProbe", rparams='1 %s %s R' % ( + ((-1) * float(x_pos_2)), ((-1) * float(y_pos_2)))) + + self.write_log("warning", "No light found.") + return False + + def store_hexapod_position(): + """ + Stores the hexpods and nanocube position for later retrieval + """ + pass + + + # msgServer.sendSciCommand("MoveOpticalProbe", rparams='0 %s %s R' % ( (-1)*(float(x_pos_1)), (-1)*(float(y_pos_1)))) + + def get_hexapod_values(self): + # before performing an area scan, store the current position + try: + motor_x_1, motor_y_1, motor_z_1, pzt_x_1, pzt_y_1, pzt_z_1 = self.msg_server.sendSciCommand( + "ReadOpticalProbePos", rparams='0 H') + motor_x_2, motor_y_2, motor_z_2, pzt_x_2, pzt_y_2, pzt_z_2 = self.msg_server.sendSciCommand( + "ReadOpticalProbePos", rparams='1 H') + self.write_log("info", + "([%s]: %s): Storing reference values for motor 1 (%s, %s, %s) Storing values for PZT 1 (%s, %s, %s). " + % (self.die_no, self.structure, motor_x_1, motor_y_1, motor_z_1, pzt_x_1, pzt_y_1, pzt_z_1) + ) + self.write_log("info", + "([%s]: %s): Storing reference values for motor 2 (%s, %s, %s) Storing values for PZT 2 (%s, %s, %s). " + % (self.die_no, self.structure, motor_x_2, motor_y_2, motor_z_2, pzt_x_2, pzt_y_2, pzt_z_2) + ) + except Exception as e: + self.write_log("warning", "([%s]: %s): Can't store reference values for motor 1 and 2." % ( + self.die_no, self.structure)) + self.write_log("warning", e) + + motor_pos = { + 'motor_1': { + 'x': motor_x_1, 'y': motor_y_1, 'z': motor_z_1 + }, + 'motor_2': { + 'x': motor_x_2, 'y': motor_y_2, 'z': motor_z_2 + } + } + + pzt_pos = { + 'pzt_1': { + 'x': pzt_x_1, 'y': pzt_y_1, 'z': pzt_z_1 + }, + 'pzt_2': { + 'x': pzt_x_2, 'y': pzt_y_2, 'z': pzt_z_2 + } + } + + return motor_pos, pzt_pos + + def _write_debug(self, description, title=None, details=None): + if details is None and title is None: + self.logger.debug(f"{description}.") + self.signals.log_debug.emit(None, description, None) + elif details is not None and title is None: + self.logger.debug(f"{description}: {details}") + self.signals.log_debug.emit(None, description, details) + elif details is None and title is not None: + self.logger.debug(f"[{title}] - {description}") + self.signals.log_debug.emit(None, description, None) + else: + self.logger.debug(f"[{title}] - {description}: {details}") + self.signals.log_debug.emit(title, description, details) + + def _write_info(self, description, title=None, details=None): + if details is None and title is None: + self.logger.info(f"{description}.") + self.signals.log_info.emit(None, description, None) + elif details is not None and title is None: + self.logger.info(f"{description}: {details}") + self.signals.log_info.emit(None, description, details) + elif details is None and title is not None: + self.logger.info(f"[{title}] - {description}") + self.signals.log_info.emit(None, description, None) + else: + self.logger.info(f"[{title}] {description}: {details}") + self.signals.log_info.emit(title, description, details) + + def _write_warning(self, description, title=None, details=None): + if details is None and title is None: + self.logger.warning(f"{description}.") + self.signals.log_warning.emit(None, description, None) + elif details is not None and title is None: + self.logger.warning(f"{description}: {details}") + self.signals.log_warning.emit(None, description, details) + elif details is None and title is not None: + self.logger.warning(f"[{title}] - {description}") + self.signals.log_warning.emit(None, description, None) + else: + self.logger.warning(f"[{title}] - {description}: {details}") + self.signals.log_warning.emit(title, description, details) + + def _write_error(self, description, title=None, details=None): + if details is None and title is None: + self.logger.error(f"{description}.") + self.signals.log_error.emit(None, description, None) + elif details is not None and title is None: + self.logger.error(f"{description}: {details}") + self.signals.log_error.emit(None, description, details) + elif details is None and title is not None: + self.logger.error(f"[{title}] - {description}") + self.signals.log_error.emit(None, description, None) + else: + self.logger.error(f"{title}. {description}: {details}") + self.signals.log_error.emit(title, description, details) + + # ================================================================================================================== + # + # ================================================================================================================== + def __del__(self): + self.msg_server.__exit__() + self.logger.info("Message Server closed!") diff --git a/src/FlexSensor/Prober/model/OpticalInterfaceModel.py b/src/FlexSensor/Prober/model/OpticalInterfaceModel.py new file mode 100644 index 0000000000000000000000000000000000000000..ecd51bbe534740b116077af4914d21a76c25b512 --- /dev/null +++ b/src/FlexSensor/Prober/model/OpticalInterfaceModel.py @@ -0,0 +1,25 @@ +class OpticalInterfaceSignals(): + pass + + + +class OpticalInterfaceModel(): + def __init__(self): + # Motor position + self._motor_out_x: float = 0.0 + self._motor_out_y: float = 0.0 + self._motor_out_z: float = 0.0 + + self._motor_in_x: float = 0.0 + self._motor_in_y: float = 0.0 + self._motor_in_z: float = 0.0 + + # PZT position + self._pzt_out_x: float = 0.0 + self._pzt_out_y: float = 0.0 + self._pzt_out_z: float = 0.0 + + self._pzt_in_x: float = 0.0 + self._pzt_in_y: float = 0.0 + self._pzt_in_z: float = 0.0 + diff --git a/src/FlexSensor/Prober/model/OpticalInterfaceStoredData.py b/src/FlexSensor/Prober/model/OpticalInterfaceStoredData.py new file mode 100644 index 0000000000000000000000000000000000000000..6fd4b13302a1b614ac01368aebc4e164d76d4aa2 --- /dev/null +++ b/src/FlexSensor/Prober/model/OpticalInterfaceStoredData.py @@ -0,0 +1,116 @@ +class OpticalInterfaceStoredData: + def __init__(self): + self._motor_out_x: float = 0.0 + self._motor_out_y: float = 0.0 + self._motor_out_z: float = 0.0 + + self._motor_in_x: float = 0.0 + self._motor_in_y: float = 0.0 + self._motor_in_z: float = 0.0 + + # PZT position + self._pzt_out_x: float = 0.0 + self._pzt_out_y: float = 0.0 + self._pzt_out_z: float = 0.0 + + self._pzt_in_x: float = 0.0 + self._pzt_in_y: float = 0.0 + self._pzt_in_z: float = 0.0 + + @property + def motor_out_x(self): + return self._motor_out_x + + @motor_out_x.setter + def motor_out_x(self, value): + self._motor_out_x = value + + @property + def motor_out_y(self): + return self._motor_out_y + + @motor_out_y.setter + def motor_out_y(self, value): + self._motor_out_y = value + + @property + def motor_out_z(self): + return self._motor_out_z + + @motor_out_z.setter + def motor_out_z(self, value): + self._motor_out_z = value + + @property + def motor_in_x(self): + return self._motor_in_x + + @motor_in_x.setter + def motor_in_x(self, value): + self._motor_in_x = value + + @property + def motor_in_y(self): + return self._motor_in_y + + @motor_in_y.setter + def motor_in_y(self, value): + self._motor_in_y = value + + @property + def motor_in_z(self): + return self._motor_in_z + + @motor_in_z.setter + def motor_in_z(self, value): + self._motor_in_z = value + + @property + def pzt_out_x(self): + return self._pzt_out_x + + @pzt_out_x.setter + def pzt_out_x(self, value): + self._pzt_out_x = value + + @property + def pzt_out_y(self): + return self._pzt_out_y + + @pzt_out_y.setter + def pzt_out_y(self, value): + self._pzt_out_y = value + + @property + def pzt_out_z(self): + return self._pzt_out_z + + @pzt_out_z.setter + def pzt_out_z(self, value): + self._pzt_out_z = value + + @property + def pzt_in_x(self): + return self._pzt_in_x + + @pzt_in_x.setter + def pzt_in_x(self, value): + self._pzt_in_x = value + + @property + def pzt_in_y(self): + return self._pzt_in_y + + @pzt_in_y.setter + def pzt_in_y(self, value): + self._pzt_in_y = value + + @property + def pzt_in_z(self): + return self._pzt_in_z + + @pzt_in_z.setter + def pzt_in_z(self, value): + self._pzt_in_z = value + + diff --git a/src/FlexSensor/Prober/model/ProberModel.py b/src/FlexSensor/Prober/model/ProberModel.py new file mode 100644 index 0000000000000000000000000000000000000000..4552abbd0ae40a995bc1e89af7215d52dea2d836 --- /dev/null +++ b/src/FlexSensor/Prober/model/ProberModel.py @@ -0,0 +1,164 @@ +from pathlib import Path + +from PySide6.QtCore import QObject, Signal + +from MeasurementData.Properties.WaferProperties import WaferProperties + + +class ProberSignals(QObject): + ''' + Defines the signals available from a running prober thread. + The signals are always constructed for proagating it's status + to a Message Bix with + Signal(title, description, details) + ''' + + connected_changed = Signal(bool) + version_changed = Signal(str) + wafer_map_changed = Signal(Path) + + die_changed = Signal(int) + curr_die_row_changed = Signal(int) + curr_die_col_changed = Signal(int) + + chuck_x_changed = Signal(float) + chuck_z_changed = Signal(float) + chuck_y_changed = Signal(float) + + errors_changed = Signal(list) + warnings_changed = Signal(list) + + + + + log_debug = Signal(str, str, str) + log_info = Signal(str, str, str) + log_warning = Signal(str, str, str) + log_error = Signal(str, str, str) + + +class ProberModel: + + def __init__(self): + self.signals = ProberSignals() + + self._connected: bool = False + self._version: str = "Unknown Version" + + self._die: int = 0 + self._die_row: int = 0 + self._die_col: int = 0 + + self._chuck_x: float = 0 + self._chuck_y: float = 0 + self._chuck_z: float = 0 + + self._errors: list = [] + self._warnings: list = [] + + self._wafer_map = None + + @property + def laser_properties(self) -> WaferProperties: + return WaferProperties(self.acceleration, + self.deceleration, + self.velocity, + (self.sweep_start_wavelength, self.sweep_stop_wavelength)) + @property + def connected(self) -> bool: + return self._connected + + @connected.setter + def connected(self, value: bool): + self._connected = value + self.signals.connected_changed.emit(value) + + @property + def version(self) -> str: + return self._version + + @version.setter + def version(self, value: str): + self._version = value + self.signals.version_changed.emit(value) + + @property + def wafer_map(self) -> Path: + return self._wafer_map + + @wafer_map.setter + def wafer_map(self, value: Path): + self._wafer_map = value + self.signals.wafer_map_changed.emit(value) + + @property + def die(self) -> int: + return self._die + + @die.setter + def die(self, value: int): + self._die = value + self.signals.die_changed.emit(value) + + @property + def die_row(self) -> int: + return self._die_row + + @die_row.setter + def die_row(self, value: int): + self._die_row = value + self.signals.curr_die_row_changed.emit(value) + + @property + def die_col(self) -> int: + return self._die_col + + @die_col.setter + def die_col(self, value: int): + self._die_col = value + self.signals.curr_die_col_changed.emit(value) + + @property + def chuck_x(self) -> float: + return self._chuck_x + + @chuck_x.setter + def chuck_x(self, value: float): + self._chuck_x = float(value) + self.signals.chuck_x_changed.emit(self._chuck_x) + + @property + def chuck_y(self) -> float: + return self._chuck_y + + @chuck_y.setter + def chuck_y(self, value: float): + self._chuck_y = float(value) + self.signals.chuck_y_changed.emit(self._chuck_y) + + @property + def chuck_z(self) -> float: + return self._chuck_z + + @chuck_z.setter + def chuck_z(self, value: float): + self._chuck_z = float(value) + self.signals.chuck_z_changed.emit(self.chuck_z) + + @property + def errors(self) -> list: + return self._errors + + @errors.setter + def errors(self, value: list): + self._errors = value + self.signals.errors_changed.emit(value) + + @property + def warnings(self) -> list: + return self._warnings + + @warnings.setter + def warnings(self, value: list): + self._warnings = value + self.signals.warnings_changed.emit(value) diff --git a/src/FlexSensor/Prober/model/WaferProperties.py b/src/FlexSensor/Prober/model/WaferProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..1038b55c5b3be60812bf4d418ba77517815ba0e0 --- /dev/null +++ b/src/FlexSensor/Prober/model/WaferProperties.py @@ -0,0 +1,94 @@ +import numpy as np +from numpy import ndarray + +from generics.GenericProperties import GenericProperties + + +class WaferProperties(GenericProperties): + def __init__(self, + wafer_number: str, structure_name: str, + die_nr: int, chuck_col: int, chuck_row: int, + structure_in: tuple, structure_out: tuple, + repetitions: int + ): + super().__init__() + self._structure_name = self.to_str(structure_name) + self._wafer_number = self.to_str(wafer_number) + + self._die_number = self.to_int(die_nr[0]) + self._chuck_col = self.to_int(chuck_col[0]) + self._chuck_row = self.to_int(chuck_row[0]) + + self._structure_in = self.to_tuple(structure_in) + self._structure_out = self.to_tuple(structure_out) + self._structure_x_in = int(self._structure_in[0]) + self._structure_y_in = int(self._structure_in[1]) + self._structure_x_out = int(self._structure_out[0]) + self._structure_y_out = int(self._structure_out[1]) + + self._repetitions: int = self.to_int(repetitions) + + @property + def repetition(self): + return int(self._repetitions) + + @property + def chuck_col(self): + return int(self._chuck_col) + + @property + def chuck_row(self): + return int(self._chuck_row) + + @property + def wafer_number(self) -> str: + return str(self._wafer_number) + + @property + def structure_x_in(self): + return int(self._structure_x_in) + + @property + def structure_y_in(self): + return int(self._structure_y_in) + + @property + def structure_x_out(self): + return int(self._structure_x_out) + + @property + def structure_name(self): + return str(self._structure_name) + + @property + def die_number(self) -> int: + return int(self._die_number) + + @property + def structure_y_out(self): + return int(self._structure_y_out) + + @property + def structure_in(self): + return tuple(self._structure_in) + + @property + def structure_out(self): + return tuple(self._structure_out) + + @property + def chuck_row(self): + return int(self._chuck_row) + + def fields(self) -> dict: + return { + 'wafer_number': self.wafer_number, + 'die_number': self.die_number, + 'structure_name': self.structure_name, + 'repetition': self.repetition, + 'structure_in': self.structure_in, + 'structure_out': self.structure_out, + 'chuck_col': self.chuck_col, + 'chuck_row': self.chuck_row + + } \ No newline at end of file diff --git a/src/FlexSensor/Prober/velox_api/MANIFEST.in b/src/FlexSensor/Prober/velox_api/MANIFEST.in new file mode 100644 index 0000000000000000000000000000000000000000..f592b1ce090a55402214a78fad5143a82491c31c --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/MANIFEST.in @@ -0,0 +1,5 @@ +include README.rst +include readme.txt +include Velox Python Interface.rtf +include velox/samples/* +include velox/sci/* diff --git a/src/FlexSensor/Prober/velox_api/PKG-INFO b/src/FlexSensor/Prober/velox_api/PKG-INFO new file mode 100644 index 0000000000000000000000000000000000000000..93ab8ec31d442401d75ee1f3672a53e5c9359ab9 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: velox +Version: 3.0.0.266 +Summary: Python 2.7+ and 3.5+ interface for Velox +Home-page: UNKNOWN +Author: Formfactor +Author-email: UNKNOWN +License: See Formfactor Velox Product License. +Description: UNKNOWN +Platform: UNKNOWN diff --git a/src/FlexSensor/Prober/velox_api/README.rst b/src/FlexSensor/Prober/velox_api/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..7e8b3f301ecfd8f8f8af7929f1953d1e74f4e672 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/README.rst @@ -0,0 +1,29 @@ +Installation +=============== +Copy the velox.tar.gz file to a convenient location and open a command prompt there. + +To install, use PIP: +> python -m pip install velox.tar.gz + +NOTE: You must use the full file extension to avoid getting any modules named +Velox from the public Python repository. + +Usage Overview +=============== +The velox folder contains the modules for interfacing with the Velox Message Server APIs +via SCI Commands (see documentation for the Velox Integration Toolkit). + +This folder contains the ``__init__.py`` file that automatically imports the correct +module based on the version of Python running at the time. + +Your code should: +------------------ + +``import velox`` + +The __init__.py will load an SCI module appropriate for either Python 2.7+ or Python 3.5+ +based on the version of Python being executed. + +The ``velox.sci27.py`` or ``velox.sci35.py`` module will import the ``vxmessageserver.py`` + + diff --git a/src/FlexSensor/Prober/velox_api/readme.txt b/src/FlexSensor/Prober/velox_api/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce665530c759145afb22d5f1bf29fd237d7d9e08 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/readme.txt @@ -0,0 +1,31 @@ +Installation +=============== +Copy the velox.zip file to a convenient location and open a command prompt there. + +To install, use PIP: +> python -m pip install velox.tar.gz + +NOTE: You must use the full file extension to avoid getting any modules named +Velox from the public Python repository. + +Usage Overview +=============== +The velox folder contains the modules for interfacing with the Velox Message Server APIs +via SCI Commands (see documentation for the Velox Integration Toolkit). + +This folder contains the ``__init__.py`` file that automatically imports the correct +module based on the version of Python running at the time. + +Your code should: +------------------ + +``import velox`` + +The __init__.py will load an SCI module appropriate for either Python 2.7+ or Python 3.5+ +based on the version of Python being executed. + +The ``velox.sci27.py`` or ``velox.sci35.py`` module will import the ``vxmessageserver.py`` + + + + diff --git a/src/FlexSensor/Prober/velox_api/setup.cfg b/src/FlexSensor/Prober/velox_api/setup.cfg new file mode 100644 index 0000000000000000000000000000000000000000..8bfd5a12f85b8fbb6c058cf67dd23da690835ea0 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/setup.cfg @@ -0,0 +1,4 @@ +[egg_info] +tag_build = +tag_date = 0 + diff --git a/src/FlexSensor/Prober/velox_api/setup.py b/src/FlexSensor/Prober/velox_api/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..ec20e5fcd8171c0593854e1a28e3270a187bb745 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup + +setup( + name='velox', + version='3.0.0.266', + packages=['velox'], + url='', + license='See Formfactor Velox Product License.', + author='Formfactor', + author_email='', + description='Python 2.7+ and 3.5+ interface for Velox', + include_package_data=True +) diff --git a/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py b/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py new file mode 100644 index 0000000000000000000000000000000000000000..d847ac3a11b51549c03a6fb7fa4706c79a2f645a --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py @@ -0,0 +1,12426 @@ +import random +import time + +from decimal import Decimal +from collections import namedtuple + +""" +Velox SCI Commands +This module provides a function interface to the Cascade Microtech Velox software suite. +The module was auto-generated from the commands.info.xml file on 2019-11-09. +737 SCI commands were found and included. + +To use this module, your code must import the veloxsci.py module. +Create a connection to the Velox Message Server using the 'with MessageServerInterface():' +command as shown in the sample below. + +The Velox Message Server must be running prior to establishing a connection. +To start the Message Server, run Velox. + +The sample code to use this module is: + +import velox +with velox.MessageServerInterface() as msgServer: + + # Your Code: try some SCI Commands - such as: + response = velox.ReportKernelVersion() + print ('The kernel version is', response.Version, 'and', response.Description) + +""" +def EchoData(TestCmd:str=""): + """ + Test Command for the Kernel Communication. Like a ping command, the given text + string is returned unchanged. + API Status: published + Args: + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:EchoData Test + """ + rsp = MessageServerInterface.sendSciCommand("EchoData",TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportKernelVersion(Module:str=""): + """ + Returns the version information of the kernel or the control box code. The + "Version" value contains version number and revision level of the actual Kernel + implementation. The text string contains a code description, version number and + the revision date. + API Status: published + Args: + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:ReportKernelVersion K + """ + rsp = MessageServerInterface.sendSciCommand("ReportKernelVersion",Module) + global ReportKernelVersion_Response + if not "ReportKernelVersion_Response" in globals(): ReportKernelVersion_Response = namedtuple("ReportKernelVersion_Response", "Version,Description") + return ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReadProberStatus(): + """ + Returns an actual status information of the prober. + API Status: published + Returns: + FlagsBusy:int + FlagsContact:int + Mode:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadProberStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadProberStatus") + global ReadProberStatus_Response + if not "ReadProberStatus_Response" in globals(): ReadProberStatus_Response = namedtuple("ReadProberStatus_Response", "FlagsBusy,FlagsContact,Mode,IsQuiet") + return ReadProberStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3])) + +def EnableMotorQuiet(WantQuietModeOn:int="", Stage:str=""): + """ + Toggles the motor power for quiet probing. In most applications this feature is + not required. However, for special measurements it may be necessary to reduce + the noise of the system. Quiet on turns off the motor power for all stages (or + the one specified with the optional parameter). Quiet off will turn on the motor + power of all stages (or the one specified with the optional parameter) for + subsequent movements. A move command will also turn on the motor power of the + moved stage automatically. For automatical switching of the quiet mode refer to + Auto Quiet functionality. Sending 'EnableMotorQuiet 1' will enable the quiet + mode for all stages. Sending 'EnableMotorQuiet 1 C' will only enable the quiet + mode for the chuck stage. Sending 'EnableMotorQuiet 1 1' will only enable the + quiet mode for the Positioner1 stage. Sending 'EnableMotorQuiet 0 S' will only + disable the quiet mode for the scope stage. + API Status: published + Args: + WantQuietModeOn:int = 0 + Stage:str = "None" + Command Timeout: 10000 + Example:EnableMotorQuiet 1 + """ + MessageServerInterface.sendSciCommand("EnableMotorQuiet",WantQuietModeOn,Stage) + + +def SetChuckVacuum(WantChuckVacuumOn:int=""): + """ + Toggles the chuck vacuum on (1) or off (0). Can return vacuum timeout error for + stations with wafer vacuum sensors in case no wafer was detected. + API Status: published + Args: + WantChuckVacuumOn:int = 0 + Command Timeout: 10000 + Example:SetChuckVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetChuckVacuum",WantChuckVacuumOn) + + +def SetMicroLight(WantIlluminatorOn:int=""): + """ + Toggles the microscope light channel of the peripheral output board and all + cameras. Notifications: 7 + API Status: published + Args: + WantIlluminatorOn:int = 2 + Command Timeout: 5000 + Example:SetMicroLight 1 + """ + MessageServerInterface.sendSciCommand("SetMicroLight",WantIlluminatorOn) + + +def SetBeaconStatus(FlagsMode:int="", PulseWidthRed:int="", PulseWidthGreen:int="", PulseWidthYellow:int="", PulseWidthBlue:int="", PulseWidthWhite:int=""): + """ + This command controls the beacon channel of the peripheral output board. All + lights can be switched on, off, or blinking. Setting an interval to zero means, + that the corresponding light will be statically on or off. The minimum blinking + interval is 50ms. + API Status: published + Args: + FlagsMode:int = 0 + PulseWidthRed:int = 1000 + PulseWidthGreen:int = 0 + PulseWidthYellow:int = 0 + PulseWidthBlue:int = 0 + PulseWidthWhite:int = 0 + Command Timeout: 5000 + Example:SetBeaconStatus 1 1000 + """ + MessageServerInterface.sendSciCommand("SetBeaconStatus",FlagsMode,PulseWidthRed,PulseWidthGreen,PulseWidthYellow,PulseWidthBlue,PulseWidthWhite) + + +def SetOutput(Channel:int="", WantOutputOn:int="", PulseTime:int=""): + """ + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: published + Args: + Channel:int = 1 + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetOutput 4 0 + """ + MessageServerInterface.sendSciCommand("SetOutput",Channel,WantOutputOn,PulseTime) + + +def StopAllMovements(): + """ + Stops all Prober movements immediately. The response status value of any pending + movement will signify that the stop command was executed. + API Status: published + Command Timeout: 5000 + Example:StopAllMovements + """ + MessageServerInterface.sendSciCommand("StopAllMovements") + + +def InkDevice(FlagsInker:int="", PulseWidth:int=""): + """ + Inks the current device under test. The range of PulseWidth is 20ms to 2000ms. + For correct function, the inkers have to be linked to default outputs. + API Status: published + Args: + FlagsInker:int = 0 + PulseWidth:int = 50 + Command Timeout: 10000 + Example:InkDevice 1 40 + """ + MessageServerInterface.sendSciCommand("InkDevice",FlagsInker,PulseWidth) + + +def ReadProbeSetup(): + """ + Returns the current positioner configuration. The output pattern is: 1. Type + Positioner 1 2. Type Positioner 2 3. Type Positioner 3 4. Type Positioner 4 5. + Type Positioner 5 6. Axis Positioner 1 (Bit 0: XY, Bit 1: Z) 7. Axis Positioner + 2 (Bit 0: XY, Bit 1: Z) 8. Axis Positioner 3 (Bit 0: XY, Bit 1: Z) 9. Axis + Positioner 4 (Bit 0: XY, Bit 1: Z) 10. Axis Positioner 5 (Bit 0: XY, Bit 1: Z) + 11. Type Positioner 6 12. Axis Positioner 6 (Bit 0: XY, Bit 1: Z) + API Status: published + Returns: + TypePositioner1:int + TypePositioner2:int + TypePositioner3:int + TypePositioner4:int + TypePositioner5:int + AxisPositioner1:int + AxisPositioner2:int + AxisPositioner3:int + AxisPositioner4:int + AxisPositioner5:int + TypePositioner6:int + AxisPositioner6:int + Command Timeout: 5000 + Example:ReadProbeSetup + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSetup") + global ReadProbeSetup_Response + if not "ReadProbeSetup_Response" in globals(): ReadProbeSetup_Response = namedtuple("ReadProbeSetup_Response", "TypePositioner1,TypePositioner2,TypePositioner3,TypePositioner4,TypePositioner5,AxisPositioner1,AxisPositioner2,AxisPositioner3,AxisPositioner4,AxisPositioner5,TypePositioner6,AxisPositioner6") + return ReadProbeSetup_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11])) + +def ReadSystemStatus(): + """ + Returns the system options which are currently enabled at the prober. + API Status: published + Returns: + Name:str + System:str + ChuckXY:int + ChuckZ:int + ChuckTheta:int + ScopeXY:int + ScopeZ:int + EdgeSensor:int + OperationalMode:str + Turret:int + TemperatureChuck:int + AuxSiteCount:int + PlatenXY:int + PlatenZ:int + LoaderGateState:str + NucleusType:str + Command Timeout: 10000 + Example:ReadSystemStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadSystemStatus") + global ReadSystemStatus_Response + if not "ReadSystemStatus_Response" in globals(): ReadSystemStatus_Response = namedtuple("ReadSystemStatus_Response", "Name,System,ChuckXY,ChuckZ,ChuckTheta,ScopeXY,ScopeZ,EdgeSensor,OperationalMode,Turret,TemperatureChuck,AuxSiteCount,PlatenXY,PlatenZ,LoaderGateState,NucleusType") + return ReadSystemStatus_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),str(rsp[14]),str("" if len(rsp) < 16 else ' '.join(rsp[15:]))) + +def SetExternalMode(Mode:str=""): + """ + If 'R' is sent, it sets the external mode of the kernel. This disables most of + the control box functions (except the LOCAL function key). Otherwise, this + command re-enables all functions of the control box. + API Status: published + Args: + Mode:str = "L" + Command Timeout: 5000 + Example:SetExternalMode L + """ + MessageServerInterface.sendSciCommand("SetExternalMode",Mode) + + +def SetStageLock(Stage:str="", WantStageLock:int="", Application:str=""): + """ + Enables or disables the stage lock functionality. Stages which are locked can't + be moved in any way. If the joystick controller is locked, the display and the + keys are deactivated. The name of the application can be stored by using the + Application Name parameter and is shown in lock-caused error messages. + API Status: published + Args: + Stage:str = "0" + WantStageLock:int = 1 + Application:str = "" + Command Timeout: 10000 + Example:SetStageLock C 0 WaferMap + """ + MessageServerInterface.sendSciCommand("SetStageLock",Stage,WantStageLock,Application) + + +def ReadSensor(Channel:int="", Type:str=""): + """ + Returns the actual status of the specified input channel, output channel or edge + sensor. The signal table is described in the Hardware Manual. Each used IO-board + has 16 channels (max. 4 IO-boards are supported), what results in a domain of 64 + channel numbers. Beyond this range there are pseudo channels, which are used for + special purposes. Pseudo channels: + API Status: published + Args: + Channel:int = 1 + Type:str = "Input" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadSensor 11 I + """ + rsp = MessageServerInterface.sendSciCommand("ReadSensor",Channel,Type) + return int(rsp[0]) + +def GetStageLock(Stage:str=""): + """ + Reads whether stages or joystick controller are locked. + API Status: published + Args: + Stage:str = "0" + Returns: + Locks:int + Application:str + Command Timeout: 10000 + Example:GetStageLock C + """ + rsp = MessageServerInterface.sendSciCommand("GetStageLock",Stage) + global GetStageLock_Response + if not "GetStageLock_Response" in globals(): GetStageLock_Response = namedtuple("GetStageLock_Response", "Locks,Application") + return GetStageLock_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetBackSideMode(WantBackSideMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets bottomside mode. In this mode the Z axis is reverse and the + command MoveChuckLoad is not allowed. + API Status: internal + Args: + WantBackSideMode:int = 0 + Command Timeout: 5000 + Example:SetBackSideMode 1 + """ + MessageServerInterface.sendSciCommand("SetBackSideMode",WantBackSideMode) + + +def GetBackSideMode(): + """ + Returns the current side mode. + API Status: published + Returns: + IsBackSideModeOn:int + Command Timeout: 5000 + Example:GetBackSideMode + """ + rsp = MessageServerInterface.sendSciCommand("GetBackSideMode") + return int(rsp[0]) + +def SetDarkMode(WantSetDarkMode:int=""): + """ + Switches off all LEDs on the Control Box, on the positioners, and on the screen + of the Control Box and also the light of the cameras. + API Status: published + Args: + WantSetDarkMode:int = 0 + Command Timeout: 5000 + Example:SetDarkMode 1 + """ + MessageServerInterface.sendSciCommand("SetDarkMode",WantSetDarkMode) + + +def GetDarkMode(): + """ + Returns the current mode of the light sources. + API Status: published + Returns: + IsDarkMode:int + Command Timeout: 5000 + Example:GetDarkMode + """ + rsp = MessageServerInterface.sendSciCommand("GetDarkMode") + return int(rsp[0]) + +def DockChuckCamera(ConnectCamera:str="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Connect or disconnect the chuck camera to the chuck stage. The command is only + available for the Prober type PA300BEP. + API Status: internal + Args: + ConnectCamera:str = "ParkPos" + Velocity:Decimal = 100 + Command Timeout: 300000 + Example:DockChuckCamera P 75 + """ + MessageServerInterface.sendSciCommand("DockChuckCamera",ConnectCamera,Velocity) + + +def ReadCBoxStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current selected stage of the joystick controller. + API Status: internal + Returns: + Stage:str + Command Timeout: 5000 + Example:ReadCBoxStage + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxStage") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxStage(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current stage of the joystick controller. + API Status: internal + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:SetCBoxStage C + """ + MessageServerInterface.sendSciCommand("SetCBoxStage",Stage) + + +def ReadCBoxPosMonConf(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current setting of the joystick controllers position monitor for the + secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + PosRef:str + Unit:str + Command Timeout: 5000 + Example:ReadCBoxPosMonConf C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxPosMonConf",Stage) + global ReadCBoxPosMonConf_Response + if not "ReadCBoxPosMonConf_Response" in globals(): ReadCBoxPosMonConf_Response = namedtuple("ReadCBoxPosMonConf_Response", "PosRef,Unit") + return ReadCBoxPosMonConf_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetCBoxPosMonConf(Stage:str="", PosRef:str="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Configures the joystick controller position monitor for the secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + PosRef:str = "Zero" + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetCBoxPosMonConf C Z Y + """ + MessageServerInterface.sendSciCommand("SetCBoxPosMonConf",Stage,PosRef,Unit) + + +def ReadCBoxCurrSpeed(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CBoxSpeed:str + Command Timeout: 5000 + Example:ReadCBoxCurrSpeed C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxCurrSpeed",Stage) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxCurrSpeed(Stage:str="", CBoxSpeed:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CBoxSpeed:str = "Speed4" + Command Timeout: 5000 + Example:SetCBoxCurrSpeed C 3 + """ + MessageServerInterface.sendSciCommand("SetCBoxCurrSpeed",Stage,CBoxSpeed) + + +def MoveChuckAsync(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck stage to the specified X,Y position without waiting for the move + to be finished If chuck Z is in contact height or higher, the chuck will drop to + separation. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveChuckAsync 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeAsync(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the scope stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveScopeAsync 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveProbeAsync(Probe:int="", XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the probe stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAsync",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def ReadChuckStatus(): + """ + Returns the current chuck status. Every bit in the bit fields works like a + boolean value: One <1> means true/on and zero <0> means false/off. + Its counted from LSB to MSB. - _FlagsInit_: X, Y, Z, Theta - _FlagsMode_: + HasOvertravel, HasAutoZ, HasInterlock, ContactSearch, IsContactSet, + EdgeInterlock, QuietContact, IsLocked - _FlagsLimit_: XHigh, XLow, YHigh, YLow, + ZHigh, ZLow, ThetaHigh, ThetaLow - _FlagsMoving_: X, Y, Z, Theta All parameters + are provided as indirect access (e.g. first bit of M_pvecFlagsInit can be + accessed by M_pbIsInitX). + API Status: published + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsVacuumOn:int + PresetHeight:str + LoadPos:str + IsLiftDown:int + CameraConnection:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckStatus") + global ReadChuckStatus_Response + if not "ReadChuckStatus_Response" in globals(): ReadChuckStatus_Response = namedtuple("ReadChuckStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,IsVacuumOn,PresetHeight,LoadPos,IsLiftDown,CameraConnection,IsQuiet") + return ReadChuckStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),int(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),str(rsp[9]),int(rsp[10])) + +def ReadChuckPosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the current chuck stage position in X, Y and Z. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadChuckPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckPosition",Unit,PosRef,Comp) + global ReadChuckPosition_Response + if not "ReadChuckPosition_Response" in globals(): ReadChuckPosition_Response = namedtuple("ReadChuckPosition_Response", "X,Y,Z") + return ReadChuckPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadChuckHeights(Unit:str=""): + """ + Returns the current settings used for the chuck Z movement. `Contact` is the + contact-height from zero in default compensation. The other heights are relative + to this. If no contact is set, the value will be -1. + API Status: published + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + SearchGap:Decimal + Command Timeout: 5000 + Example:ReadChuckHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckHeights",Unit) + global ReadChuckHeights_Response + if not "ReadChuckHeights_Response" in globals(): ReadChuckHeights_Response = namedtuple("ReadChuckHeights_Response", "Contact,Overtravel,AlignDist,SepDist,SearchGap") + return ReadChuckHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def InitChuck(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + Machine Coordinate System: Chuck X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - _FlagsMoveRange_: + X, Y, Z, Theta All flags can be accessed by indirect members. Initializes the + chuck stage and resets current coordinate system. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 150000 + Example:InitChuck 7 0 0 + """ + MessageServerInterface.sendSciCommand("InitChuck",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveChuck(XValue:float="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck stage to the specified X,Y position. If chuck Z is in contact + height or higher, Interlock and Auto Z flags will be analyzed and stage will + behave correspondingly - can move to separation first or return an error: + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MoveChuck 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuck",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveChuckIndex(XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves the chuck stage in index steps. This command modifies Die Home Position. + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveChuckSubsite(XValue:Decimal="", YValue:Decimal="", Unit:str="", Velocity:Decimal=""): + """ + Moves the chuck stage to the specified X, Y sub-site position. Die home position + is defined by destination position of last successful MoveChuck or + MoveChuckIndex commands. MoveChuckVelocity does not touch die home position. If + you have moved chuck with MoveChuckVelocity, "MoveChuckSubsite 0 0" will move it + back to die home position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckSubsite 200 200 Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSubsite",XValue,YValue,Unit,Velocity) + + +def MoveChuckContact(Velocity:Decimal=""): + """ + Performs a movement of chuck Z axis to preset contact height or will return + error if no contact height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckContact 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckContact",Velocity) + + +def MoveChuckAlign(Velocity:Decimal=""): + """ + Moves the chuck Z axis to the align height. If no Contact height is set will + return an error. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAlign",Velocity) + + +def MoveChuckSeparation(Velocity:Decimal=""): + """ + Moves the chuck Z axis to the separation height. Returns error if no Contact + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSeparation",Velocity) + + +def MoveChuckLoad(LoadPosition:str=""): + """ + Moves the Chuck stage in X, Y, Z and Theta to the load position. + API Status: published + Args: + LoadPosition:str = "First" + Command Timeout: 60000 + Example:MoveChuckLoad 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckLoad",LoadPosition) + + +def MoveChuckZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck Z axis to the specified height. If contact is set, only moves up + to contact height will be allowed. If overtravel is enabled - up to overtravel + height. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 60000 + Example:MoveChuckZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckZ",Height,PosRef,Unit,Velocity,Comp) + + +def SearchChuckContact(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck Z axis to the specified height and sets contact. The move stops + immediately if the Contact Sensor ( Edge Sensor) is triggered. If no contact has + been found and an old one was set before the old contact will not get lost, it + will be reset. + API Status: published + Args: + Height:Decimal = 100 + PosRef:str = "Relative" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 60000 + Example:SearchChuckContact 1000 R Y 10 + """ + rsp = MessageServerInterface.sendSciCommand("SearchChuckContact",Height,PosRef,Unit,Velocity,Comp) + return Decimal(rsp[0]) + +def MoveChuckVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + Moves the chuck stage in velocity mode. The motion continues until the + StopChuckMovement command is received, or the end limit is reached. + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveChuckVelocity + + 0 100 30 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopChuckMovement(FlagsStop:int=""): + """ + Stops chuck movement for the given axis. Notifications: 31 / 32 / 5 + API Status: published + Args: + FlagsStop:int = 15 + Command Timeout: 5000 + Example:StopChuckMovement 7 + """ + MessageServerInterface.sendSciCommand("StopChuckMovement",FlagsStop) + + +def SetChuckMode(Overtravel:int="", AutoZ:int="", Interlock:int="", ContactSearch:int="", EdgeInterlock:int="", QuietContact:int=""): + """ + Mode manages the way the chuck behaves when it is in contact height. Chuck mode + is made from 6 flags and you can control all of them using this command. Every + flag can be turned on by using value 1 or turned off by using value 0. If you do + not want to change a flag - use value of 2. + API Status: published + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + ContactSearch:int = 2 + EdgeInterlock:int = 2 + QuietContact:int = 2 + Command Timeout: 5000 + Example:SetChuckMode 2 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetChuckMode",Overtravel,AutoZ,Interlock,ContactSearch,EdgeInterlock,QuietContact) + + +def SetChuckHome(Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets wafer and die home position, which can be used later as coordinate system + for movements. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetChuckHome",Mode,Unit,XValue,YValue) + + +def SetChuckIndex(XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the wafer index size. Normally the size of one die. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetChuckIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetChuckIndex",XValue,YValue,Unit) + + +def SetChuckHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation. A predefined contact search gap is able to write. No data + in the optional parameters sets contact height at current position. If Mode is + '0', contact height can be set at current position. The levels O, A, S and T + support no Mode '0'. If Mode is 'V' and no value for height is specified - + default 0 will be used, what potentially can be not what you expect. If Mode is + 'R', contact height can be invalidated. The levels O, A, S and T support no Mode + 'R'. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHeight C V Y 5000. + """ + MessageServerInterface.sendSciCommand("SetChuckHeight",PresetHeight,Mode,Unit,Value) + + +def ReadChuckIndex(Unit:str=""): + """ + The command gets the current die size which is stored in the kernel. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadChuckIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckIndex",Unit) + global ReadChuckIndex_Response + if not "ReadChuckIndex_Response" in globals(): ReadChuckIndex_Response = namedtuple("ReadChuckIndex_Response", "IndexX,IndexY") + return ReadChuckIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveChuckTransfer(): + """ + Moves the Chuck to the Transfer Position. If the movement starts in Load + Position (where it's possible to pull out the chuck) the handling of the Add On + Platen or the Pin Chuck is integrated. + API Status: published + Command Timeout: 90000 + Example:MoveChuckTransfer + """ + MessageServerInterface.sendSciCommand("MoveChuckTransfer") + + +def MoveChuckLift(SetLift:int=""): + """ + Moves the chuck to the upper (0) or lower = lifted (1) position. This initiates + motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveChuckLift 1 + """ + MessageServerInterface.sendSciCommand("MoveChuckLift",SetLift) + + +def SetChuckThermoScale(ScaleX:Decimal="", ScaleY:Decimal=""): + """ + Thermo drifts of the wafer will be compensated. The compensation is not + persistent, (power off - this compensation is deleted). The algorithm works as + an additional one. This is for an iterative usage, so: 1. `ResetProber H` 2. + `SetChuckThermoScale 1.5 1.5` 3. `SetChuckThermoScale 1.5 1.5` will result in a + scale of 2.25 in both directions. The thermal scale can also be reset using the + command 'SetChcukThermoValue 20 C' + API Status: published + Args: + ScaleX:Decimal = 1 + ScaleY:Decimal = 1 + Command Timeout: 5000 + Example:SetChuckThermoScale 1.000005 1.0000045 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoScale",ScaleX,ScaleY) + + +def ReadChuckThermoScale(): + """ + Read the linear scaling value of the chuck. + API Status: published + Returns: + ScaleX:Decimal + ScaleY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoScale + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoScale") + global ReadChuckThermoScale_Response + if not "ReadChuckThermoScale_Response" in globals(): ReadChuckThermoScale_Response = namedtuple("ReadChuckThermoScale_Response", "ScaleX,ScaleY") + return ReadChuckThermoScale_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetChuckThermoValue(Temperature:Decimal="", Unit:str="", ExpCoeffX:Decimal="", ExpCoeffY:Decimal=""): + """ + Set a temperature and optional the expansion coefficient. The temperature for + normal level is 20 degree. The scaling factor at this temperature is 1.0. If you + set the temperature directly the controller calculates the stage difference in + the coordinate system. For the calculation use the set coefficient of expansion + from the controller. The default coefficient of expansion is based on silicon: + 2.33E-06 1/K. + API Status: published + Args: + Temperature:Decimal = 0 + Unit:str = "Celsius" + ExpCoeffX:Decimal = 0 + ExpCoeffY:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckThermoValue 250 C 2.43 2.32 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoValue",Temperature,Unit,ExpCoeffX,ExpCoeffY) + + +def ReadChuckThermoValue(Unit:str=""): + """ + Read the current temperature (either set or calculated) for the thermal scaling. + With SetChuckThermoScale in use, the value will be calculated by the current + scale and the expansion factor of silicium. The temperature that is read with + this command is not identical to the current chuck temperature. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + Temperature:Decimal + ExpCoeffX:Decimal + ExpCoeffY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoValue C + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoValue",Unit) + global ReadChuckThermoValue_Response + if not "ReadChuckThermoValue_Response" in globals(): ReadChuckThermoValue_Response = namedtuple("ReadChuckThermoValue_Response", "Temperature,ExpCoeffX,ExpCoeffY") + return ReadChuckThermoValue_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetChuckTableID(TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ChuckTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetChuckTableID ChuckTable + """ + rsp = MessageServerInterface.sendSciCommand("GetChuckTableID",TableName) + return int(rsp[0]) + +def MoveChuckTablePoint(TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move the chuck to the next stored table site. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckTablePoint 3 10 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckTablePoint",TableID,PointID,Velocity) + + +def ReadChuckTablePoint(TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the table site information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadChuckTablePoint 10 250 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTablePoint",TableID,PointID,Unit) + global ReadChuckTablePoint_Response + if not "ReadChuckTablePoint_Response" in globals(): ReadChuckTablePoint_Response = namedtuple("ReadChuckTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadChuckTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetChuckTablePoint(TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the chuck table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetChuckTablePoint 10 12000.0 2344.0 Y F + """ + rsp = MessageServerInterface.sendSciCommand("SetChuckTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearChuckTablePoint(TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of chuck table site points in the in the Kernel. If Start + Point is -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearChuckTablePoint 5 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearChuckTablePoint",TableID,StartPoint,EndPoint) + global ClearChuckTablePoint_Response + if not "ClearChuckTablePoint_Response" in globals(): ClearChuckTablePoint_Response = namedtuple("ClearChuckTablePoint_Response", "ClearNumber,ValidNumber") + return ClearChuckTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def AttachAmbientWafer(MoveTimeMs:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is moved to slowly attach a wafer that is at ambient temperature while + the chuck is hot. The command acts similar to MoveChuckTransfer when moving + out of Load 2 but will use a much slower Z velocity. This is only supported + for BnR-machines (CM300 and Summit200) at the moment. + API Status: internal + Args: + MoveTimeMs:Decimal = 30000 + Command Timeout: 300000 + Example:AttachAmbientWafer + """ + MessageServerInterface.sendSciCommand("AttachAmbientWafer",MoveTimeMs) + + +def ReadThetaStatus(): + """ + Returns the actual status of the chuck Theta axis. + API Status: published + Returns: + IsInit:int + FlagsLimit:int + IsMoving:int + Command Timeout: 5000 + Example:ReadThetaStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaStatus") + global ReadThetaStatus_Response + if not "ReadThetaStatus_Response" in globals(): ReadThetaStatus_Response = namedtuple("ReadThetaStatus_Response", "IsInit,FlagsLimit,IsMoving") + return ReadThetaStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadThetaPosition(Unit:str="", PosRef:str=""): + """ + Returns the actual Theta position. + API Status: published + Args: + Unit:str = "Degrees" + PosRef:str = "Home" + Returns: + Position:Decimal + Command Timeout: 5000 + Example:ReadThetaPosition D Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaPosition",Unit,PosRef) + return Decimal(rsp[0]) + +def InitTheta(FlagsDoPlus:int="", FlagsMoveRange:int=""): + """ + Performs an initialization move and resets the coordinate system of the Theta + axis. + API Status: published + Args: + FlagsDoPlus:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitTheta 0 0 + """ + MessageServerInterface.sendSciCommand("InitTheta",FlagsDoPlus,FlagsMoveRange) + + +def MoveTheta(Position:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal=""): + """ + Moves the chuck Theta axis to the specified position. The positive direction is + counter-clockwise. + API Status: published + Args: + Position:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Degrees" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveTheta 1000. R E + """ + MessageServerInterface.sendSciCommand("MoveTheta",Position,PosRef,Unit,Velocity) + + +def MoveThetaVelocity(Polarity:str="", Velocity:Decimal=""): + """ + Moves the chuck Theta axis in velocity mode. The positive direction is counter- + clockwise. The motion continues until the StopThetaMovement command is received, + or the end limit (error condition) is reached. This command is mostly used for + joystick movements that do not have a target destination. + API Status: published + Args: + Polarity:str = "Fixed" + Velocity:Decimal = 0 + Command Timeout: 240000 + Example:MoveThetaVelocity + 67 + """ + MessageServerInterface.sendSciCommand("MoveThetaVelocity",Polarity,Velocity) + + +def StopThetaMovement(): + """ + Stops any type (velocity, position etc.) of chuck Theta axis movement. This is + treated as a smooth stop rather than an emergency stop. + API Status: published + Command Timeout: 5000 + Example:StopThetaMovement + """ + MessageServerInterface.sendSciCommand("StopThetaMovement") + + +def SetThetaHome(Mode:str="", Unit:str="", Position:Decimal=""): + """ + Sets the chuck Theta position to home. This position is usable as reference + position for other commands. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Degrees" + Position:Decimal = 0 + Command Timeout: 5000 + Example:SetThetaHome 0 + """ + MessageServerInterface.sendSciCommand("SetThetaHome",Mode,Unit,Position) + + +def ScanChuckZ(ZDistance:Decimal="", TriggerEveryNthCycle:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts moving the chuck from the current position with Velocity [%] over + ZDistance (sign is important, as a negative sign will move chuck down during + scan) - Predefined camera trigger pulses (TTL active high for at least 5us) will + be sent during the scan every passed number of BnR cyclics (800us per cyclic) + until the ZDistance has been reached. Command returns number of positions and + all compensated Z Positions from Zero, where the trigger was sent. + API Status: internal + Args: + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 3 + Velocity:Decimal = 10 + Returns: + NumberOfPositions:int + TriggerPositions:str + Command Timeout: 60000 + Example:ScanChuckZ 300 3 1.5 + """ + rsp = MessageServerInterface.sendSciCommand("ScanChuckZ",ZDistance,TriggerEveryNthCycle,Velocity) + global ScanChuckZ_Response + if not "ScanChuckZ_Response" in globals(): ScanChuckZ_Response = namedtuple("ScanChuckZ_Response", "NumberOfPositions,TriggerPositions") + return ScanChuckZ_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def MoveChuckZSafe(): + """ + Moves the chuck Z axis to a z height considered safe. This is either the lower + Z-Fence or the kernel setup item Chuck:SafeTransferHeight (which ever is larger) + API Status: published + Command Timeout: 60000 + Example:MoveChuckZSafe + """ + MessageServerInterface.sendSciCommand("MoveChuckZSafe") + + +def SetPlatenMode(Overtravel:int="", AutoZ:int="", Interlock:int="", AutoZFollow:int="", AutoQuiet:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The mode manages the way the platen behaves when it is in contact height. Platen + mode is made up from 5 flags and the user can control all of them by using this + command. Every flag can be turned on by setting value 1 or turned off by setting + value 0. If no change for a flag is wanted, use the value of 2. + API Status: internal + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Command Timeout: 5000 + Example:SetPlatenMode 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetPlatenMode",Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + + +def MovePlatenLift(SetLift:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen to the high (0) or low = lifted (1) position. This initiates + motion; the actual movement may take some seconds. + API Status: internal + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MovePlatenLift 1 + """ + MessageServerInterface.sendSciCommand("MovePlatenLift",SetLift) + + +def SearchPlatenContact(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Searches contact height using the edge sensor using a z movement of the platen + stage + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + CompLayer:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("SearchPlatenContact",Height,PosRef,Unit,Velocity,CompLayer) + return Decimal(rsp[0]) + +def ReadPlatenStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current platen status. + API Status: internal + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + PresetHeight:str + IsLiftDown:int + Command Timeout: 10000 + Example:ReadPlatenStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenStatus") + global ReadPlatenStatus_Response + if not "ReadPlatenStatus_Response" in globals(): ReadPlatenStatus_Response = namedtuple("ReadPlatenStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,PresetHeight,IsLiftDown") + return ReadPlatenStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ReadPlatenPosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the platens X, Y and Z axes. The default + compensation is the currently selected compensation for the stage. + API Status: internal + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadPlatenPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenPosition",Unit,PosRef,Comp) + global ReadPlatenPosition_Response + if not "ReadPlatenPosition_Response" in globals(): ReadPlatenPosition_Response = namedtuple("ReadPlatenPosition_Response", "X,Y,Z") + return ReadPlatenPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadPlatenHeights(Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual settings for the probe Z movement. + API Status: internal + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadPlatenHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenHeights",Unit) + global ReadPlatenHeights_Response + if not "ReadPlatenHeights_Response" in globals(): ReadPlatenHeights_Response = namedtuple("ReadPlatenHeights_Response", "Contact,Overtravel,AlignDist,SepDist") + return ReadPlatenHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def InitPlaten(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the platens X, Y and Z axes. Currently the initialization in + negative direction and the move range scan are not supported. + API Status: internal + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitPlaten 4 + """ + MessageServerInterface.sendSciCommand("InitPlaten",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MovePlatenZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the specified height. If contact is set, only moves + up to contact height will be allowed. If overtravel is enabled - up to + overtravel height. + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MovePlatenZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MovePlatenZ",Height,PosRef,Unit,Velocity,Comp) + + +def MovePlatenContact(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a movement of platen Z axis to preset contact height or returns an + error, if no contact height is set. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenContact 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenContact",Velocity) + + +def MovePlatenAlign(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the align height. If no contact height is set, the + command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenAlign 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenAlign",Velocity) + + +def MovePlatenSeparation(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the separation height. If no contact height is set, + the command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenSeparation 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenSeparation",Velocity) + + +def MovePlatenVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen stage in velocity mode. The motion continues until the + StopPlatenMovement command is received, or the software fence is reached. + API Status: internal + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 240000 + Example:MovePlatenVelocity + + 0 67 50 0 + """ + MessageServerInterface.sendSciCommand("MovePlatenVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopPlatenMovement(FlagsStop:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the movement of a set of platen axes immediately. + API Status: internal + Args: + FlagsStop:int = 7 + Command Timeout: 10000 + Example:StopPlatenMovement 4 + """ + MessageServerInterface.sendSciCommand("StopPlatenMovement",FlagsStop) + + +def SetPlatenHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation height. A command without data sets contact height at + current position. + API Status: internal + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 10000 + Example:SetPlatenHeight C V Y 5000 + """ + MessageServerInterface.sendSciCommand("SetPlatenHeight",PresetHeight,Mode,Unit,Value) + + +def ReadManualPlatenState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the current status of the manual platen. THis is only supported for + Nucleus and Summit200. + API Status: internal + Returns: + IsUp:int + IsDown:int + IsSafe:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadManualPlatenState") + global ReadManualPlatenState_Response + if not "ReadManualPlatenState_Response" in globals(): ReadManualPlatenState_Response = namedtuple("ReadManualPlatenState_Response", "IsUp,IsDown,IsSafe") + return ReadManualPlatenState_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadScopeStatus(): + """ + Returns the current scope status. + API Status: published + Returns: + FlagsInit:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsScopeLiftUp:int + PresetHeight:str + IsScopeLight:int + FlagsMode:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadScopeStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeStatus") + global ReadScopeStatus_Response + if not "ReadScopeStatus_Response" in globals(): ReadScopeStatus_Response = namedtuple("ReadScopeStatus_Response", "FlagsInit,FlagsLimit,FlagsMoving,Comp,IsScopeLiftUp,PresetHeight,IsScopeLight,FlagsMode,IsQuiet") + return ReadScopeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),str(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def ReadScopePosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual scope stage position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadScopePosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopePosition",Unit,PosRef,Comp) + global ReadScopePosition_Response + if not "ReadScopePosition_Response" in globals(): ReadScopePosition_Response = namedtuple("ReadScopePosition_Response", "X,Y,Z") + return ReadScopePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeHeights(Unit:str=""): + """ + Returns the actual settings of the focus height, align gap, and separation gap + for the scope Z axis. + API Status: published + Args: + Unit:str = "Microns" + Returns: + FocusHeight:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadScopeHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeHeights",Unit) + global ReadScopeHeights_Response + if not "ReadScopeHeights_Response" in globals(): ReadScopeHeights_Response = namedtuple("ReadScopeHeights_Response", "FocusHeight,AlignDist,SepDist") + return ReadScopeHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def InitScope(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + Initializes the microscope stage in X, Y and Z. The Axis default is all axes and + the Direction default is XY in minus and Z in plus. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 240000 + Example:InitScope 3 0 0 + """ + MessageServerInterface.sendSciCommand("InitScope",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveScope(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 70000 + Example:MoveScope 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScope",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeIndex(XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves the microscope stage in index steps. If no PositionReference byte is + passed the scope will step relative to the wafer home position. ('R' means the + step relative to current position). + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveScopeZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the microscope Z axis to the specified height. Default velocity is 100%. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 120000 + Example:MoveScopeZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeZ",Height,PosRef,Unit,Velocity,Comp) + + +def SetScopeMode(QuietMode:int="", FollowMode:int=""): + """ + Scope mode is made up of two flags which can be controlled using this command. + Each flag can be turned on by using value 1 or turned off by using value 0. If + you do not want to change a flag, use value of 2. + API Status: published + Args: + QuietMode:int = 2 + FollowMode:int = 2 + Command Timeout: 5000 + Example:SetScopeMode 2 2 + """ + MessageServerInterface.sendSciCommand("SetScopeMode",QuietMode,FollowMode) + + +def MoveScopeVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + Moves the microscope stage in velocity mode. The motion continues until the + StopScopeMovement command is received, or the end limit (error condition) is + reached. Axes parameter: '+' move this axis in plus direction '-' move this axis + in minus direction '0' Do not change this axis + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveScopeVelocity + + 0 67 100 0 + """ + MessageServerInterface.sendSciCommand("MoveScopeVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopScopeMovement(FlagsStop:int=""): + """ + Stops scope movement for the given axis. A smooth stop is executed, no emergency + stop. + API Status: published + Args: + FlagsStop:int = 7 + Command Timeout: 5000 + Example:StopScopeMovement 7 + """ + MessageServerInterface.sendSciCommand("StopScopeMovement",FlagsStop) + + +def SetScopeHome(Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the scope Home position in X and Y. It identifies the scope coordinate + system for later movements. Usually this position is identical to the die home + location. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHome",Mode,Unit,XValue,YValue) + + +def SetScopeIndex(XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the microscope index size. Normally set in relation to the wafer index + size. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetScopeIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetScopeIndex",XValue,YValue,Unit) + + +def SetScopeHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + This command defines scope focus height and the corresponding gaps for alignment + or separation. No data sets focus height at current position. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHeight F 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHeight",PresetHeight,Mode,Unit,Value) + + +def ReadScopeIndex(Unit:str=""): + """ + Returns the actual scope stage index values in X and Y. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadScopeIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeIndex",Unit) + global ReadScopeIndex_Response + if not "ReadScopeIndex_Response" in globals(): ReadScopeIndex_Response = namedtuple("ReadScopeIndex_Response", "IndexX,IndexY") + return ReadScopeIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveScopeFocus(Velocity:Decimal=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 25000 + Example:MoveScopeFocus 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeFocus",Velocity) + + +def MoveScopeAlign(Velocity:Decimal=""): + """ + Moves the Scope Z axis to the alignment height. If no focus height is set an + error will bereturned. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 10000 + Example:MoveScopeAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAlign",Velocity) + + +def MoveScopeSeparation(Velocity:Decimal=""): + """ + Moves the scope Z axis to the separation height. Returns an error if no focus + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveScopeSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeSeparation",Velocity) + + +def MoveScopeLift(SetLift:int=""): + """ + Moves the microscope lift to the lower (0) or upper = lifted (1) position. This + initiates the motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveScopeLift 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeLift",SetLift) + + +def ReadTurretStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current status of the motorized turret. + API Status: internal + Returns: + IsMoving:int + Command Timeout: 5000 + Example:ReadTurretStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTurretStatus") + return int(rsp[0]) + +def SelectLens(Lens:int=""): + """ + Parfocality and para-centricity are adjusted according to the stored values. + This can be used with manual turrets to compensate for XYZ differences between + lenses. + API Status: published + Args: + Lens:int = 1 + Command Timeout: 30000 + Example:SelectLens 1 + """ + MessageServerInterface.sendSciCommand("SelectLens",Lens) + + +def GetScopeTable(TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ScopeTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetScopeTable ScopeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeTable",TableName) + return int(rsp[0]) + +def MoveScopeTablePoint(TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeTablePoint 10 5 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeTablePoint",TableID,PointID,Velocity) + + +def ReadScopeTablePoint(TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the scope table site Information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadScopeTablePoint 2 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTablePoint",TableID,PointID,Unit) + global ReadScopeTablePoint_Response + if not "ReadScopeTablePoint_Response" in globals(): ReadScopeTablePoint_Response = namedtuple("ReadScopeTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadScopeTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def ReadCurrentLens(): + """ + Returns the number of the current microscope lens. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:ReadCurrentLens + """ + rsp = MessageServerInterface.sendSciCommand("ReadCurrentLens") + return int(rsp[0]) + +def SetScopeTablePoint(TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the scope table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetScopeTablePoint 10 10 8992.5 7883.0 Y H + """ + rsp = MessageServerInterface.sendSciCommand("SetScopeTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearScopeTablePoint(TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of scope table site points in the Kernel. If Start Point is + -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearScopeTablePoint 2 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearScopeTablePoint",TableID,StartPoint,EndPoint) + global ClearScopeTablePoint_Response + if not "ClearScopeTablePoint_Response" in globals(): ClearScopeTablePoint_Response = namedtuple("ClearScopeTablePoint_Response", "ClearNumber,ValidNumber") + return ClearScopeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ReadScopeSiloCount(): + """ + Returns the number of silos in the scope fence. Will be zero if no silos are + configured. + API Status: published + Returns: + Count:int + Command Timeout: 5000 + Example:ReadScopeSiloCount + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSiloCount") + return int(rsp[0]) + +def ReadProbeStatus(Probe:int=""): + """ + Returns the current positioner's status. + API Status: published + Args: + Probe:int = 1 + Returns: + ProbeEcho:int + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + Side:str + PresetHeight:str + IsLiftUp:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadProbeStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeStatus",Probe) + global ReadProbeStatus_Response + if not "ReadProbeStatus_Response" in globals(): ReadProbeStatus_Response = namedtuple("ReadProbeStatus_Response", "ProbeEcho,FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,Side,PresetHeight,IsLiftUp,IsQuiet") + return ReadProbeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadProbePosition(Probe:int="", Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual positioner's position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + ProbeEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadProbePosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbePosition",Probe,Unit,PosRef,Comp) + global ReadProbePosition_Response + if not "ReadProbePosition_Response" in globals(): ReadProbePosition_Response = namedtuple("ReadProbePosition_Response", "ProbeEcho,X,Y,Z") + return ReadProbePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadProbeHeights(Probe:int="", Unit:str=""): + """ + Returns the actual settings for the probe Z movement. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadProbeHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeHeights",Probe,Unit) + global ReadProbeHeights_Response + if not "ReadProbeHeights_Response" in globals(): ReadProbeHeights_Response = namedtuple("ReadProbeHeights_Response", "ProbeEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadProbeHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def OrientProbe(Probe:int="", Side:str=""): + """ + Defines the orientation of the positioner's coordinate system and turns the + Y-axis of the probe coordinate system. + API Status: published + Args: + Probe:int = 1 + Side:str = "Left" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:OrientProbe 1 R + """ + rsp = MessageServerInterface.sendSciCommand("OrientProbe",Probe,Side) + return int(rsp[0]) + +def InitProbe(Probe:int="", FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int="", FlagsInitInPlace:int=""): + """ + Performs an initialization move and resets the coordinate system of the given + positioner. + API Status: published + Args: + Probe:int = 1 + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + FlagsInitInPlace:int = 0 + Returns: + ProbeEcho:int + Command Timeout: 120000 + Example:InitProbe 1 7 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("InitProbe",Probe,FlagsInit,FlagsDirection,FlagsMoveRange,FlagsInitInPlace) + return int(rsp[0]) + +def MoveProbe(Probe:int="", XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbe 1 1000. 1000. R Y 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbe",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeIndex(Probe:int="", XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeIndex 1 1 1 R 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeIndex",Probe,XSteps,YSteps,PosRef,Velocity) + return int(rsp[0]) + +def MoveProbeContact(Probe:int="", Velocity:Decimal=""): + """ + Moves the given ProbeHeads Z axis to the preset contact height. If no contact + height is set, the kernel will return a 'Contact height not set' error. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeContact 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeContact",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeAlign(Probe:int="", Velocity:Decimal=""): + """ + Moves the given ProbeHeads Z axis to the align height. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeAlign 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAlign",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeSeparation(Probe:int="", Velocity:Decimal=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeSeparation 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeSeparation",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeZ(Probe:int="", Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves a given ProbeHeads Z axis to a defined Z height. + API Status: published + Args: + Probe:int = 1 + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeZ 1 1000. R Y 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeZ",Probe,Height,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeLift(Probe:int="", SetLift:int=""): + """ + Moves the positioner to the lower (0) or upper = lifted (1) position. The + command initiates the motion only, the whole movement may take some seconds. + API Status: published + Args: + Probe:int = 1 + SetLift:int = 1 + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:MoveProbeLift 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeLift",Probe,SetLift) + return int(rsp[0]) + +def MoveProbeVelocity(Probe:int="", PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + '+' Move this axis into plus direction '-' Move this axis into minus direction + '0' Do not change this axis + API Status: published + Args: + Probe:int = 1 + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeVelocity 1 + + Z 67 100 0 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeVelocity",Probe,PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + return int(rsp[0]) + +def StopProbeMovement(Probe:int="", FlagsStop:int=""): + """ + Stops positioner movement for the given axes immediately. A smooth stop is + performed. + API Status: published + Args: + Probe:int = 1 + FlagsStop:int = 7 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:StopProbeMovement 1 7 + """ + rsp = MessageServerInterface.sendSciCommand("StopProbeMovement",Probe,FlagsStop) + return int(rsp[0]) + +def SetProbeMode(Probe:int="", Overtravel:int="", AutoZ:int="", Interlock:int="", AutoZFollow:int="", AutoQuiet:int=""): + """ + The mode manages the way the chuck behaves when it is in contact height. + Positioner mode is made up from 5 flags and the user can control all of them by + using this command. Every flag can be turned on by setting value 1, or turned + off by setting value 0. Use the value 2 if no change for a flag is needed. + API Status: published + Args: + Probe:int = 1 + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeMode 1 2 2 2 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeMode",Probe,Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + return int(rsp[0]) + +def SetProbeHome(Probe:int="", Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the positioner's Home position in X and Y. This position identifies the + probe coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + Probe:int = 1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHome",Probe,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetProbeIndex(Probe:int="", XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the positioner's index size or the location of the reference die relative + to the home die. + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeIndex",Probe,XValue,YValue,Unit) + return int(rsp[0]) + +def SetProbeHeight(Probe:int="", PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align, load and separation height. No data sets contact height at current + position. + API Status: published + Args: + Probe:int = 1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHeight",Probe,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadProbeIndex(Probe:int="", Unit:str=""): + """ + Returns the current positioner's wafer index values or the current positioner's + index positions for X and Y. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadProbeIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeIndex",Probe,Unit) + global ReadProbeIndex_Response + if not "ReadProbeIndex_Response" in globals(): ReadProbeIndex_Response = namedtuple("ReadProbeIndex_Response", "ProbeEcho,IndexX,IndexY") + return ReadProbeIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetProbeLED(Probe:int="", NewLEDState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the positioner LED On or Off. + API Status: internal + Args: + Probe:int = 1 + NewLEDState:int = 0 + Returns: + ProbeEcho:int + LEDState:int + Command Timeout: 5000 + Example:SetProbeLED 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeLED",Probe,NewLEDState) + global SetProbeLED_Response + if not "SetProbeLED_Response" in globals(): SetProbeLED_Response = namedtuple("SetProbeLED_Response", "ProbeEcho,LEDState") + return SetProbeLED_Response(int(rsp[0]),int(rsp[1])) + +def GetProbeTableID(Probe:int="", TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the ID of a stored probe table or creates a new table. The ID is unique + for the name and the probe. The table itself has a string name. This name is not + case sensitive. The command has to be used before all other table commands can + be used. Access to tables is possible only with an ID Number (name dependent). + API Status: internal + Args: + Probe:int = 1 + TableName:str = "ProbeTable" + Returns: + ProbeEcho:int + TableID:int + Command Timeout: 5000 + Example:GetProbeTableID 1 ProbeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetProbeTableID",Probe,TableName) + global GetProbeTableID_Response + if not "GetProbeTableID_Response" in globals(): GetProbeTableID_Response = namedtuple("GetProbeTableID_Response", "ProbeEcho,TableID") + return GetProbeTableID_Response(int(rsp[0]),int(rsp[1])) + +def MoveProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: internal + Args: + Probe:int = 1 + TableID:int = 1 + PointID:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeTablePoint 3 14 10 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeTablePoint",Probe,TableID,PointID,Velocity) + return int(rsp[0]) + +def ReadProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the data from a point of a stored table in the Kernel. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadProbeTablePoint 2 4 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTablePoint",Probe,TableID,PointID,Unit) + global ReadProbeTablePoint_Response + if not "ReadProbeTablePoint_Response" in globals(): ReadProbeTablePoint_Response = namedtuple("ReadProbeTablePoint_Response", "ProbeEcho,CoordX,CoordY,CoordSystem") + return ReadProbeTablePoint_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets one point of a ProbeHeads table inside the Kernel. If there is still a + point with this index loaded, the Kernel returns an error. Number of positions + and number of tables are dependet on the internal memory. All positions are + stored persistent, that means after switching power on or off the positions are + still available. The table starts with point number 1 and ends with the ID 16. + The table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ProbeEcho:int + ValidPoint:int + Command Timeout: 5000 + Example:SetProbeTablePoint 3 12 10 8992.5 7883.0 Y Z M + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeTablePoint",Probe,TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + global SetProbeTablePoint_Response + if not "SetProbeTablePoint_Response" in globals(): SetProbeTablePoint_Response = namedtuple("SetProbeTablePoint_Response", "ProbeEcho,ValidPoint") + return SetProbeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ClearProbeTablePoint(Probe:int="", TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of ProbeHead table site points in the Kernel. If StartPoint + is a negative value, the whole table will be deleted. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ProbeEcho:int + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearProbeTablePoint 3 4 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearProbeTablePoint",Probe,TableID,StartPoint,EndPoint) + global ClearProbeTablePoint_Response + if not "ClearProbeTablePoint_Response" in globals(): ClearProbeTablePoint_Response = namedtuple("ClearProbeTablePoint_Response", "ProbeEcho,ClearNumber,ValidNumber") + return ClearProbeTablePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def MoveScopeSilo(Index:int=""): + """ + Move the scope to the reference position of the given silo. The reference + position should be - if not defined otherwise - 200 um above the safe z-height + in the center of the scope. + API Status: published + Args: + Index:int = 1 + Command Timeout: 70000 + Example:MoveScopeSilo 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeSilo",Index) + + +def SetScopeSiloReference(Index:int="", X:Decimal="", Y:Decimal="", Z:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the reference position of a silo. The next time the scope moves to this + silo, it woll go to this position. The Referenceposition must be inside the silo + in xy and above the lower Z-Fence of the silo. Setting the reference position + directly on the fence in x, y or z typically leads to errors. Try to keep a + safety margin. + API Status: internal + Args: + Index:int = 1 + X:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeSiloReference 1 1000 2000 3000 + """ + MessageServerInterface.sendSciCommand("SetScopeSiloReference",Index,X,Y,Z) + + +def AlignChuckTheta(XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a chuck Theta axis rotation to align the wafer to the chuck + X,Y movements. It can be used to perform a two point alignment with + P1(X1,Y1) and P2(X2,Y2) as two points on a wafer street line. The units of + the distances are not important - but both distances should use the same unit. + If one or both distances are zero, the command does not return an error and + instead ignore this alignment + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignChuckTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignChuckTheta",XDistance,YDistance,PosRef) + + +def AlignScopeTheta(XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a virtual rotation of the scope coordinate system to align + the scope to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of X and Y distances: + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignScopeTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignScopeTheta",XDistance,YDistance,PosRef) + + +def AlignProbeTheta(Probe:int="", XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a rotation of the coordinate system of given probe to align + the probe to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of Y and Y distances: + API Status: published + Args: + Probe:int = 1 + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:AlignProbeTheta 1 10000 10 R + """ + rsp = MessageServerInterface.sendSciCommand("AlignProbeTheta",Probe,XDistance,YDistance,PosRef) + return int(rsp[0]) + +def AlignCardTheta(Angle:Decimal="", Unit:str="", PosRef:str=""): + """ + This command causes a rotation of the chuck coordinate system to align the chuck + X, Y axis to the probecard. The polarity of the data determines a left or a + right rotation of the chuck coordinate system. + API Status: published + Args: + Angle:Decimal = 0 + Unit:str = "Degrees" + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignCardTheta 2.5 D R + """ + MessageServerInterface.sendSciCommand("AlignCardTheta",Angle,Unit,PosRef) + + +def ReadCardTheta(Unit:str=""): + """ + Returns the angle between the chuck-coordinate-system and the probecard- + coordinate-system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadCardTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadCardTheta",Unit) + return Decimal(rsp[0]) + +def ReadChuckTheta(Unit:str=""): + """ + Returns the current chuck alignment angle which is identical to the current + value of theta rotation. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadChuckTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTheta",Unit) + return Decimal(rsp[0]) + +def ReadScopeTheta(Unit:str=""): + """ + Returns the scope's alignment angle, which is the angle between the chuck + coordinate system and the scope coordinate system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadScopeTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTheta",Unit) + return Decimal(rsp[0]) + +def ReadProbeTheta(Probe:int="", Unit:str=""): + """ + Returns the actual positioner's alignment angle, which is the angle between the + chuck coordinate system and the positioner coordinate system. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Degrees" + Returns: + ProbeEcho:int + Angle:Decimal + Command Timeout: 5000 + Example:ReadProbeTheta 1 D + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTheta",Probe,Unit) + global ReadProbeTheta_Response + if not "ReadProbeTheta_Response" in globals(): ReadProbeTheta_Response = namedtuple("ReadProbeTheta_Response", "ProbeEcho,Angle") + return ReadProbeTheta_Response(int(rsp[0]),Decimal(rsp[1])) + +def ReadJoystickSpeeds(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the preset speeds, which are used by the joystick controller for moving a + single stage. The speeds can be read for XY, for Z and for Theta axis + separately. Jog timing and index timing are the times, the joystick controller + waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "X" + Returns: + JogTime:Decimal + Speed2:Decimal + Speed3:Decimal + Speed4:Decimal + IndexTime:Decimal + Command Timeout: 5000 + Example:ReadJoystickSpeeds S Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeeds",Stage,Axis) + global ReadJoystickSpeeds_Response + if not "ReadJoystickSpeeds_Response" in globals(): ReadJoystickSpeeds_Response = namedtuple("ReadJoystickSpeeds_Response", "JogTime,Speed2,Speed3,Speed4,IndexTime") + return ReadJoystickSpeeds_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetJoystickSpeeds(Stage:str="", JogTime:Decimal="", Speed2:Decimal="", Speed3:Decimal="", Speed4:Decimal="", IndexTime:Decimal="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the preset speeds, which are used by the joystick controller for moving a + single stage. After setting, the speeds can be selected by pressing the Speed n + buttons at the controller. The speeds must be set separately for XY, for Z and + for Theta axis. Jog timing and index timing are the times, the joystick + controller waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + JogTime:Decimal = 0 + Speed2:Decimal = 0 + Speed3:Decimal = 0 + Speed4:Decimal = 0 + IndexTime:Decimal = 0 + Axis:str = "X" + Command Timeout: 5000 + Example:SetJoystickSpeeds S 10 20 30 40 50 Z + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeeds",Stage,JogTime,Speed2,Speed3,Speed4,IndexTime,Axis) + + +def SetLoaderGate(Open:int=""): + """ + Opens or closes the loader gate. Automatic handling systems can load wafers to + the chuck through the gate. + API Status: published + Args: + Open:int = 0 + Command Timeout: 5000 + Example:SetLoaderGate 0 + """ + MessageServerInterface.sendSciCommand("SetLoaderGate",Open) + + +def ReadWaferStatus(): + """ + Returns whether the system detected a wafer. This feature can be used if the + probe station is equipped with a vacuum sensor and while vacuum is activated. + API Status: published + Returns: + SensedByVac:str + Command Timeout: 5000 + Example:ReadWaferStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadWaferStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadContactCount(Stage:str=""): + """ + Returns the number of times this stage moved to contact since the last time the + counter was reset. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Count:int + Command Timeout: 5000 + Example:ReadContactCount C + """ + rsp = MessageServerInterface.sendSciCommand("ReadContactCount",Stage) + return int(rsp[0]) + +def ResetContactCount(Stage:str=""): + """ + Resets the contact counter for the specified stage to zero. Notifications: 23 + API Status: published + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:ResetContactCount C + """ + MessageServerInterface.sendSciCommand("ResetContactCount",Stage) + + +def SetManualMode(Enable:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command enables the manual mode on Elite/Summit/S300 systems. This mode + will allow to move the chuck using the knobs. + API Status: internal + Args: + Enable:int = 1 + Command Timeout: 10000 + Example:SetManualMode 1 + """ + MessageServerInterface.sendSciCommand("SetManualMode",Enable) + + +def GetManualMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of the manual mode on Elite/Summit/S300 stations. + API Status: internal + Returns: + Enable:int + Command Timeout: 10000 + Example:GetManualMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetManualMode") + return int(rsp[0]) + +def GetAxisReverse(Stage:str="", Axis:str=""): + """ + Allows reading if an axis is reverse. + API Status: published + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + IsReverse:int + Command Timeout: 5000 + Example:GetAxisReverse C X + """ + rsp = MessageServerInterface.sendSciCommand("GetAxisReverse",Stage,Axis) + return int(rsp[0]) + +def EnableEdgeSensor(EdgeSensor:int="", Enable:int=""): + """ + Enables/disables the use of an edge sensor. + API Status: published + Args: + EdgeSensor:int = 1 + Enable:int = 1 + Command Timeout: 5000 + Example:EnableEdgeSensor 1 1 + """ + MessageServerInterface.sendSciCommand("EnableEdgeSensor",EdgeSensor,Enable) + + +def SetTypedOutput(Channel:str="", WantOutputOn:int="", PulseTime:int=""): + """ + Controls the kernel valve driver signals and can be used to drive the outputs. + API Status: published + Args: + Channel:str = "NoSensor" + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetTypedOutput WaferVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetTypedOutput",Channel,WantOutputOn,PulseTime) + + +def ReadTypedSensor(Channel:str=""): + """ + Returns the status of the specified input channel, output channel, or edge + sensor. + API Status: published + Args: + Channel:str = "NoSensor" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadTypedSensor EmoIn I + """ + rsp = MessageServerInterface.sendSciCommand("ReadTypedSensor",Channel) + return int(rsp[0]) + +def MoveCoolDownPosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck to the cool down position that is defined in KernelSetup. The + cooldown position is used to move the chuck away in XY while the robot is in the + chamber and tries to get a hot wafer. + API Status: internal + Command Timeout: 30000 + Example:MoveCoolDownPosition + """ + MessageServerInterface.sendSciCommand("MoveCoolDownPosition") + + +def ReadJoystickSpeedsCycle(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the cycling speeds - these are the speeds that are used by + the USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CycleJog:int + CycleSpeed2:int + CycleSpeed3:int + CycleSpeed4:int + CycleIndex:int + Command Timeout: 5000 + Example:ReadJoystickSpeedsCycle S + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeedsCycle",Stage) + global ReadJoystickSpeedsCycle_Response + if not "ReadJoystickSpeedsCycle_Response" in globals(): ReadJoystickSpeedsCycle_Response = namedtuple("ReadJoystickSpeedsCycle_Response", "CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex") + return ReadJoystickSpeedsCycle_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetJoystickSpeedsCycle(Stage:str="", CycleJog:int="", CycleSpeed2:int="", CycleSpeed3:int="", CycleSpeed4:int="", CycleIndex:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets the cycling speeds - these are the speeds that are used by the + USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + CycleJog:int = 0 + CycleSpeed2:int = 0 + CycleSpeed3:int = 0 + CycleSpeed4:int = 0 + CycleIndex:int = 0 + Command Timeout: 5000 + Example:SetJoystickSpeedsCycle C 1 1 1 1 1 + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeedsCycle",Stage,CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex) + + +def SendAUCSCommand(Command:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows sending low level AUCS commands to the ECX box stage. Only + applies to Elite/Summit/S300 stations. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 60000 + Example:SendAUCSCommand "MM 1 0 INIT 0" + """ + rsp = MessageServerInterface.sendSciCommand("SendAUCSCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadCompensationStatus(Stage:str="", Compensation:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command allows reading if a specific type of compensation is enabled or + disabled. Returns an error if this type of compensation is not available for + this stage. + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Returns: + Enabled:int + Active:int + Command Timeout: 5000 + Example:ReadCompensationStatus C A + """ + rsp = MessageServerInterface.sendSciCommand("ReadCompensationStatus",Stage,Compensation) + global ReadCompensationStatus_Response + if not "ReadCompensationStatus_Response" in globals(): ReadCompensationStatus_Response = namedtuple("ReadCompensationStatus_Response", "Enabled,Active") + return ReadCompensationStatus_Response(int(rsp[0]),int(rsp[1])) + +def RegisterNotification(NotificationCode:int="", WantNotification:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deprecated. All Kernel notifications are now enabled by default. + API Status: internal + Args: + NotificationCode:int = 0 + WantNotification:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterNotification",NotificationCode,WantNotification) + + +def AlertNotification(NotificationId:int="", Value1:Decimal="", Value2:Decimal="", Value3:Decimal=""): + """ + This is not a regular command. Asynchronous notifications will be sent from the + Kernel controller to the host system only. All notifications can be switched off + and on, except the Prober reset notification (ID01). /warning This is a stub + implementation without appropriate handling + API Status: published + Args: + NotificationId:int = 0 + Value1:Decimal = 0 + Value2:Decimal = 0 + Value3:Decimal = 0 + Command Timeout: 5000 + Example:AlertNotification 31 195000 160000 0 + """ + MessageServerInterface.sendSciCommand("AlertNotification",NotificationId,Value1,Value2,Value3) + + +def SetCompensationStatus(Stage:str="", Compensation:str="", Status:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables a compensation mode for the specified stage + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Status:int = -1 + Command Timeout: 5000 + Example:SetCompensationStatus C A 1 + """ + MessageServerInterface.sendSciCommand("SetCompensationStatus",Stage,Compensation,Status) + + +def GetControllerInfo(ControllerInfo:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command gets the value "Value" for the parameter "Parameter". The unit is + parameter specific. + API Status: internal + Args: + ControllerInfo:str = "Unknown" + Returns: + Value:Decimal + Command Timeout: 1000 + Example:GetControllerInfo HasScanChuckZ + """ + rsp = MessageServerInterface.sendSciCommand("GetControllerInfo",ControllerInfo) + return Decimal(rsp[0]) + +def SetOperationalMode(OperationalMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + In unprotected mode a number of security features like software fence and + initialization necessity are deactivated. Unprotected mode is + deactivated automatically after 5 minutes. Sending 'SetOperationalMode U' + anytime before resets the timer back to 5 minutes. It is not necessary to + deactivate it before. **WARNING**: If unprotected mode is enabled, even the + most basic safety- and sanity-checks are skipped. Any movement may cause + irreparable damage to the prober or attached hardware. + API Status: internal + Args: + OperationalMode:str = "ProtectedMode" + Command Timeout: 5000 + Example:SetOperationalMode P + """ + MessageServerInterface.sendSciCommand("SetOperationalMode",OperationalMode) + + +def GetNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured Nano-chamber-state. + API Status: internal + Returns: + NanoChamberState:str + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetNanoChamberState(NanoChamberState:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the NanoChamber-state. + API Status: internal + Args: + NanoChamberState:str = "Free" + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetNanoChamberState",NanoChamberState) + + +def SetCameraCool(State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows to force activate/deactivate the camera cool output or to let it be set + automatically by purge control. + API Status: internal + Args: + State:int = 2 + Command Timeout: 10000 + Example:SetCameraCool 0 + """ + MessageServerInterface.sendSciCommand("SetCameraCool",State) + + +def ActivateChuckVacuum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the chuck vacuum and forces it to be on. This command ignores the + vacuum sensor and timeout. + API Status: internal + Command Timeout: 10000 + Example:ActivateChuckVacuum + """ + MessageServerInterface.sendSciCommand("ActivateChuckVacuum") + + +def ReadMatrixValues(Stage:str="", MatrixIndexX:int="", MatrixIndexY:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns a point from the matrix compensation table for the + specified axis from the kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + Returns: + XVal:Decimal + YVal:Decimal + Command Timeout: 5000 + Example:ReadMatrixValues C 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMatrixValues",Stage,MatrixIndexX,MatrixIndexY) + global ReadMatrixValues_Response + if not "ReadMatrixValues_Response" in globals(): ReadMatrixValues_Response = namedtuple("ReadMatrixValues_Response", "XVal,YVal") + return ReadMatrixValues_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetMatrixValues(Stage:str="", MatrixIndexX:int="", MatrixIndexY:int="", XVal:Decimal="", YVal:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Downloads a point of the matrix compensation table for a specified stage to the + kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + XVal:Decimal = 0 + YVal:Decimal = 0 + Command Timeout: 5000 + Example:SetMatrixValues C 0 0 5000.0 5000.0 2500.0 + """ + MessageServerInterface.sendSciCommand("SetMatrixValues",Stage,MatrixIndexX,MatrixIndexY,XVal,YVal) + + +def ReadMEAStatus(Stage:str="", Type:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads if the MEA file for a stage is loaded/enabled (Nucleus legacy stations + only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Returns: + Enable:int + Command Timeout: 5000 + Example:ReadMEAStatus C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMEAStatus",Stage,Type) + return int(rsp[0]) + +def LoadMEAFile(Stage:str="", Type:int="", Load:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Load the MEA file for a stage (Nucleus legacy stations only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Load:int = 0 + Command Timeout: 5000 + Example:LoadMEAFile C 0 1 + """ + MessageServerInterface.sendSciCommand("LoadMEAFile",Stage,Type,Load) + + +def ReadSoftwareLimits(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The command returns the positions of the actual software limits (end of move + range) for each axis of the specified stage in microns. If the Theta stage is + selected Z1 and Z2 include the values for the Theta limits. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + ZLowValue:Decimal + ZHighValue:Decimal + X1Value:Decimal + Y1Value:Decimal + X2Value:Decimal + Y2Value:Decimal + X3Value:Decimal + Y3Value:Decimal + X4Value:Decimal + Y4Value:Decimal + Command Timeout: 5000 + Example:ReadSoftwareLimits C + """ + rsp = MessageServerInterface.sendSciCommand("ReadSoftwareLimits",Stage) + global ReadSoftwareLimits_Response + if not "ReadSoftwareLimits_Response" in globals(): ReadSoftwareLimits_Response = namedtuple("ReadSoftwareLimits_Response", "ZLowValue,ZHighValue,X1Value,Y1Value,X2Value,Y2Value,X3Value,Y3Value,X4Value,Y4Value") + return ReadSoftwareLimits_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def SetSoftwareFence(Stage:str="", AuxID:int="", FenceForm:str="", XBase:Decimal="", YBase:Decimal="", XDist:Decimal="", YDist:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets types and dimensions of technological software fences. It can + also be used for enabling and disabling the software fence. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + FenceForm:str = "None" + XBase:Decimal = 0 + YBase:Decimal = 0 + XDist:Decimal = 0 + YDist:Decimal = 0 + Command Timeout: 10000 + Example:SetSoftwareFence C 0 R 5000 5000 25000 25000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareFence",Stage,AuxID,FenceForm,XBase,YBase,XDist,YDist) + + +def GetSoftwareFence(Stage:str="", AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the type and the dimensions of an actual set technological + software fence. In case of a rectangular software fence, X and Y coordinates of + the four edge points of the fence are given back. In case of a circular software + fence, X and Y coordinates of the center point and the radius are given back. + All other return values are filled with zeros. All position values are in + microns from zero. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + Returns: + FenceForm:str + XValue1:Decimal + YValue1:Decimal + XValue2:Decimal + YValue2:Decimal + XValue3:Decimal + YValue3:Decimal + XValue4:Decimal + YValue4:Decimal + Command Timeout: 10000 + Example:GetSoftwareFence C + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareFence",Stage,AuxID) + global GetSoftwareFence_Response + if not "GetSoftwareFence_Response" in globals(): GetSoftwareFence_Response = namedtuple("GetSoftwareFence_Response", "FenceForm,XValue1,YValue1,XValue2,YValue2,XValue3,YValue3,XValue4,YValue4") + return GetSoftwareFence_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8])) + +def GetZFence(Stage:str="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands reads if the Z-Fence is activated and the currently set Z-fence + values for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CompLayer:str = "Default" + Returns: + Enabled:int + ZLow:Decimal + ZHigh:Decimal + Command Timeout: 10000 + Example:GetZFence S + """ + rsp = MessageServerInterface.sendSciCommand("GetZFence",Stage,CompLayer) + global GetZFence_Response + if not "GetZFence_Response" in globals(): GetZFence_Response = namedtuple("GetZFence_Response", "Enabled,ZLow,ZHigh") + return GetZFence_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetZFence(Stage:str="", Enabled:int="", ZLow:Decimal="", ZHigh:Decimal="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands sets Z-Fence and the Z-fence values for the specified stage. + Values are stored uncompensated internally and set default compensated as + default. + API Status: internal + Args: + Stage:str = "Chuck" + Enabled:int = 0 + ZLow:Decimal = 0 + ZHigh:Decimal = 0 + CompLayer:str = "Default" + Command Timeout: 10000 + Example:SetZFence S 1 5000 10000 + """ + MessageServerInterface.sendSciCommand("SetZFence",Stage,Enabled,ZLow,ZHigh,CompLayer) + + +def ResetProber(Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the Prober and replaces the current configuration with a formerly + written recovery file. If no recovery file was written, the configuration is + reset to the version of the last Prober restart. For ProberBench electronics, + 'H' will restart the Operating system, 'S' will only restart the Kernel + application. For Windows Kernel, 'H' and 'S' are identical. + API Status: internal + Args: + Mode:str = "S" + Command Timeout: 20000 + Example:ResetProber S + """ + MessageServerInterface.sendSciCommand("ResetProber",Mode) + + +def ResetCBox(ResetMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reboots the operation system inside the Joystick Controller and restarts the + functionality. The restart will need a time of around 20 seconds. + API Status: internal + Args: + ResetMode:str = "S" + Command Timeout: 20000 + Example:ResetCBox S + """ + MessageServerInterface.sendSciCommand("ResetCBox",ResetMode) + + +def ReadStageLocations(Stage:str="", LocationType:str="", AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The Home Position on the Chuck or ProbeHead Z axis is also called contact + height. The Home Position on the Scope Z axis is also called focus height. + API Status: internal + Args: + Stage:str = "Chuck" + LocationType:str = "Center" + AuxID:int = 0 + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadStageLocations C C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadStageLocations",Stage,LocationType,AuxID) + global ReadStageLocations_Response + if not "ReadStageLocations_Response" in globals(): ReadStageLocations_Response = namedtuple("ReadStageLocations_Response", "X,Y,Z") + return ReadStageLocations_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetDataIterator(ShowAll:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters. + and requires the GetNextDatum command. + API Status: internal + Args: + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 10000 + Example:GetDataIterator 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetDataIterator",ShowAll) + global GetDataIterator_Response + if not "GetDataIterator_Response" in globals(): GetDataIterator_Response = namedtuple("GetDataIterator_Response", "IdentityToken,SizeNoAll") + return GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def GetNextDatum(IdentityToken:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + Attributes:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:GetNextDatum 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetNextDatum",IdentityToken) + global GetNextDatum_Response + if not "GetNextDatum_Response" in globals(): GetNextDatum_Response = namedtuple("GetNextDatum_Response", "IsLastDatum,DatumCode,Attributes,PathNameDescrValue") + return GetNextDatum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetDatum(PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:SetDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetDatum",PathNameAndValue) + + +def GetDatum(PathName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + PathName:str = "" + Returns: + Attributes:int + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:GetDatum Chuck:AlignGap + """ + rsp = MessageServerInterface.sendSciCommand("GetDatum",PathName) + global GetDatum_Response + if not "GetDatum_Response" in globals(): GetDatum_Response = namedtuple("GetDatum_Response", "Attributes,DatumCode,ValueDesc") + return GetDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetRecoveryDatum(PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 5000 + Example:SetRecoveryDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetRecoveryDatum",PathNameAndValue) + + +def TraceStart(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the motion recording. The recording parameters are set in dynamic + kernel setup. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStart C + """ + MessageServerInterface.sendSciCommand("TraceStart",Controller) + + +def TraceStatus(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Checks the motion recording status for one stage. + API Status: internal + Args: + Controller:str = "Chuck" + Returns: + IsReady:int + SizeCh0Raw:int + SizeCh0Comp:int + SizeCh1Raw:int + SizeCh1Comp:int + SizeCh2Raw:int + SizeCh2Comp:int + SizeCh3Raw:int + SizeCh3Comp:int + Command Timeout: 10000 + Example:TraceStatus C + """ + rsp = MessageServerInterface.sendSciCommand("TraceStatus",Controller) + global TraceStatus_Response + if not "TraceStatus_Response" in globals(): TraceStatus_Response = namedtuple("TraceStatus_Response", "IsReady,SizeCh0Raw,SizeCh0Comp,SizeCh1Raw,SizeCh1Comp,SizeCh2Raw,SizeCh2Comp,SizeCh3Raw,SizeCh3Comp") + return TraceStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def TraceGetData(Controller:str="", Channel:int="", PointOne:int="", IsCompress:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a collection of five data pairs. A pair is the index and the value of a + recording point. If the stream is empty or at the end the index is 1 and the + value 0. The index is relative to the start of the motion recording. The + recording is clocked by the motion controller cycle. The cycle time is contained + in the Kernel setup. In the raw stream all recorded trace points are contained. + But in the compressed stream only the non-linear depending trace points are + contained. To reload the recording points the stream must be reset to the first + recording point. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + PointOne:int = 1 + IsCompress:int = 1 + Returns: + Point1:int + Value1:int + Point2:int + Value2:int + Point3:int + Value3:int + Point4:int + Value4:int + Point5:int + Value5:int + Command Timeout: 10000 + Example:TraceGetData C 0 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("TraceGetData",Controller,Channel,PointOne,IsCompress) + global TraceGetData_Response + if not "TraceGetData_Response" in globals(): TraceGetData_Response = namedtuple("TraceGetData_Response", "Point1,Value1,Point2,Value2,Point3,Value3,Point4,Value4,Point5,Value5") + return TraceGetData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def TraceSetDataPosition(Controller:str="", Channel:int="", NewPos:int="", IsCompress:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the index position in the raw or compressed stream for the next call of the + command TraceGetData. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + NewPos:int = 0 + IsCompress:int = 1 + Command Timeout: 10000 + Example:TraceSetDataPosition C 0 1000 1 + """ + MessageServerInterface.sendSciCommand("TraceSetDataPosition",Controller,Channel,NewPos,IsCompress) + + +def TraceStop(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the motion recording. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStop C + """ + MessageServerInterface.sendSciCommand("TraceStop",Controller) + + +def SetZProfilePoint(Stage:str="", XValue:Decimal="", YValue:Decimal="", ZGap:Decimal="", PosRef:str="", Unit:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set a point for the Z height profile. If this profile is enabled, the Z height + depends on a X and Y coordinate. The Z value is a gap to the current Z height. + Positive values are elevated spots, negative values are hollows. The height + profile is used to adjust the Z height. The adjusted Z height at a X and Y + position is derivated from the nearest profile point. The Z contact level will + be calculated from the contact height and the stored Z gap at this point. See + GetZProfilePoint for details. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + ZGap:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + ValueCount:int + Command Timeout: 5000 + Example:SetZProfilePoint C 5000 5000 -3 H Y + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfilePoint",Stage,XValue,YValue,ZGap,PosRef,Unit,ZProfileType) + return int(rsp[0]) + +def ReadZProfilePoint(Stage:str="", Index:int="", PosRef:str="", Unit:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a single point and the corresponding Z gap of the Z height profile. The + different z profiles are: - transient: meant to be used on a per-wafer-basis, + default - persistent: configured once, stays in memory - persistent-offset: same + as persistent, active when offset is enabled - scratch: not used internaly. Can + be used to translate KernelDatums <-> ZProfile-Points + API Status: internal + Args: + Stage:str = "Chuck" + Index:int = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + XValue:Decimal + YValue:Decimal + ZGap:Decimal + ValueCount:int + Command Timeout: 5000 + Example:ReadZProfilePoint C 1 H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfilePoint",Stage,Index,PosRef,Unit,ZProfileType) + global ReadZProfilePoint_Response + if not "ReadZProfilePoint_Response" in globals(): ReadZProfilePoint_Response = namedtuple("ReadZProfilePoint_Response", "XValue,YValue,ZGap,ValueCount") + return ReadZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3])) + +def ClearZProfile(Stage:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clears all profile points. See GetZProfile for type description. + API Status: internal + Args: + Stage:str = "Chuck" + ZProfileType:int = 0 + Command Timeout: 5000 + Example:ClearZProfile C + """ + MessageServerInterface.sendSciCommand("ClearZProfile",Stage,ZProfileType) + + +def ReadScopeSilo(Index:int=""): + """ + Returns the definition of a silo. If the type is rectangle, center means + _Point1_. If the type is circle, the meaning of Pos2X and Pos2Y is undefined. + API Status: published + Args: + Index:int = 1 + Returns: + Type:str + CenterX:Decimal + CenterY:Decimal + Radius:Decimal + Pos2X:Decimal + Pos2Y:Decimal + ZHigh:Decimal + RefX:Decimal + RefY:Decimal + RefZ:Decimal + Command Timeout: 5000 + Example:ReadScopeSilo 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSilo",Index) + global ReadScopeSilo_Response + if not "ReadScopeSilo_Response" in globals(): ReadScopeSilo_Response = namedtuple("ReadScopeSilo_Response", "Type,CenterX,CenterY,Radius,Pos2X,Pos2Y,ZHigh,RefX,RefY,RefZ") + return ReadScopeSilo_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def NewProjectFile(FileName:str=""): + """ + Alerts applications if the project file was changed. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("NewProjectFile",FileName) + + +def SaveProjectFile(FileName:str=""): + """ + Alerts applications to save the current project. This notification _MUST_ only + be invoked by CommonCommands. Sending this notification directly _WILL_ give + erroneous results. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectFile",FileName) + + +def NewAccessLevel(AccessLevel:str="", UserName:str="", VeloxLocked:int=""): + """ + Alerts applications of new access level. + API Status: published + Args: + AccessLevel:str = "Engineer" + UserName:str = "" + VeloxLocked:int = 0 + Command Timeout: 5000 + Example:NewAccessLevel 1 + """ + MessageServerInterface.sendSciCommand("NewAccessLevel",AccessLevel,UserName,VeloxLocked) + + +def LicenseInfo(AnnualEnabled:int="", AnnualDaysLeft:int="", VeloxProEnabled:int="", VueTrackEnabled:int="", VueTrack4PEnabled:int="", ReAlignEnabled:int="", AutomationEnabled:int="", IdToolsEnabled:int="", IVistaEnabled:int="", IVistaProEnabled:int="", LaserCutterEnabled:int="", SiPToolsEnabled:int="", AutoRfEnabled:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener about the licensed Velox features. Is sent cyclically by + CommonCommands. + API Status: internal + Args: + AnnualEnabled:int = 1 + AnnualDaysLeft:int = 460 + VeloxProEnabled:int = 0 + VueTrackEnabled:int = 0 + VueTrack4PEnabled:int = 0 + ReAlignEnabled:int = 0 + AutomationEnabled:int = 0 + IdToolsEnabled:int = 0 + IVistaEnabled:int = 0 + IVistaProEnabled:int = 0 + LaserCutterEnabled:int = 0 + SiPToolsEnabled:int = 0 + AutoRfEnabled:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicenseInfo",AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled) + + +def RegisterProberAppChange(AppName:str="", SecName:str="", NewRegistered:int=""): + """ + Alerts applications that an application is registered or unregistered on + MsgServer. + API Status: published + Args: + AppName:str = "SharedTest" + SecName:str = "SharedTest" + NewRegistered:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterProberAppChange",AppName,SecName,NewRegistered) + + +def AlignmentModeChange(AlignmentMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications of a change of the current alignment mode + API Status: internal + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + Example:AlignmentModeChange OnAxis + """ + MessageServerInterface.sendSciCommand("AlignmentModeChange",AlignmentMode) + + +def KernelConnectionStatus(ControllerNum:int="", Type:str="", Result:str="", Desc:str=""): + """ + An example of Kernel Connection Status is "Windows Socket Error Number and + Error Description." + API Status: published + Args: + ControllerNum:int = 1 + Type:str = "Socket" + Result:str = "Disconnected" + Desc:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelConnectionStatus",ControllerNum,Type,Result,Desc) + + +def KernelCompensationStatusChange(Stage:str="", Compensation:str="", Enabled:int="", Active:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Compensation:str = "None" + Enabled:int = 0 + Active:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationStatusChange",Stage,Compensation,Enabled,Active) + + +def KernelCompensationLevelChange(Stage:str="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation level has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Comp:str = "None" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationLevelChange",Stage,Comp) + + +def MoveZCombinedStatusChange(Status:str="", PlatenSafe:int="", Height:Decimal="", HeightMax:Decimal="", HeightRelative:Decimal="", SafeHeight:Decimal="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the combined-z-move-system + API Status: internal + Args: + Status:str = "Off" + PlatenSafe:int = 0 + Height:Decimal = 0 + HeightMax:Decimal = 0 + HeightRelative:Decimal = 0 + SafeHeight:Decimal = 0 + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedStatusChange",Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message) + + +def MachineStateChange(MachineState:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the machine state + API Status: internal + Args: + MachineState:str = "Off" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MachineStateChange",MachineState) + + +def ChuckVacuumChangeRequest(VacuumState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if the user requests a chuck vacuum change + API Status: internal + Args: + VacuumState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ChuckVacuumChangeRequest",VacuumState) + + +def SoftwareStopChangedNotify(SoftwareStopState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if software stop was activated or deactivated + API Status: internal + Args: + SoftwareStopState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SoftwareStopChangedNotify",SoftwareStopState) + + +def KernelQuietModeChange(IsQuiet:int="", Stage:str="", IsStageQuiet:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs if the overall quiet mode changes and about changes of single stages + API Status: internal + Args: + IsQuiet:int = 0 + Stage:str = "None" + IsStageQuiet:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelQuietModeChange",IsQuiet,Stage,IsStageQuiet) + + +def ConfigurationChanged(ParameterChanged:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies that a configuration item has changed by some application + API Status: internal + Args: + ParameterChanged:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ConfigurationChanged",ParameterChanged) + + +def ScopeWorkingStageChanged(ScopeWorkingStage:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs that a new working stage is active + API Status: internal + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ScopeWorkingStageChanged",ScopeWorkingStage) + + +def BnR_AxisNotify(Stage:str="", Axis:str="", State:str="", AdditionalStateInfo:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the user Interface and Kernel if the state of the axis has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + State:str = "NotExisting" + AdditionalStateInfo:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisNotify",Stage,Axis,State,AdditionalStateInfo) + + +def BnR_StageNotify(Stage:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the stage status has changed. + API Status: internal + Args: + Stage:str = "Chuck" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_StageNotify",Stage,State) + + +def BnR_InputNotify(Channel:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an input channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InputNotify",Channel,State) + + +def BnR_OutputNotify(Channel:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an output channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_OutputNotify",Channel,State) + + +def BnR_AxisStatusNotify(Stage:str="", Axis:str="", Initialized:int="", PositiveLimit:int="", NegativeLimit:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener that an axis status has changed. Currently used to notify + the Kernel about the init state of a BnR axis. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Initialized:int = 0 + PositiveLimit:int = 0 + NegativeLimit:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisStatusNotify",Stage,Axis,Initialized,PositiveLimit,NegativeLimit) + + +def AutoXYModeChange(AutoXYModeOn:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by Spectrum if Automation was enabled or disabled. This can be AutoXY, + AutoZ or VueTrack. Handled by WaferMap to ensure that automation is executed + when stepping. + API Status: internal + Args: + AutoXYModeOn:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("AutoXYModeChange",AutoXYModeOn) + + +def ZoomLevelChange(ZoomLevel:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by OpticalControl when the AZoom zoom level is changed. Spectrum should + handle this so it doesn't have to poll OpticalControl for the current zoom + level. + API Status: internal + Args: + ZoomLevel:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ZoomLevelChange",ZoomLevel) + + +def BnR_AnalogIONotify(AnalogIO:str="", ValuePercent:Decimal="", UnderOverflow:int="", Error:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state or value of an analog input or output channel + has changed. + API Status: internal + Args: + AnalogIO:str = "AO_PurgeDewPoint" + ValuePercent:Decimal = 0 + UnderOverflow:int = 0 + Error:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AnalogIONotify",AnalogIO,ValuePercent,UnderOverflow,Error) + + +def BnR_ControllerInfoNotify(ControllerNum:int="", ControllerInfo:str="", Value:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies the listener about changed controller info. Currently used to inform + Toolbar about the battery state of the BnR controller. + API Status: internal + Args: + ControllerNum:int = 1 + ControllerInfo:str = "BatteryOK" + Value:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_ControllerInfoNotify",ControllerNum,ControllerInfo,Value) + + +def BnR_PositionNotify(Stage:str="", XorT:Decimal="", Y:Decimal="", Z:Decimal="", CommandedXorT:Decimal="", CommandedY:Decimal="", CommandedZ:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by BnR controller if a axis position has changed. Currently + used to notify the Kernel about the new axis position. + API Status: internal + Args: + Stage:str = "Chuck" + XorT:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + CommandedXorT:Decimal = 0 + CommandedY:Decimal = 0 + CommandedZ:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_PositionNotify",Stage,XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ) + + +def BnR_InfoNotify(InfoType:str="", Info:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Generic Information Notification + API Status: internal + Args: + InfoType:str = "" + Info:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InfoNotify",InfoType,Info) + + +def WMNewCurrentDie(DieX:int="", DieY:int="", XFromHome:Decimal="", YFromHome:Decimal="", CurSite:int="", LastSiteIndex:int=""): + """ + Alerts applications that WaferMap has a new position. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + XFromHome:Decimal = 0 + YFromHome:Decimal = 0 + CurSite:int = 1 + LastSiteIndex:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMNewCurrentDie",DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex) + + +def WMSetupChange(): + """ + Alerts applications that a wafer's parameters have been changed. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMSetupChange") + + +def ButtonPress(TargetIdent:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when button instrumented for guided workflow is pressed. The TargetIdent is + the identifier for the button as defined for the guided workflow. + API Status: internal + Args: + TargetIdent:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("ButtonPress",TargetIdent) + + +def CryoCmdReady(State:str="", Error:int="", ErrorDescription:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when the cooling or heating process was terminated successfully or + incorrectly. Returns the status with which the process was finished (IDLE, COLD, + COOL DOWN, WARMUP) and sends the error code and error message. + API Status: internal + Args: + State:str = "IDLE" + Error:int = 0 + ErrorDescription:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CryoCmdReady",State,Error,ErrorDescription) + + +def VMProjectLoaded(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent when Spectrum VS project has finished loading. + API Status: internal + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProjectLoaded") + + +def VMProbeCardData(Access:str="", FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent when a probe card file is loaded. + API Status: internal + Args: + Access:str = "L" + FileName:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProbeCardData",Access,FileName) + + +def TTLTestDone(): + """ + Alerts applications that the TTL Test is ready. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("TTLTestDone") + + +def PSStateChanged(State:str="", SubState:str="", Message:str="", Error:int=""): + """ + Notification sent when VeloxPro changes its running state. + API Status: published + Args: + State:str = "Unknown" + SubState:str = "Unknown" + Message:str = "" + Error:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSStateChanged",State,SubState,Message,Error) + + +def PSProgressChanged(ProgressPercent:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent during wafer stepping process. It updates the progress + information. 'Progress' is the relationship of dies tested to dies to be tested. + API Status: internal + Args: + ProgressPercent:Decimal = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSProgressChanged",ProgressPercent) + + +def PSLoaderUsage(UseLoader:int="", UseAutoWafer:int="", WaferSizes:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent to notify the listener about usage of Loader, usage of + fully/semiautomatic mode and supported wafer sizes of process station. + API Status: internal + Args: + UseLoader:int = 0 + UseAutoWafer:int = 0 + WaferSizes:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSLoaderUsage",UseLoader,UseAutoWafer,WaferSizes) + + +def LoaderMessage(Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by loader to display a message on the process station. + API Status: internal + Args: + Message:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("LoaderMessage",Message) + + +def OpenProjectDialog(ProjectFilename:str="", Option:int=""): + """ + Asks if the current project should be saved and then brings up the Open Project + window which opens the selected project file if the user clicks ok. + API Status: published + Args: + ProjectFilename:str = "" + Option:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("OpenProjectDialog",ProjectFilename,Option) + + +def SaveProjectAsDialog(): + """ + Brings up the Save Project window which saves the project if the user clicks ok. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsDialog") + + +def LoginDialog(LevelToOffer:str=""): + """ + Brings up the Login window and sends a New Access Level alert if the user enters + a valid password. + API Status: published + Args: + LevelToOffer:str = "1" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoginDialog",LevelToOffer) + + +def GetStatus(): + """ + Returns the current software status. The server holds and maintains the software + status. Status can be changed by using any of the following commands: + BeginProbing, LoginDialog, AbortProbing, SetExternalMode, PauseProbing, + UnloadWafer, ResumeProbing + API Status: published + Returns: + DummyCommonMode:int + RunningMode:str + AccessLevel:str + ExternalMode:int + LicenseDaysLeft:int + MKH:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetStatus") + global GetStatus_Response + if not "GetStatus_Response" in globals(): GetStatus_Response = namedtuple("GetStatus_Response", "DummyCommonMode,RunningMode,AccessLevel,ExternalMode,LicenseDaysLeft,MKH") + return GetStatus_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def LicensingDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Licensing window. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicensingDialog") + + +def GetLicenseInfo(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current license information. + API Status: internal + Returns: + AnnualEnabled:int + AnnualDaysLeft:int + VeloxProEnabled:int + VueTrackEnabled:int + VueTrack4PEnabled:int + ReAlignEnabled:int + AutomationEnabled:int + IdToolsEnabled:int + IVistaEnabled:int + IVistaProEnabled:int + LaserCutterEnabled:int + SiPToolsEnabled:int + AutoRfEnabled:int + SecsGemEnabled:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLicenseInfo") + global GetLicenseInfo_Response + if not "GetLicenseInfo_Response" in globals(): GetLicenseInfo_Response = namedtuple("GetLicenseInfo_Response", "AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled,SecsGemEnabled") + return GetLicenseInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13])) + +def GetProjectFile(): + """ + Returns the current project file. + API Status: published + Returns: + ProjectFilename:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProjectFile") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportSoftwareVersion(): + """ + Returns the Velox software version as string. + API Status: published + Returns: + SoftwareVersion:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReportSoftwareVersion") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OpenProject(ProjectFilename:str=""): + """ + The OpenProject command opens the specified project. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("OpenProject",ProjectFilename) + + +def IsAppRegistered(Application:str=""): + """ + Checks the server to see if the application "AppName" is registered with the + server. + API Status: published + Args: + Application:str = "" + Returns: + IsAppRegistered:int + Command Timeout: 5000 + Example:IsAppRegistered WaferMap + """ + rsp = MessageServerInterface.sendSciCommand("IsAppRegistered",Application) + return int(rsp[0]) + +def SaveProject(ProjectFilename:str=""): + """ + Saves the current data to the project file. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("SaveProject",ProjectFilename) + + +def GetSoftwarePath(PathType:str=""): + """ + Returns the path for either the applications/data or project files. + API Status: published + Args: + PathType:str = "User" + Returns: + SoftwarePath:str + Command Timeout: 5000 + Example:GetSoftwarePath User + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwarePath",PathType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CCSelectLens(Lens:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. + API Status: internal + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:CCSelectLens 1 + """ + MessageServerInterface.sendSciCommand("CCSelectLens",Lens) + + +def CCReadCurrentLens(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. Probably no longer used. + API Status: internal + Returns: + Lens:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("CCReadCurrentLens") + return int(rsp[0]) + +def CCMoveAuxSite(AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calls the Kernel command MoveAuxSite to move the chuck to the + position of a given AUX site. For the transfer move a safe height is used. If + AUX ID is set to 0, the target of the move is the wafer site. If the flag 'Auto + Align by Spectrum' in ControlCenter-SystemSetup-Aux Sites is True, the Spectrum + command AlignAux is executed after MoveAuxSite to align the site automatically. + The flag is only visible, if the aux site type is CalSubstrate and Spectrum is + installed. AUX ID in the response is the ID of the new active site. + API Status: internal + Args: + AuxID:int = 1 + Command Timeout: 200000 + """ + MessageServerInterface.sendSciCommand("CCMoveAuxSite",AuxID) + + +def ExecuteCleaningSequence(SequenceName:str="", AllowMediaReuse:int="", SkipAlignAux:int="", SkipReturnMove:int=""): + """ + This command moves to the single cleaning site, executes CleanProbeTip, moves to + the contact verify site, and then moves to contact. Returns an error if the + clean or verify sites aren't defined. + API Status: published + Args: + SequenceName:str = "" + AllowMediaReuse:int = 0 + SkipAlignAux:int = 0 + SkipReturnMove:int = 0 + Command Timeout: 1800000 + Example:ExecuteCleaningSequence "DeepClean" + """ + MessageServerInterface.sendSciCommand("ExecuteCleaningSequence",SequenceName,AllowMediaReuse,SkipAlignAux,SkipReturnMove) + + +def GetAlignmentMode(): + """ + Get the active alignment mode (either on axis or off axis). + API Status: published + Returns: + AlignmentMode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetAlignmentMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetAlignmentMode(AlignmentMode:str=""): + """ + Sets the active alignment mode (either on axis or off axis). + API Status: published + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetAlignmentMode",AlignmentMode) + + +def GetLoginData(CmdUserName:str=""): + """ + Gets the Velox user data: name, full name, group, access level. If the + commanded user name is empty, the data of the current user will be responded + API Status: published + Args: + CmdUserName:str = "" + Returns: + UserName:str + LongUserName:str + UserGroup:str + AccessLevel:str + VeloxLocked:int + Command Timeout: 5000 + Example:GetLoginData + """ + rsp = MessageServerInterface.sendSciCommand("GetLoginData",CmdUserName) + global GetLoginData_Response + if not "GetLoginData_Response" in globals(): GetLoginData_Response = namedtuple("GetLoginData_Response", "UserName,LongUserName,UserGroup,AccessLevel,VeloxLocked") + return GetLoginData_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4])) + +def NucleusInitChuck(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to warn user of chuck initialization for Nucleus stations. + Allows user to OK/Cancel. + API Status: internal + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("NucleusInitChuck") + + +def ShutdownVeloxWithSave(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to allow saving project before shutting down Velox. Allows + user to OK/Cancel. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ShutdownVeloxWithSave") + + +def WinCalAutoCal(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCal command to WinCal. + API Status: internal + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCal") + + +def WinCalCheckAutoRFStability(AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCheckAutoRFStability command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Returns: + StabilityPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalCheckAutoRFStability",AllowMove) + return int(rsp[0]) + +def WinCalCloseRFStabilityReport(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCloseRFStabilityReport command to WinCal. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalCloseRFStabilityReport") + + +def WinCalMoveToIssRef(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalMoveToIssRef command to WinCal to move to the specified ISS + reference. The ISS index is the IssIdxMap index as returned from + WinCalGetIssListForAuxSite. + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("WinCalMoveToIssRef",IssIdx) + + +def WinCalVerifyIssRefLocAtHome(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalVerifyIssRefLocAtHome command to WinCal and returns AllRefAtHome + as 1 if stage and positioners at home. + API Status: internal + Args: + IssIdx:int = 0 + Returns: + AllRefAtHome:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalVerifyIssRefLocAtHome",IssIdx) + return int(rsp[0]) + +def WinCalGetIssForAuxSite(AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetIssForAuxSite command to WinCal and returns the ISS + information for the given aux site ID. + API Status: internal + Args: + AuxID:int = 0 + Returns: + IssIdx:int + IssPN:str + IssDescription:str + IssEnabled:int + AuxSiteName:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetIssForAuxSite",AuxID) + global WinCalGetIssForAuxSite_Response + if not "WinCalGetIssForAuxSite_Response" in globals(): WinCalGetIssForAuxSite_Response = namedtuple("WinCalGetIssForAuxSite_Response", "IssIdx,IssPN,IssDescription,IssEnabled,AuxSiteName") + return WinCalGetIssForAuxSite_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def WinCalGetNameAndVersion(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetNameAndVersion command to WinCal. + API Status: internal + Returns: + ServerName:str + Version:str + MajorVersion:int + MinorVersion:int + Revision:int + Build:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNameAndVersion") + global WinCalGetNameAndVersion_Response + if not "WinCalGetNameAndVersion_Response" in globals(): WinCalGetNameAndVersion_Response = namedtuple("WinCalGetNameAndVersion_Response", "ServerName,Version,MajorVersion,MinorVersion,Revision,Build") + return WinCalGetNameAndVersion_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def WinCalMonitorNoMove(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMonitorNoMove command to WinCal. Triggers WinCal to measure the + monitor portion of the current calibration setup. + API Status: internal + Returns: + MonitorPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalMonitorNoMove") + return int(rsp[0]) + +def WinCalValidateAdvanced(ProbeSpacing:Decimal="", ResetTrace:int="", AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidateAdvanced command to WinCal. Performs the validation step of + the currently selected calibration setup. Resets the controller used in WinCal + for validataion. + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + ResetTrace:int = 1 + AllowMove:int = 1 + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidateAdvanced",ProbeSpacing,ResetTrace,AllowMove) + return int(rsp[0]) + +def WinCalMeasureMonitorReference(AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMeasureMonitorReference command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalMeasureMonitorReference",AllowMove) + + +def WinCalGetNumValidationPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumValidationPorts command to WinCal. + API Status: internal + Returns: + NumValidationPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumValidationPorts") + return int(rsp[0]) + +def WinCalSetNumValidationPorts(NumValidationPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumValidationPorts command to WinCal. + API Status: internal + Args: + NumValidationPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumValidationPorts",NumValidationPorts) + + +def WinCalGetNumMonitoringPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumMonitoringPorts command to WinCal. + API Status: internal + Returns: + NumMonitoringPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumMonitoringPorts") + return int(rsp[0]) + +def WinCalSetNumMonitoringPorts(NumMonitoringPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumMonitoringPorts command to WinCal. + API Status: internal + Args: + NumMonitoringPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumMonitoringPorts",NumMonitoringPorts) + + +def WinCalGetNumRepeatabilityPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumRepeatabilityPorts command to WinCal. + API Status: internal + Returns: + NumRepeatabilityPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumRepeatabilityPorts") + return int(rsp[0]) + +def WinCalSetNumRepeatabilityPorts(NumRepeatabilityPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumRepeatabilityPorts command to WinCal. + API Status: internal + Args: + NumRepeatabilityPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumRepeatabilityPorts",NumRepeatabilityPorts) + + +def WinCalValidate(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidate command to WinCal. Performs the validation step of the + currently selected calibration setup in WinCal. + API Status: internal + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidate") + return int(rsp[0]) + +def WinCalGetValidationSetup(Port:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends CalGetValidationSetup command to WinCal. Returns calibration setup + parameters. + API Status: internal + Args: + Port:int = 1 + Returns: + StandardType:str + StandardPorts:int + StandardCompareType:int + StructureType:str + PostCorrect:int + PostCorrectMatching:int + AutoConfigure:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetValidationSetup",Port) + global WinCalGetValidationSetup_Response + if not "WinCalGetValidationSetup_Response" in globals(): WinCalGetValidationSetup_Response = namedtuple("WinCalGetValidationSetup_Response", "StandardType,StandardPorts,StandardCompareType,StructureType,PostCorrect,PostCorrectMatching,AutoConfigure") + return WinCalGetValidationSetup_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def WinCalAutoCalNoValidation(ProbeSpacing:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCalNoValidation command to WinCal. Performs an AutoCal + without the validation step + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCalNoValidation",ProbeSpacing) + + +def WinCalHideAllWindows(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalHideAllWindows command to WinCal. This minimizes all the WinCal + windows + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalHideAllWindows") + + +def WinCalGetReferenceStructureInfo(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetReferenceStructureInfo command to WinCal. Given the WinCal ISS + index it will return a string with the reference information + API Status: internal + Args: + IssIdx:int = 0 + Returns: + ReferenceInfo:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetReferenceStructureInfo",IssIdx) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def WinCalSystemSetupHasUnappliedChanges(ShowErrors:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalSystemSetupHasUnappliedChanges command to WinCal. Returns true + if WinCal has unapplied changes + API Status: internal + Args: + ShowErrors:int = 0 + Returns: + HasUnappliedChanges:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalSystemSetupHasUnappliedChanges",ShowErrors) + return int(rsp[0]) + +def WinCalRecordIssRefAtCurrentLoc(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalRecordIssRefAtCurrentLoc command to WinCal. Record the ISS, + indicated by the index, reference as being the current location + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalRecordIssRefAtCurrentLoc",IssIdx) + + +def SaveProjectAsTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Save Project as Template window which saves the project template + if the user clicks ok. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsTemplateDialog") + + +def CreateProjectFromTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the New Project from Template dialog which allows the user to select a + template and create a new project. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CreateProjectFromTemplateDialog") + + +def WinCalGetNumPortsAndProbes(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns Max Ports and Number of probes connected to a port + API Status: internal + Returns: + MaxPorts:int + NumPortsConnectedtoProbes:int + Command Timeout: 1000 + Example:WinCalGetNumPortsAndProbes + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumPortsAndProbes") + global WinCalGetNumPortsAndProbes_Response + if not "WinCalGetNumPortsAndProbes_Response" in globals(): WinCalGetNumPortsAndProbes_Response = namedtuple("WinCalGetNumPortsAndProbes_Response", "MaxPorts,NumPortsConnectedtoProbes") + return WinCalGetNumPortsAndProbes_Response(int(rsp[0]),int(rsp[1])) + +def WinCalGetProbeInfoForPort(VnaPortNum:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the properties from one probe, based on the passed in index. Pass in a + physical VNA port number that is less than or equal to Max Probes from the call + to CalGetNumPortsAndProbes + API Status: internal + Args: + VnaPortNum:int = 1 + Returns: + IsSelected:int + BaseProbe:str + Options:str + PhysicalOrient:str + IsDual:int + IsSymmetric:int + SignalConfig:str + SelectedPitch:int + Command Timeout: 1000 + Example:WinCalGetProbeInfoForPort 1 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetProbeInfoForPort",VnaPortNum) + global WinCalGetProbeInfoForPort_Response + if not "WinCalGetProbeInfoForPort_Response" in globals(): WinCalGetProbeInfoForPort_Response = namedtuple("WinCalGetProbeInfoForPort_Response", "IsSelected,BaseProbe,Options,PhysicalOrient,IsDual,IsSymmetric,SignalConfig,SelectedPitch") + return WinCalGetProbeInfoForPort_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),str(rsp[6]),int(rsp[7])) + +def GetMachineState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current state of the machine. + API Status: internal + Returns: + MachineState:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMachineState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowAboutDialog(Pid:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the help about dialog for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowAboutDialog",Pid) + + +def ShowSplashScreen(Pid:int="", TimeoutMs:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + TimeoutMs:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowSplashScreen",Pid,TimeoutMs) + + +def CloseSplashScreen(Pid:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseSplashScreen",Pid) + + +def GetLastFourProjects(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the last four project files that were opened. + API Status: internal + Returns: + ProjectFile1:str + ProjectFile2:str + ProjectFile3:str + ProjectFile4:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLastFourProjects") + global GetLastFourProjects_Response + if not "GetLastFourProjects_Response" in globals(): GetLastFourProjects_Response = namedtuple("GetLastFourProjects_Response", "ProjectFile1,ProjectFile2,ProjectFile3,ProjectFile4") + return GetLastFourProjects_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def WinCalExecuteCommand(Command:str=""): + """ + Sends the WinCalExecuteCommand command to WinCal and returns the response + string. + API Status: published + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalExecuteCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDemoMode(TurnOnDemoMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will return an error if its called with any other parameter as 0. + API Status: internal + Args: + TurnOnDemoMode:int = 1 + Command Timeout: 5000 + Example:SetDemoMode 0 + """ + MessageServerInterface.sendSciCommand("SetDemoMode",TurnOnDemoMode) + + +def ChangeDemoRsp(Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Override a command with a demo response. The command will not reach its + destination but the supplied demo response will be returned. An active overide + for a command will be removed if the provided timeout is negative. Format: [ID] + [Time] [ErrorCode]:[Response] - Id: command id in hex withoud leding 0x - Time: + time in ms between command and response, negativ to reset demo mode for this + command - Errorcode: 0 for success, everything else indicates an error - + Response: response string + API Status: internal + Args: + Param:str = "" + Command Timeout: 5000 + Example:ChangeDemoRsp 31 200 0:5000.0 5000.0 8500 + """ + MessageServerInterface.sendSciCommand("ChangeDemoRsp",Param) + + +def GetDemoMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will always return 0. + API Status: internal + Returns: + DemoModeOn:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDemoMode") + return int(rsp[0]) + +def ResetNetworkPort(Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + (Re)sets the IP address and listen port of the socket to which the NetworkDriver + tries to connect to (IP address and listen port of Kernel socket). Dummy + implementation for Kernel to support backwards. + API Status: internal + Args: + Param:str = "" + Command Timeout: 10000 + Example:ResetNetworkPort 192.168.3.1 10000 + """ + MessageServerInterface.sendSciCommand("ResetNetworkPort",Param) + + +def GetNDriverClientStatus(ClientNum:int="", Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets status information about the connection NetworkDriver to Kernel. Socket + Error is the Windows socket error, Description the Windows socket error + description. If Socket Error is 0, the description 'Registered' informs that the + Kernel is ready to receive Remote Commands. + API Status: internal + Args: + ClientNum:int = 1 + Param:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:GetNDriverClientStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetNDriverClientStatus",ClientNum,Param) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OverrideCommandTimeout(CmdID:int="", TimeoutMilliSec:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows specifying a separate command timeout for a single instance + of a command. This is especially useful if the application that receives a + command knows how long a command will take. This command had been added for + SoakTime-handling of StepNextDie. A safe guess for the timeout of StepNextDie is + 5s. + API Status: internal + Args: + CmdID:int = 0 + TimeoutMilliSec:int = 1000 + Command Timeout: 5000 + Example:OverrideCommandTimeout 3234 20000 + """ + MessageServerInterface.sendSciCommand("OverrideCommandTimeout",CmdID,TimeoutMilliSec) + + +def ShutdownVelox(IgnorePID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shutdown all Velox applications in an ordered fashion. When this command returns + success, all non-mandatory apps are closed and the mandatory ones will follow + shortly + API Status: internal + Args: + IgnorePID:int = 0 + Command Timeout: 120000 + Example:ShutdownVelox + """ + MessageServerInterface.sendSciCommand("ShutdownVelox",IgnorePID) + + +def InitializationDone(CommandGroup:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Registration of an application can be delayed. To trigger this behavior, + RegisterProberApp has to be called with flag 3 set (0x04). From + RegisterProberApp to the time this command is sent, the application can send + commands but can't receive commands. This is necessary because some application + have to communicate with others during initialization and can not handle + commands properly during this time. The command group is necessary because of + architectural reasons (By design, the command receiver does not now the sender + of a command). + API Status: internal + Args: + CommandGroup:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("InitializationDone",CommandGroup) + + +def StepFirstZProfilePoint(XPos:Decimal="", YPos:Decimal="", NumberOfPoints:int="", NumberOfEPoints:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command goes to the first Z Profile Point, adjusts Z (in the automatic mode + only) and pauses after it (even in the automatic mode) + API Status: internal + Args: + XPos:Decimal = 0 + YPos:Decimal = 0 + NumberOfPoints:int = 0 + NumberOfEPoints:int = 0 + Command Timeout: 60000 + Example:StepFirstZProfilePoint 10000 20000 5 5 + """ + MessageServerInterface.sendSciCommand("StepFirstZProfilePoint",XPos,YPos,NumberOfPoints,NumberOfEPoints) + + +def StepNextZProfilePoint(Point:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calculates a delta value for the current point and then moves to + the specified point (if it's presented) or to the next one. Note, that in case + of the automatic Z detecting a return ZDelta parameter is a value for the + current point, but in case of the semiautomatic mode the command returns ZDelta + as a value for a previous tested point. If the profiling is finished this + command will return #807 error (End of the profile). Point indices are started + from 1 (1 is first, 2 is second, and so on). + API Status: internal + Args: + Point:int = 0 + Returns: + XPos:Decimal + YPos:Decimal + Delta:Decimal + CurPoint:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 60000 + Example:StepNextZProfilePoint 1 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextZProfilePoint",Point) + global StepNextZProfilePoint_Response + if not "StepNextZProfilePoint_Response" in globals(): StepNextZProfilePoint_Response = namedtuple("StepNextZProfilePoint_Response", "XPos,YPos,Delta,CurPoint,NumberOfPoints,NumberOfEPoints") + return StepNextZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def SetZProfileOptions(ProfileMode:str="", SepSpeed:Decimal="", ProfileSensor:str="", Stage:str="", SearchSpeed:Decimal="", Gap:Decimal="", Units:str="", ClearElectronics:int="", ClearRefZ:int="", Inaccuracy:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets some Z Profile Program Options remotely. + API Status: internal + Args: + ProfileMode:str = "S" + SepSpeed:Decimal = 25 + ProfileSensor:str = "E" + Stage:str = "C" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + Units:str = "Y" + ClearElectronics:int = 1 + ClearRefZ:int = 1 + Inaccuracy:Decimal = 0 + Command Timeout: 10000 + Example:SetZProfileOptions S 25 E C 50 10 Y 1 1 0 + """ + MessageServerInterface.sendSciCommand("SetZProfileOptions",ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy) + + +def GetZProfileOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return predefined settings of the Z Profile Program. + API Status: internal + Returns: + ProfileMode:str + SepSpeed:Decimal + ProfileSensor:str + Stage:str + SearchSpeed:Decimal + Gap:Decimal + Units:str + ClearElectronics:int + ClearRefZ:int + Inaccuracy:Decimal + Command Timeout: 10000 + Example:GetZProfileOptions + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOptions") + global GetZProfileOptions_Response + if not "GetZProfileOptions_Response" in globals(): GetZProfileOptions_Response = namedtuple("GetZProfileOptions_Response", "ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy") + return GetZProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str(rsp[6]),int(rsp[7]),int(rsp[8]),Decimal(rsp[9])) + +def OpenZProfileFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command opens the file inside of the Z Profiling. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 240000 + Example:OpenZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("OpenZProfileFile",FileName) + global OpenZProfileFile_Response + if not "OpenZProfileFile_Response" in globals(): OpenZProfileFile_Response = namedtuple("OpenZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return OpenZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def SaveZProfileFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves the current profile in the specified file. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:SaveZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("SaveZProfileFile",FileName) + global SaveZProfileFile_Response + if not "SaveZProfileFile_Response" in globals(): SaveZProfileFile_Response = namedtuple("SaveZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return SaveZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def ReadZProfile(NewOrigin:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read a profile from the ProberBench Electronics II to the application. Return a + number of available points. + API Status: internal + Args: + NewOrigin:str = "Z" + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:ReadZProfile H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfile",NewOrigin) + return int(rsp[0]) + +def SetZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Uploads the current profile to the ProberBench Electronics II. Returns a number + of written points. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:SetZProfile + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfile") + return int(rsp[0]) + +def CloseZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Z-Profiling application. + API Status: internal + Command Timeout: 5000 + Example:CloseZProfiling + """ + MessageServerInterface.sendSciCommand("CloseZProfiling") + + +def SetZProfileStartPoint(X:Decimal="", Y:Decimal="", PosRef:str="", Units:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets new start point for the profile. All points of the profile will be shifted + accordingly. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + PosRef:str = "Z" + Units:str = "Y" + Command Timeout: 10000 + Example:SetZProfileStartPoint 0 0 H Y + """ + MessageServerInterface.sendSciCommand("SetZProfileStartPoint",X,Y,PosRef,Units) + + +def GetZProfilingStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the profiling process. If this status is true it means the + process is started. + API Status: internal + Returns: + Started:int + Command Timeout: 10000 + Example:GetZProfilingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilingStatus") + return int(rsp[0]) + +def StopZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the profiling process. + API Status: internal + Command Timeout: 10000 + Example:StopZProfiling + """ + MessageServerInterface.sendSciCommand("StopZProfiling") + + +def SetZProfileOrigin(Pos:str="", X:Decimal="", Y:Decimal="", Z:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an origin for the profile. If the origin position is H the command ignores + X and Y parameters. If Z is None the command clears Z value of the origin. + Otherwise it tries to extract a double value from the string and set it. + API Status: internal + Args: + Pos:str = "H" + X:Decimal = 0 + Y:Decimal = 0 + Z:str = "None" + Command Timeout: 10000 + Example:SetZProfileOrigin H 0 0 None + """ + MessageServerInterface.sendSciCommand("SetZProfileOrigin",Pos,X,Y,Z) + + +def GetZProfileOrigin(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current parameters of the profile origin. If the origin Z has no value + the return string for it will be None, otherwise it consists a double value of + the profile Z. + API Status: internal + Returns: + Pos:str + X:Decimal + Y:Decimal + Z:str + Command Timeout: 10000 + Example:GetZProfileOrigin + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOrigin") + global GetZProfileOrigin_Response + if not "GetZProfileOrigin_Response" in globals(): GetZProfileOrigin_Response = namedtuple("GetZProfileOrigin_Response", "Pos,X,Y,Z") + return GetZProfileOrigin_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def StartZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Command Timeout: 10000 + Example:StartZProfiling + """ + MessageServerInterface.sendSciCommand("StartZProfiling") + + +def ZProfileWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 36000000 + Example:ZProfileWafer + """ + rsp = MessageServerInterface.sendSciCommand("ZProfileWafer") + global ZProfileWafer_Response + if not "ZProfileWafer_Response" in globals(): ZProfileWafer_Response = namedtuple("ZProfileWafer_Response", "NumberOfPoints,NumberOfEPoints") + return ZProfileWafer_Response(int(rsp[0]),int(rsp[1])) + +def GetZProfileStartPoint(PosRef:str="", Units:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current start point of the profile by using given units and a + reference position. + API Status: internal + Args: + PosRef:str = "Z" + Units:str = "Y" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + Example:GetZProfileStartPoint H Y + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileStartPoint",PosRef,Units) + global GetZProfileStartPoint_Response + if not "GetZProfileStartPoint_Response" in globals(): GetZProfileStartPoint_Response = namedtuple("GetZProfileStartPoint_Response", "X,Y") + return GetZProfileStartPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AddZProfilePoint(X:Decimal="", Y:Decimal="", After:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Adds new point to the profile at the end (default) or after the given point. + Returns an index of new point and a number of all points in the profile. Point + indices are started from 1. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + After:int = 0 + Returns: + Index:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:AddZProfilePoint 50000 50000 + """ + rsp = MessageServerInterface.sendSciCommand("AddZProfilePoint",X,Y,After) + global AddZProfilePoint_Response + if not "AddZProfilePoint_Response" in globals(): AddZProfilePoint_Response = namedtuple("AddZProfilePoint_Response", "Index,NumberOfPoints,NumberOfEPoints") + return AddZProfilePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def DeleteZProfilePoint(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deletes the point from the profile. Returns a number of all and enabled points + in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:DeleteZProfilePoint 11 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteZProfilePoint",Index) + global DeleteZProfilePoint_Response + if not "DeleteZProfilePoint_Response" in globals(): DeleteZProfilePoint_Response = namedtuple("DeleteZProfilePoint_Response", "NumberOfPoints,NumberOfEPoints") + return DeleteZProfilePoint_Response(int(rsp[0]),int(rsp[1])) + +def SetZProfilePointStatus(Index:int="", Status:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Status:str = "0" + Command Timeout: 10000 + Example:SetZProfilePointStatus 11 E + """ + MessageServerInterface.sendSciCommand("SetZProfilePointStatus",Index,Status) + + +def GetZProfilePointStatus(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + Status:str + Command Timeout: 10000 + Example:GetZProfilePointStatus 11 + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilePointStatus",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def PreciseZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + All points are covered by triangles, each vertex of the triangle is a point of + the profile. The centers of the triangles are new points of the profile. If all + three vertexes of the triangle are tested points the new point will be marked as + tested also and has Z value equal to average Z of all three vertexes. Otherwise + the new point will be marked as untested. The command returns a number of points + in the profile after the update. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:PreciseZProfile + """ + rsp = MessageServerInterface.sendSciCommand("PreciseZProfile") + return int(rsp[0]) + +def CloseTableView(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the TableView application. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CloseTableView") + + +def StepChuckSite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Site no. of the chuck table view. + If no Site no is specified the chuck will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSite",Site) + return int(rsp[0]) + +def StepChuckSubsite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Subsite no. of the chuck subsite + table view. If no Subsite no. is specified the chuck will step automatically to + the next logical site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSubsite",Site) + return int(rsp[0]) + +def StepScopeSite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the microscope stage to the requested Site no. of the scope table view. If + no Site no is specified the scope will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepScopeSite",Site) + return int(rsp[0]) + +def StepProbeSite(Probe:int="", Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the specified probe to the requested Site no. of the Probe no table view. + If no Site no. is specified the Probe no. will step automatically to the next + logical site location. The first site in the table is site 1. + API Status: internal + Args: + Probe:int = -1 + Site:int = -1 + Returns: + ProbeRet:int + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepProbeSite",Probe,Site) + global StepProbeSite_Response + if not "StepProbeSite_Response" in globals(): StepProbeSite_Response = namedtuple("StepProbeSite_Response", "ProbeRet,SiteRet") + return StepProbeSite_Response(int(rsp[0]),int(rsp[1])) + +def ReadChuckSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual chuck site position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSitePosition") + global ReadChuckSitePosition_Response + if not "ReadChuckSitePosition_Response" in globals(): ReadChuckSitePosition_Response = namedtuple("ReadChuckSitePosition_Response", "Site,X,Y") + return ReadChuckSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSitePosition") + global ReadScopeSitePosition_Response + if not "ReadScopeSitePosition_Response" in globals(): ReadScopeSitePosition_Response = namedtuple("ReadScopeSitePosition_Response", "Site,X,Y") + return ReadScopeSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadProbeSitePosition(Probe:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Args: + Probe:int = -1 + Returns: + ProbeRet:int + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSitePosition",Probe) + global ReadProbeSitePosition_Response + if not "ReadProbeSitePosition_Response" in globals(): ReadProbeSitePosition_Response = namedtuple("ReadProbeSitePosition_Response", "ProbeRet,Site,X,Y") + return ReadProbeSitePosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadChuckSubsitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the chuck subsite position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSubsitePosition") + global ReadChuckSubsitePosition_Response + if not "ReadChuckSubsitePosition_Response" in globals(): ReadChuckSubsitePosition_Response = namedtuple("ReadChuckSubsitePosition_Response", "Site,X,Y") + return ReadChuckSubsitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def StepFirstDie(ClearBins:int="", RecalcRoute:int=""): + """ + Steps the chuck to the first die of the wafer map. Returns the row and column + number of the actual die location after the move is completed. If ClearBins is + 1, all binning data will be cleared from dies. If yes the route will be + recalculated. All dies marked to skip during the last test (marked to skip with + SetDieStatus) will be eliminated from the route. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + DieX:int + DieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstDie",ClearBins,RecalcRoute) + global StepFirstDie_Response + if not "StepFirstDie_Response" in globals(): StepFirstDie_Response = namedtuple("StepFirstDie_Response", "DieX,DieY,CurSite,LastSiteIndex") + return StepFirstDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def StepNextDie(CDieX:int="", CDieY:int="", Site:int=""): + """ + Steps the chuck to the specified x,y die location of the wafer map. If no + command data is passed, the chuck automatically steps to the next logical wafer + map die location. Returns the row and column number of the actual die location + after the move is completed. In addition, the SubDie location, and total number + of SubDies is also returned. If Site (i.e. SubDie) is -1, the chuck will move + to SubDie 0, on the next die; in this case, the first 2 parameters are ignored. + If sent without parameters, it will literally 'step to the next die'. When using + this command from shared code, use SendWithoutParameter(). + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDie",CDieX,CDieY,Site) + global StepNextDie_Response + if not "StepNextDie_Response" in globals(): StepNextDie_Response = namedtuple("StepNextDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepNextDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinMapDie(Bin:int="", CDieX:int="", CDieY:int=""): + """ + Assigns the bin information to the wafer map at the current die, unless a row + and column is specified. Inks the device if the real time inking option (of the + wafer map) is enabled. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 30000 + Example:BinMapDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinMapDie",Bin,CDieX,CDieY) + global BinMapDie_Response + if not "BinMapDie_Response" in globals(): BinMapDie_Response = namedtuple("BinMapDie_Response", "RDieX,RDieY") + return BinMapDie_Response(int(rsp[0]),int(rsp[1])) + +def AssignMapBins(Bins:str=""): + """ + Assigns the pass or fail information to the actual bin value. Redundant to + SetBinCode. + API Status: published + Args: + Bins:str = "" + Command Timeout: 10000 + Example:AssignMapBins PFFFFFF + """ + MessageServerInterface.sendSciCommand("AssignMapBins",Bins) + + +def StepFailedBack(): + """ + Steps the chuck back the number of consecutive failed dies (goes back to the + last known good die) and returns the number of consecutive failed dies. + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedBack") + return int(rsp[0]) + +def StepFailedForward(): + """ + Steps the chuck forward the number of consecutive failed dies (goes to next + untested die). + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedForward") + return int(rsp[0]) + +def ReadMapPosition(Pos:int="", FromPos:str=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 1-based, + the first value is 1, not 0. M_pnCurSite returns the currently selected + Subdie (1-based) or 0 if no Subdie is currently selected. This command (i.e. + ReadMapPosition) has been included for legacy support. ReadMapPosition2 is + the preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition",Pos,FromPos) + global ReadMapPosition_Response + if not "ReadMapPosition_Response" in globals(): ReadMapPosition_Response = namedtuple("ReadMapPosition_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadMapYield(): + """ + Returns the actual wafer map yield data information. + API Status: published + Returns: + TotalDies:int + TestedDies:int + Passed:int + Failed:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapYield") + global ReadMapYield_Response + if not "ReadMapYield_Response" in globals(): ReadMapYield_Response = namedtuple("ReadMapYield_Response", "TotalDies,TestedDies,Passed,Failed") + return ReadMapYield_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinStepDie(Bin:int="", CDieX:int="", CDieY:int="", Site:int=""): + """ + Bins the current die and steps the chuck to the next selected die location of + the wafer map (default) or steps to the specified Column and Row position, if + these values are passed. In contrast to StepNextDie, the BinStepDie command + will only step from die to die while staying on the current subdie. It will not + step through the subdies so it cannot be used for subdie stepping. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + Example:BinStepDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinStepDie",Bin,CDieX,CDieY,Site) + global BinStepDie_Response + if not "BinStepDie_Response" in globals(): BinStepDie_Response = namedtuple("BinStepDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinStepDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetMapHome(DieX:int="", DieY:int=""): + """ + If the command has no parameters it sets the current position as home position + both for the wafer map and for the chuck. Otherwise, it changes the wafer map + home position using the given die coordinates. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapHome",DieX,DieY) + + +def SaveMapFile(FileName:str="", FileType:str=""): + """ + Saves current map file with specified name. + API Status: published + Args: + FileName:str = "" + FileType:str = "m" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SaveMapFile",FileName,FileType) + + +def SetWaferMapMode(Mode:str=""): + """ + Enables or disables an external mode for the application. In the external mode, + all controls are disabled. The application handles all its remote commands in + both modes. Special interactive modes can also be turned on. + API Status: published + Args: + Mode:str = "" + Returns: + ModeType:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("SetWaferMapMode",Mode) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetWaferMapMode(ModeType:str=""): + """ + Returns whether the application is in external mode or not. + API Status: published + Args: + ModeType:str = "" + Returns: + Mode:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapMode",ModeType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferNum(Number:str=""): + """ + Specifies the wafer number. + API Status: published + Args: + Number:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferNum",Number) + + +def GetWaferNum(): + """ + Returns the wafer number for the current wafer. + API Status: published + Returns: + Number:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferNum") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferID(ID:str=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferID",ID) + + +def GetWaferID(): + """ + Returns the wafer ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetProductID(ID:str=""): + """ + Specifies the product ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetProductID",ID) + + +def GetProductID(): + """ + Displays the product ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProductID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DoInkerRun(): + """ + Instructs the WaferMap to perform an ink run on the current wafer. Returns the + number of dies which were inked during the inker run. + API Status: published + Returns: + InkedDies:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("DoInkerRun") + return int(rsp[0]) + +def CloseWaferMap(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Wafer Map application. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseWaferMap") + + +def GetNumSelectedDies(): + """ + Gets the number of dies in the map which are selected for probing. + API Status: published + Returns: + SelectedDies:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedDies") + return int(rsp[0]) + +def GetSelectedDieCoords(Die:int=""): + """ + Given the index of a selected die in the range [1..NumSelectedDies], returns the + column and row indices for the selected die. + API Status: published + Args: + Die:int = 0 + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedDieCoords",Die) + global GetSelectedDieCoords_Response + if not "GetSelectedDieCoords_Response" in globals(): GetSelectedDieCoords_Response = namedtuple("GetSelectedDieCoords_Response", "DieX,DieY") + return GetSelectedDieCoords_Response(int(rsp[0]),int(rsp[1])) + +def StepNextDieOffset(XOffset:Decimal="", YOffset:Decimal="", CDieX:int="", CDieY:int=""): + """ + Moves to a user-specified offset within a die. The optional col row params can + be used to specify the die. If they are omitted, WaferMap moves to the specified + offset within the next selected die. + API Status: published + Args: + XOffset:Decimal = 0 + YOffset:Decimal = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDieOffset",XOffset,YOffset,CDieX,CDieY) + global StepNextDieOffset_Response + if not "StepNextDieOffset_Response" in globals(): StepNextDieOffset_Response = namedtuple("StepNextDieOffset_Response", "RDieX,RDieY") + return StepNextDieOffset_Response(int(rsp[0]),int(rsp[1])) + +def ReadMapPosition2(Pos:int="", FromPos:str=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 0-based, + the first value is 0, not 1. M_pnCurSite returns the currently selected Subdie + (0-based) or -1 if no Subdie is currently selected. This command is the + preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition2",Pos,FromPos) + global ReadMapPosition2_Response + if not "ReadMapPosition2_Response" in globals(): ReadMapPosition2_Response = namedtuple("ReadMapPosition2_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition2_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def DeleteSubDie2(Site:int=""): + """ + Deletes selected subdie. The SubDie collection is 0-based, the first value is 0, + not 1. This command is the preferred method for deleting a selected + subdie. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie2",Site) + return int(rsp[0]) + +def DeleteAllSubDie(): + """ + Deletes all subdies for all dies. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("DeleteAllSubDie") + + +def GetDieLabel(DieX:int="", DieY:int=""): + """ + Returns a label from the wafer map at the current die, unless a row and column + are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabel",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabel(Label:str="", DieX:int="", DieY:int=""): + """ + Assigns a label to the wafer map at the current die, unless a row and column are + specified. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabel",Label,DieX,DieY) + + +def StepNextSubDie(Site:int=""): + """ + Steps the chuck to the specified SubDie number relative to the current die + origin of the wafer map. Returns the SubDie number of the actual die location + after the move is completed and the total number of subdies. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextSubDie",Site) + global StepNextSubDie_Response + if not "StepNextSubDie_Response" in globals(): StepNextSubDie_Response = namedtuple("StepNextSubDie_Response", "CurSite,LastSiteIndex") + return StepNextSubDie_Response(int(rsp[0]),int(rsp[1])) + +def OpenWaferMap(FileName:str=""): + """ + Opens a Wafer Map file. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenWaferMap",FileName) + + +def SetDieResult(Result:str="", DieX:int="", DieY:int=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResult",Result,DieX,DieY) + + +def GetDieResult(DieX:int="", DieY:int=""): + """ + Returns a measurement result from the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResult",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResult(Result:str="", DieX:int="", DieY:int="", Site:int=""): + """ + Assigns a measurement result to the wafer die map at the current die and the + current subdie, unless a subdie, row, and column are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResult",Result,DieX,DieY,Site) + + +def GetDieMapResult(DieX:int="", DieY:int="", Site:int=""): + """ + Returns a measurement result from the wafer map at the current die and current + subdie, unless a row, column, and subdie are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResult",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BinSubDie(Bin:int="", CDieX:int="", CDieY:int="", Site:int=""): + """ + Assigns the bin information for the current subdie in the current die, unless a + subdie, row, and column are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("BinSubDie",Bin,CDieX,CDieY,Site) + global BinSubDie_Response + if not "BinSubDie_Response" in globals(): BinSubDie_Response = namedtuple("BinSubDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinSubDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetSubDieData(Site:int="", X:Decimal="", Y:Decimal="", Label:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + Site:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieData",Site,X,Y,Label) + + +def GetSubDieData(Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + X:Decimal + Y:Decimal + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieData",Site) + global GetSubDieData_Response + if not "GetSubDieData_Response" in globals(): GetSubDieData_Response = namedtuple("GetSubDieData_Response", "CurSite,X,Y,Label") + return GetSubDieData_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def GetMapHome(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the home die location of the WaferMap. + API Status: internal + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapHome") + global GetMapHome_Response + if not "GetMapHome_Response" in globals(): GetMapHome_Response = namedtuple("GetMapHome_Response", "DieX,DieY") + return GetMapHome_Response(int(rsp[0]),int(rsp[1])) + +def GetMapDims(): + """ + Returns the parameters for the current wafer. + API Status: published + Returns: + MapType:str + XIndex:Decimal + YIndex:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapDims") + global GetMapDims_Response + if not "GetMapDims_Response" in globals(): GetMapDims_Response = namedtuple("GetMapDims_Response", "MapType,XIndex,YIndex,Columns,Rows") + return GetMapDims_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetWaferMapParams(Diameter:Decimal="", DieWidth:Decimal="", DieHeight:Decimal="", FlatLength:Decimal="", FlatAngle:int="", XOffset:Decimal="", YOffset:Decimal="", EdgeArea:Decimal=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are percentages. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def SetRectMapParams(DieWidth:Decimal="", DieHeight:Decimal="", Columns:int="", Rows:int=""): + """ + Creates the rectangle wafer with specified parameters. + API Status: published + Args: + DieWidth:Decimal = 0 + DieHeight:Decimal = 0 + Columns:int = 0 + Rows:int = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetRectMapParams",DieWidth,DieHeight,Columns,Rows) + + +def StepToDie(DieNumber:int="", Site:int=""): + """ + Steps the chuck to the die location specified by the die number of the wafer + map. If no command data is passed, the chuck automatically steps to the next + logical wafer map die location. Returns the row and column number of the actual + die location after the move is completed. In addition, the SubDie location, and + total number of SubDies is also returned. + API Status: published + Args: + DieNumber:int = -1 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepToDie",DieNumber,Site) + global StepToDie_Response + if not "StepToDie_Response" in globals(): StepToDie_Response = namedtuple("StepToDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepToDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetMapOrientation(UseOrientationCornerForShift:int=""): + """ + Returns parameters of the map coordinate system. + API Status: published + Args: + UseOrientationCornerForShift:int = 0 + Returns: + Orientation:int + OriginShiftX:int + OriginShiftY:int + UseAlphas:int + UseIOs:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapOrientation",UseOrientationCornerForShift) + global GetMapOrientation_Response + if not "GetMapOrientation_Response" in globals(): GetMapOrientation_Response = namedtuple("GetMapOrientation_Response", "Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs") + return GetMapOrientation_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetMapOrientation(Orientation:int="", OriginShiftX:int="", OriginShiftY:int="", UseAlphas:int="", UseIOs:int="", UseOrientationCornerForShift:int=""): + """ + Sets up new map origin and new coordinate system after that. + API Status: published + Args: + Orientation:int = 0 + OriginShiftX:int = 0 + OriginShiftY:int = 0 + UseAlphas:int = 0 + UseIOs:int = 1 + UseOrientationCornerForShift:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapOrientation",Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs,UseOrientationCornerForShift) + + +def SetDieStatus(DieX:int="", DieY:int="", Status:str=""): + """ + Sets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieStatus",DieX,DieY,Status) + + +def GetDieStatus(DieX:int="", DieY:int=""): + """ + Gets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieStatus",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieStatus(Site:int="", Status:str=""): + """ + Sets the SubDie status. The SubDie collection is 0-based, the first value is 0, + not 1. + API Status: published + Args: + Site:int = 0 + Status:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieStatus",Site,Status) + + +def GetSubDieStatus(Site:int=""): + """ + Returns the SubDie status. The SubDie collection is 0-based, the first value is + 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieStatus",Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetBinCode(Bin:int=""): + """ + Returns the Die size from the current map. + API Status: published + Args: + Bin:int = 0 + Returns: + Chars:str + Color:int + Status:str + Inker1:int + Inker2:int + Inker3:int + Inker4:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinCode",Bin) + global GetBinCode_Response + if not "GetBinCode_Response" in globals(): GetBinCode_Response = namedtuple("GetBinCode_Response", "Chars,Color,Status,Inker1,Inker2,Inker3,Inker4") + return GetBinCode_Response(str(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetBinCode(Bin:int="", Chars:str="", Color:int="", Status:str="", Inker1:int="", Inker2:int="", Inker3:int="", Inker4:int=""): + """ + Appends the Bin information to a bin code. + API Status: published + Args: + Bin:int = 0 + Chars:str = "" + Color:int = 0 + Status:str = "" + Inker1:int = 0 + Inker2:int = 0 + Inker3:int = 0 + Inker4:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinCode",Bin,Chars,Color,Status,Inker1,Inker2,Inker3,Inker4) + + +def GetDieDataAsNum(CDieIndex:int=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Number is absent it uses the current die + on the wafer. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsNum",CDieIndex) + global GetDieDataAsNum_Response + if not "GetDieDataAsNum_Response" in globals(): GetDieDataAsNum_Response = namedtuple("GetDieDataAsNum_Response", "RDieIndex,DieX,DieY,Bin,Result") + return GetDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsNum(DieIndex:int="", Bin:int="", Result:str=""): + """ + Sets the Die Information. If the Die Number is invalid it returns an error. + API Status: published + Args: + DieIndex:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsNum",DieIndex,Bin,Result) + + +def GetSubDieDataAsNum(CDieIndex:int="", Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsNum",CDieIndex,Site) + global GetSubDieDataAsNum_Response + if not "GetSubDieDataAsNum_Response" in globals(): GetSubDieDataAsNum_Response = namedtuple("GetSubDieDataAsNum_Response", "RDieIndex,DieX,DieY,CurSite,Bin,Result") + return GetSubDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsNum(DieIndex:int="", Site:int="", Bin:int="", Result:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieIndex:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsNum",DieIndex,Site,Bin,Result) + + +def GetDieDataAsColRow(CDieX:int="", CDieY:int=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Column and Row are absent it uses the + current die on the wafer. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsColRow",CDieX,CDieY) + global GetDieDataAsColRow_Response + if not "GetDieDataAsColRow_Response" in globals(): GetDieDataAsColRow_Response = namedtuple("GetDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,Bin,Result") + return GetDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsColRow(DieX:int="", DieY:int="", Bin:int="", Result:str=""): + """ + Sets the Data in the Row Column format. If the Die is invalid it returns an + error. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsColRow",DieX,DieY,Bin,Result) + + +def GetSubDieDataAsColRow(CDieX:int="", CDieY:int="", Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsColRow",CDieX,CDieY,Site) + global GetSubDieDataAsColRow_Response + if not "GetSubDieDataAsColRow_Response" in globals(): GetSubDieDataAsColRow_Response = namedtuple("GetSubDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,CurSite,Bin,Result") + return GetSubDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsColRow(DieX:int="", DieY:int="", Site:int="", Bin:int="", Result:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsColRow",DieX,DieY,Site,Bin,Result) + + +def SelectAllDiesForProbing(DoSelectAll:int="", DoEdgeDies:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables all dies. + API Status: internal + Args: + DoSelectAll:int = 0 + DoEdgeDies:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SelectAllDiesForProbing",DoSelectAll,DoEdgeDies) + + +def GetMapName(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current WaferMap Filename. + API Status: internal + Returns: + Name:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapName") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetLotID(ID:str=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetLotID",ID) + + +def GetLotID(): + """ + Returns the Lot ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLotID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StepFirstCluster(ClearBins:int="", RecalcRoute:int=""): + """ + Steps the chuck to the first die cluster of the cluster map. If clusters are not + defined, the first Die is used. Returns the row and column information of the + actual cluster and die location after the move is completed. Switches to remote + control if the "Disable Velox" flag is set in the external options window. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstCluster",ClearBins,RecalcRoute) + global StepFirstCluster_Response + if not "StepFirstCluster_Response" in globals(): StepFirstCluster_Response = namedtuple("StepFirstCluster_Response", "ClusterX,ClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepFirstCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def StepNextCluster(CClusterX:int="", CClusterY:int=""): + """ + Steps the chuck to the specified x,y cluster die location of the cluster map. If + no command data is passed, the chuck automatically steps to the next logical + cluster map location. If clusters are not defined, the Die information is used. + Returns the row and column number of the actual die location after the move is + completed. + API Status: published + Args: + CClusterX:int = 0 + CClusterY:int = 0 + Returns: + RClusterX:int + RClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextCluster",CClusterX,CClusterY) + global StepNextCluster_Response + if not "StepNextCluster_Response" in globals(): StepNextCluster_Response = namedtuple("StepNextCluster_Response", "RClusterX,RClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepNextCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetMapRoute(MoveMode:str="", StartColumn:str="", StartRow:str="", MoveParam:str=""): + """ + Specifies the Move Path for the probe station inside the Wafer Map. Optimization + is done for the shortest move way for the station. + API Status: published + Args: + MoveMode:str = "B" + StartColumn:str = "L" + StartRow:str = "T" + MoveParam:str = "H" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapRoute",MoveMode,StartColumn,StartRow,MoveParam) + + +def GetMapRoute(): + """ + Returns the specified move path for the probe station inside the Wafer Map. + API Status: published + Returns: + MoveMode:str + StartColumn:str + StartRow:str + MoveParam:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapRoute") + global GetMapRoute_Response + if not "GetMapRoute_Response" in globals(): GetMapRoute_Response = namedtuple("GetMapRoute_Response", "MoveMode,StartColumn,StartRow,MoveParam") + return GetMapRoute_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetClusterParams(UseClusters:int="", ClusterWidth:int="", ClusterHeight:int="", TestIncomplete:int=""): + """ + Specifies the clusters parameters. + API Status: published + Args: + UseClusters:int = 0 + ClusterWidth:int = 1 + ClusterHeight:int = 1 + TestIncomplete:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterParams",UseClusters,ClusterWidth,ClusterHeight,TestIncomplete) + + +def GetClusterParams(): + """ + Returns current clusters parameters. + API Status: published + Returns: + UseClusters:int + ClusterWidth:int + ClusterHeight:int + TestIncomplete:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterParams") + global GetClusterParams_Response + if not "GetClusterParams_Response" in globals(): GetClusterParams_Response = namedtuple("GetClusterParams_Response", "UseClusters,ClusterWidth,ClusterHeight,TestIncomplete") + return GetClusterParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def NewWaferMap(): + """ + Deletes current wafer map, sub dies and binning information; then creates new + wafer map with defaults parameters. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("NewWaferMap") + + +def AddSubDie(X:Decimal="", Y:Decimal="", Label:str=""): + """ + Adds new subdie at the end of the table. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("AddSubDie",X,Y,Label) + return int(rsp[0]) + +def DeleteSubDie(Site:int=""): + """ + Deletes selected subdie. The SubDie collection is 1-based, the first value is 1, + not 0. If 0 is passed in as the subdie index, WaferMap will delete all subdies + for all dies.This command (i.e. DeleteSubDie) has been included for legacy + support. DeleteSubDie2 is the preferred method for deleting a selected + subdie. DeleteAllSubDie is the preferred method for deleting all subdies for all + dies. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie",Site) + return int(rsp[0]) + +def GetNumSelectedClusters(): + """ + Gets the number of clusters in the map which are selected for probing. + API Status: published + Returns: + SelectedClusters:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedClusters") + return int(rsp[0]) + +def GetSelectedClusterCoords(ClusterIndex:int=""): + """ + Given the index of a selected cluster in the range [1..NumSelectedClusters], + returns the column and row indices for the selected cluster. + API Status: published + Args: + ClusterIndex:int = 0 + Returns: + ClusterX:int + ClusterY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedClusterCoords",ClusterIndex) + global GetSelectedClusterCoords_Response + if not "GetSelectedClusterCoords_Response" in globals(): GetSelectedClusterCoords_Response = namedtuple("GetSelectedClusterCoords_Response", "ClusterX,ClusterY") + return GetSelectedClusterCoords_Response(int(rsp[0]),int(rsp[1])) + +def GetClusterDieStatus(ClusterX:int="", ClusterY:int="", DieX:int="", DieY:int=""): + """ + Gets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterDieStatus",ClusterX,ClusterY,DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetClusterDieStatus(ClusterX:int="", ClusterY:int="", DieX:int="", DieY:int="", Status:str=""): + """ + Sets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterDieStatus",ClusterX,ClusterY,DieX,DieY,Status) + + +def OpenBinCodeTable(FileName:str=""): + """ + Opens a Bin Code Table file (.bct) with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenBinCodeTable",FileName) + + +def SaveBinCodeTable(FileName:str=""): + """ + Saves bin code table to a file with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SaveBinCodeTable",FileName) + + +def SetBinTableSize(BinsSize:int=""): + """ + Sets size of the bin code table. This is the size of bins used in statistics and + binning. + API Status: published + Args: + BinsSize:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinTableSize",BinsSize) + + +def GetBinTableSize(): + """ + Gets size of the bin code table. + API Status: published + Returns: + BinsSize:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinTableSize") + return int(rsp[0]) + +def StepFailedClusterBack(): + """ + Steps the chuck the consecutive failed clusters back (goes back to the last + known good cluster) and returns the number of consecutive failed clusters. + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterBack") + return int(rsp[0]) + +def StepFailedClusterForward(): + """ + Steps the chuck the consecutive failed clusters forward and returns the number + of consecutive failed clusters (goes to next untested cluster). + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterForward") + return int(rsp[0]) + +def GoToWaferHome(): + """ + Moves the chuck to the wafer home position. + API Status: published + Command Timeout: 6000000 + """ + MessageServerInterface.sendSciCommand("GoToWaferHome") + + +def GetWaferInfo(): + """ + Returns a number of all units marked to test. Note that TestSites is a number of + all sites for all dies. + API Status: published + Returns: + ClustersCount:int + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferInfo") + global GetWaferInfo_Response + if not "GetWaferInfo_Response" in globals(): GetWaferInfo_Response = namedtuple("GetWaferInfo_Response", "ClustersCount,DiesCount,SitesCount") + return GetWaferInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetClusterInfo(Cluster:int=""): + """ + Returns a number of all dies and sites marked to test in the given cluster. + API Status: published + Args: + Cluster:int = 0 + Returns: + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterInfo",Cluster) + global GetClusterInfo_Response + if not "GetClusterInfo_Response" in globals(): GetClusterInfo_Response = namedtuple("GetClusterInfo_Response", "DiesCount,SitesCount") + return GetClusterInfo_Response(int(rsp[0]),int(rsp[1])) + +def GetDieInfo(Die:int=""): + """ + Returns a number of sites marked to test in the given die. + API Status: published + Args: + Die:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieInfo",Die) + return int(rsp[0]) + +def ConvertToAlphas(Start:int="", Finish:int=""): + """ + Returns a string of the alpha column coordinates for the given range divided by + spaces. + API Status: published + Args: + Start:int = 0 + Finish:int = 0 + Returns: + Alphas:str + Command Timeout: 240000 + """ + rsp = MessageServerInterface.sendSciCommand("ConvertToAlphas",Start,Finish) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetActiveLayer(Layer:str=""): + """ + Sets new active layer. + API Status: published + Args: + Layer:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetActiveLayer",Layer) + + +def GetActiveLayer(): + """ + Returns current active layer. + API Status: published + Returns: + Layer:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetActiveLayer") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieRefPoint(RefX:Decimal="", RefY:Decimal=""): + """ + Sets a new reference point for the die. This point is NOT used for die stepping, + nor for subdie stepping. When using the "Chuck Position from Reference" WaferMap + GUI setting, the Die Reference Point can be set to be more representative of the + actual reference location within the die. A setting of (0.0, 0.0) is defined as + the upper left corner of the die. All subdie coordinates are relative to upper + left corner of the die. + API Status: published + Args: + RefX:Decimal = 0 + RefY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieRefPoint",RefX,RefY) + + +def GetDieRefPoint(): + """ + Returns current reference point for the die. For details see SetDieRefPoint + command. + API Status: published + Returns: + RefX:Decimal + RefY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieRefPoint") + global GetDieRefPoint_Response + if not "GetDieRefPoint_Response" in globals(): GetDieRefPoint_Response = namedtuple("GetDieRefPoint_Response", "RefX,RefY") + return GetDieRefPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ClearAllBins(): + """ + Clears all binning data in the wafer map. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ClearAllBins") + + +def SetWindowState(State:str="", Window:str=""): + """ + Has sense in the application only (not for ActiveX controls). It shows or hides + a window. All parameters are case-insensitive. + API Status: published + Args: + State:str = "s" + Window:str = "setup" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWindowState",State,Window) + + +def SetCurrentBin(Bin:int="", ButtonStatus:int=""): + """ + Sets the current bin for the application. Second parameter allows to enable or + disable "Mark with Bin" mode in the application. + API Status: published + Args: + Bin:int = 0 + ButtonStatus:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetCurrentBin",Bin,ButtonStatus) + + +def GetCurrentBin(): + """ + Returns the current bin in the application. + API Status: published + Returns: + Bin:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetCurrentBin") + return int(rsp[0]) + +def ReadClusterPosition(Pos:int="", FromPos:str=""): + """ + Returns the actual wafer map cluster position. If the cluster probing is + disabled, the command will assume a cluster of size 1x1. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + DieX:int + DieY:int + DieIndex:int + ClusterWidth:int + ClusterHeight:int + EnabledDies:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadClusterPosition",Pos,FromPos) + global ReadClusterPosition_Response + if not "ReadClusterPosition_Response" in globals(): ReadClusterPosition_Response = namedtuple("ReadClusterPosition_Response", "ClusterX,ClusterY,ClusterIndex,DieX,DieY,DieIndex,ClusterWidth,ClusterHeight,EnabledDies") + return ReadClusterPosition_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str("" if len(rsp) < 9 else ' '.join(rsp[8:]))) + +def GetWaferMapParams(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are percentages. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams") + global GetWaferMapParams_Response + if not "GetWaferMapParams_Response" in globals(): GetWaferMapParams_Response = namedtuple("GetWaferMapParams_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def GetRectMapParams(): + """ + Creates a rectangular wafermap with specified parameters. + API Status: published + Returns: + DieWidth:Decimal + DieHeight:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetRectMapParams") + global GetRectMapParams_Response + if not "GetRectMapParams_Response" in globals(): GetRectMapParams_Response = namedtuple("GetRectMapParams_Response", "DieWidth,DieHeight,Columns,Rows") + return GetRectMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SyncMapHome(X:Decimal="", Y:Decimal=""): + """ + Tries to find an appropriate position in the wafer for the current chuck + position. X and Y describe the chuck position of the wafer center relatively to + the chuck zero position. If the wafer position is found the command sets it as + the wafer map home position and sets the current chuck position as the chuck + home position. If there is no corresponding wafer position the command returns + error 701. Command is used by AutoAlign for the BuildMap feature. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SyncMapHome",X,Y) + + +def SetWaferProfileOptions(ProfileSensor:str="", SearchSpeed:Decimal="", Gap:Decimal="", SuccessRatio:Decimal="", ProfDistX:Decimal="", ProfDistY:Decimal=""): + """ + Sets some WaferMap profiling options remotely. + API Status: published + Args: + ProfileSensor:str = "e" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + SuccessRatio:Decimal = 75 + ProfDistX:Decimal = 0 + ProfDistY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferProfileOptions",ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY) + + +def GetWaferProfileOptions(): + """ + Returns predefined settings of the WaferMap profiling options. + API Status: published + Returns: + ProfileSensor:str + SearchSpeed:Decimal + Gap:Decimal + SuccessRatio:Decimal + ProfDistX:Decimal + ProfDistY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfileOptions") + global GetWaferProfileOptions_Response + if not "GetWaferProfileOptions_Response" in globals(): GetWaferProfileOptions_Response = namedtuple("GetWaferProfileOptions_Response", "ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY") + return GetWaferProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def StartWaferProfiling(DoContinue:int=""): + """ + Starts the profiling process. To determine the current profiling state, use + GetWaferProfilingStatus command. + API Status: published + Args: + DoContinue:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StartWaferProfiling",DoContinue) + + +def GetWaferProfilingStatus(): + """ + Returns status of the profiling process. If this status is true, the process is + started. + API Status: published + Returns: + Started:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfilingStatus") + return int(rsp[0]) + +def StopWaferProfiling(): + """ + Stops the profiling process. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StopWaferProfiling") + + +def DoWaferProfiling(): + """ + Profiles the wafer and returns a status of the profiling as an error code. + API Status: published + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfiling") + + +def DoWaferProfilingOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Profiles the wafer and returns a status of the profiling as an error code. + Executes profiling using the off axis camera + API Status: internal + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfilingOffAxis") + + +def GetSubDieLabel(DieX:int="", DieY:int="", Site:int=""): + """ + Returns a label from the wafer map at the current die and current subdie, unless + a row, column, and subdie are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabel",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabel(Label:str="", DieX:int="", DieY:int="", Site:int=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, row, and column are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabel",Label,DieX,DieY,Site) + + +def GetSubDieLabelAsNum(CDieIndex:int="", Site:int=""): + """ + Returns a label from the wafer map the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabelAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabelAsNum(Label:str="", CDieIndex:int="", Site:int=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabelAsNum",Label,CDieIndex,Site) + + +def GetDieLabelAsNum(CDieIndex:int=""): + """ + Returns a label from the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabelAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabelAsNum(Label:str="", CDieIndex:int=""): + """ + Assigns a label to the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabelAsNum",Label,CDieIndex) + + +def GetHomeDieOffset(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the XY offset from the reference position of the Home Die to wafer + center in chuck coordinates. + API Status: internal + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetHomeDieOffset") + global GetHomeDieOffset_Response + if not "GetHomeDieOffset_Response" in globals(): GetHomeDieOffset_Response = namedtuple("GetHomeDieOffset_Response", "X,Y") + return GetHomeDieOffset_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetWaferMapParams2(Diameter:Decimal="", DieWidth:Decimal="", DieHeight:Decimal="", FlatLength:Decimal="", FlatAngle:int="", XOffset:Decimal="", YOffset:Decimal="", EdgeArea:Decimal=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are microns. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams2",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def GetWaferMapParams2(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are microns. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams2") + global GetWaferMapParams2_Response + if not "GetWaferMapParams2_Response" in globals(): GetWaferMapParams2_Response = namedtuple("GetWaferMapParams2_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams2_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def SetWaferTestAngle(Angle:int=""): + """ + This command sets the Wafer Test Angle. This is different from the notch angle + and allows rotating the WaferMap. + API Status: published + Args: + Angle:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferTestAngle",Angle) + + +def GetWaferTestAngle(): + """ + This returns the Wafer Test Angle. This is different from the notch angle and + allows rotating the WaferMap. + API Status: published + Returns: + Angle:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferTestAngle") + return int(rsp[0]) + +def LoadPreMappedDiesTable(FileName:str="", ClearMap:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads the Pre-Mapped Dies Table file with specified name. + API Status: internal + Args: + FileName:str = "" + ClearMap:int = 1 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("LoadPreMappedDiesTable",FileName,ClearMap) + + +def GetPreMappedDieInfo(DieX:int="", DieY:int=""): + """ + This command is valid when a PreMapped Dies Table has been loaded. Returns + values at the current die, unless a column (M_pnDieX) and row (M_pnDieY) are + specified. Returns actual (as measured during the Pre-Mapping) x, y, z, and + theta die positions. Also returns whether or not Z and Theta are being used. + This command is only valid when a Pre-Mapped Dies Table has been loaded. If a + PreMapped Dies Table has NOT been loaded, ERR_IllegalParameters (715) is + returned. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + UseZ:int + UseTheta:int + ActualX:Decimal + ActualY:Decimal + ActualZ:Decimal + Theta:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPreMappedDieInfo",DieX,DieY) + global GetPreMappedDieInfo_Response + if not "GetPreMappedDieInfo_Response" in globals(): GetPreMappedDieInfo_Response = namedtuple("GetPreMappedDieInfo_Response", "UseZ,UseTheta,ActualX,ActualY,ActualZ,Theta") + return GetPreMappedDieInfo_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def GetDieResultAsNum(CDieIndex:int=""): + """ + Returns a measurement result from the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResultAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieResultAsNum(Result:str="", CDieIndex:int=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResultAsNum",Result,CDieIndex) + + +def GetDieMapResultAsNum(CDieIndex:int="", Site:int=""): + """ + Returns a measurement result from the wafer map the current die and the current + subdie, unless a subdie, and die number are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResultAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResultAsNum(Result:str="", CDieIndex:int="", Site:int=""): + """ + Assigns a measurement result to the wafer die map at the current die at the + current subdie, unless a subdie, and die number are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResultAsNum",Result,CDieIndex,Site) + + +def MapEdgeDies(Enable:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables edge dies for test + API Status: internal + Args: + Enable:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("MapEdgeDies",Enable) + + +def GetSpectrumData(DataPath:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows access to read any data item in Spectrum explorer. GetSpectrumData + AlignWafer/ProjectData/Mark1/ChuckPosition/X GetSpectrumData Chuck + Camera/Camera Settings/Shutter + API Status: internal + Args: + DataPath:str = "" + Returns: + Value:str + Command Timeout: 6000 + Example:GetSpectrumData Chuck Camera/Camera Settings/Shutter + """ + rsp = MessageServerInterface.sendSciCommand("GetSpectrumData",DataPath) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumData(PathAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows changing any data item in Spectrum explorer. Works independent of access + level. SetSpectrumData AlignWafer/ProjectData/Mark1/ChuckPosition/X=1000 + SetSpectrumData Chuck Camera/Camera Settings/Shutter=17 + API Status: internal + Args: + PathAndValue:str = "" + Command Timeout: 6000 + Example:SetSpectrumData Scope Camera/Camera Settings/Shutter=17 + """ + MessageServerInterface.sendSciCommand("SetSpectrumData",PathAndValue) + + +def ReadVMPosition(ToolName:str="", XY:int="", Z:int="", Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the current chuck and microscope position and sets them as + new controller or chuck and microscope positions. The command was originally used + by ReAlignWizard but may be removed in the future because of direct access to + tooldata within Spectrum. + API Status: internal + Args: + ToolName:str = "" + XY:int = 1 + Z:int = 0 + Model:int = -1 + Command Timeout: 60000 + Example:ReadVMPosition AlignWafer 1 0 0 + """ + MessageServerInterface.sendSciCommand("ReadVMPosition",ToolName,XY,Z,Model) + + +def MoveToVMPosition(ToolName:str="", XYChuck:int="", ZChuck:int="", XYScope:int="", ZScope:int="", Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command moves to trained stages positions of a requested tool. Command is + used by ReAlignWizard to move to the trained positions for AutoAlign and + DetectWaferHeight. + API Status: internal + Args: + ToolName:str = "" + XYChuck:int = 1 + ZChuck:int = 1 + XYScope:int = 0 + ZScope:int = 0 + Model:int = -1 + Command Timeout: 120000 + Example:MoveToVMPosition AlignWafer 1 0 0 0 0 + """ + MessageServerInterface.sendSciCommand("MoveToVMPosition",ToolName,XYChuck,ZChuck,XYScope,ZScope,Model) + + +def ShapeTracker(SetHome:int="", AutoEdgeFind:int="", FileName:str=""): + """ + ShapeTracker automatically tracks the shape of a substrate (e.g. a broken wafer) + to determine the contour of it. The data will be memorized as xy coordinates of + contour points referenced to the home position. These Points are written to a + file after tracking the shape. + API Status: published + Args: + SetHome:int = 1 + AutoEdgeFind:int = 0 + FileName:str = "" + Command Timeout: 600000 + Example:ShapeTracker 1 + """ + MessageServerInterface.sendSciCommand("ShapeTracker",SetHome,AutoEdgeFind,FileName) + + +def DetectWaferHeight(SetStartPosition:int="", Synchronize:int="", ChuckX:Decimal="", ChuckY:Decimal=""): + """ + Synchronizes chuck and top camera in X, Y and Z. Then the wafer surface is + focused on the trained chuck position or the manual adjusted reference position. + This tool uses the FindFocus tool with its own Range. + API Status: published + Args: + SetStartPosition:int = 0 + Synchronize:int = 0 + ChuckX:Decimal = -1 + ChuckY:Decimal = -1 + Returns: + PositionX:Decimal + PositionY:Decimal + WaferHeight:Decimal + SynchGap:Decimal + ZOffset:Decimal + Stage:str + Command Timeout: 300000 + Example:DetectWaferHeight 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("DetectWaferHeight",SetStartPosition,Synchronize,ChuckX,ChuckY) + global DetectWaferHeight_Response + if not "DetectWaferHeight_Response" in globals(): DetectWaferHeight_Response = namedtuple("DetectWaferHeight_Response", "PositionX,PositionY,WaferHeight,SynchGap,ZOffset,Stage") + return DetectWaferHeight_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def CheckSpectrumPlugin(Plugin:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command checks if a plugin is trained and returns a string of error/warning + messages including information about what is not trained, setup for the tool to + run. + API Status: internal + Args: + Plugin:str = "" + Returns: + PluginAvailable:int + Message:str + Command Timeout: 1000 + Example:CheckSpectrumPlugin AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("CheckSpectrumPlugin",Plugin) + global CheckSpectrumPlugin_Response + if not "CheckSpectrumPlugin_Response" in globals(): CheckSpectrumPlugin_Response = namedtuple("CheckSpectrumPlugin_Response", "PluginAvailable,Message") + return CheckSpectrumPlugin_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AutoAlign(SetValue:int="", SkipSettingHome:int=""): + """ + Executes the AutoAlign tool to do a theta alignment of the wafer with optional + index calculation or thermal expansion measurement. The command will update home + if home was trained. It will only move to its trained chuck/scope position + before starting the alignment if the option "MoveToTrainedXYPosition" and/or + "MoveToTrainedZPosition" is true. + API Status: published + Args: + SetValue:int = 0 + SkipSettingHome:int = 0 + Command Timeout: 300000 + Example:AutoAlign 1 + """ + MessageServerInterface.sendSciCommand("AutoAlign",SetValue,SkipSettingHome) + + +def SetCameraQuiet(Active:int=""): + """ + Activates/deactivates the camera quiet mode. (Applies only to ATM300A and + SPS300/SUMMIT200 stations.) The camera quiet mode deactivates the chuck, + platen and contact view camera and triggers a digital output which + connects/disconnects these cameras firewire connection to the PC. + API Status: published + Args: + Active:int = 0 + Command Timeout: 30000 + Example:SetCameraQuiet 1 + """ + MessageServerInterface.sendSciCommand("SetCameraQuiet",Active) + + +def SetRefDieOffset(RefDieCol:int="", RefDieRow:int="", RefDieDistToCentreX:Decimal="", RefDieDistToCentreY:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is based on the SetMapOrientation command. It allows shifting the + center of the reference die to the center of the wafer. + API Status: internal + Args: + RefDieCol:int = 0 + RefDieRow:int = 0 + RefDieDistToCentreX:Decimal = 0 + RefDieDistToCentreY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetRefDieOffset",RefDieCol,RefDieRow,RefDieDistToCentreX,RefDieDistToCentreY) + + +def AlignWafer(TrackPosition:int=""): + """ + Performs a two-point alignment and moves chuck to the trained align position. XY + correction is made afterwards to calculate the new home position. + API Status: published + Args: + TrackPosition:int = 0 + Returns: + ThetaOffset:Decimal + Command Timeout: 120000 + Example:AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("AlignWafer",TrackPosition) + return Decimal(rsp[0]) + +def AlignChip(): + """ + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). The + current chip is assumed to be in the region of interest when the command is + called. + API Status: published + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChip + """ + rsp = MessageServerInterface.sendSciCommand("AlignChip") + global AlignChip_Response + if not "AlignChip_Response" in globals(): AlignChip_Response = namedtuple("AlignChip_Response", "ThetaOffset,XOffset,YOffset") + return AlignChip_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def FindFocus(StepCount:int="", Range:Decimal=""): + """ + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. + API Status: published + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocus 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocus",StepCount,Range) + global FindFocus_Response + if not "FindFocus_Response" in globals(): FindFocus_Response = namedtuple("FindFocus_Response", "ZPosition,Stage") + return FindFocus_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAux(AuxSiteID:int=""): + """ + Performs an automated aux site alignment in XYZ. Tool can correct reference + position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAux 1 + """ + MessageServerInterface.sendSciCommand("AlignAux",AuxSiteID) + + +def FindFeature(Model:int="", ReturnDistanceFromModelOrigin:int="", UseSingleImageAcquisition:int=""): + """ + Search user-defined models. Up to 40 different models can be trained. After + training, these models can be searched on screen either by direct user + interaction or from external applications with a remote command. The remote + command returns the X/Y-Positions, angle (degree) and score value (0 - 1.0) for + each instance of the controller found in the region of interest. + API Status: published + Args: + Model:int = 1 + ReturnDistanceFromModelOrigin:int = 0 + UseSingleImageAcquisition:int = 1 + Returns: + Data:str + Command Timeout: 10000 + Example:FindFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("FindFeature",Model,ReturnDistanceFromModelOrigin,UseSingleImageAcquisition) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CloseSpectrum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + CloseSpectrum closes the Spectrum application. Used internally by CommonCommands + during Project loading. Does save configuration data but does not save project + data. + API Status: internal + Command Timeout: 6000 + Example:CloseSpectrum + """ + MessageServerInterface.sendSciCommand("CloseSpectrum") + + +def SnapImage(MountPos:str="", FullPath:str="", SnapShotMode:int=""): + """ + Saves the currently displayed image to the specified file. The image is stored + in the requested file format (bmp, jpg or png). By default. it will save the raw + camera image and an image with the overlays that are currently visible on the + camera view. Using a parameter, one can decide to only save either raw image, + overlay image or both. By Specifying 'ALL' as the mount position, the captured + screenshot will consist of the currently selected camera layout without + providing the raw image. If MountPos and FullPath are empty then the current + camera view with overlays is copied to the clipboard. + API Status: published + Args: + MountPos:str = "Scope" + FullPath:str = "Image.bmp" + SnapShotMode:int = 2 + Command Timeout: 60000 + Example:SnapImage Scope C:/Temp/Image.bmp + """ + MessageServerInterface.sendSciCommand("SnapImage",MountPos,FullPath,SnapShotMode) + + +def SetCameraView(Name:str="", Zoom:int="", LiveVideo:int="", WindowState:int=""): + """ + Switches the desired video window of Spectrum as foreground and active view. The + camera view can be determined over a tool name or the camera mount position. The + second parameter defines the displays zoom factor to be used. Third parameter is + used to toogle the live video. Last parameter can be used to maximize a window. + API Status: published + Args: + Name:str = "" + Zoom:int = 0 + LiveVideo:int = 2 + WindowState:int = 1 + Command Timeout: 6000 + Example:SetCameraView AlignWafer 0 2 2 + """ + MessageServerInterface.sendSciCommand("SetCameraView",Name,Zoom,LiveVideo,WindowState) + + +def SetCameraLight(Name:str="", State:int="", Shutter:Decimal="", Gain:Decimal="", Brightness:int="", Contrast:int="", Sharpness:int="", Illumination:int=""): + """ + Switches the light of the choosen camera on or off. Light values of -1 will + cause that the parameter is not affected. + API Status: published + Args: + Name:str = "" + State:int = 0 + Shutter:Decimal = -1 + Gain:Decimal = -1 + Brightness:int = -1 + Contrast:int = -1 + Sharpness:int = -1 + Illumination:int = -1 + Command Timeout: 6000 + Example:SetCameraLight AlignWafer 1 20 5 + """ + MessageServerInterface.sendSciCommand("SetCameraLight",Name,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination) + + +def ShowWizard(ToolName:str="", MountPosition:str="", AskExecute:int=""): + """ + Starts the wizard of a given tool on the display defined in the tool settings. + Additionally it can start a wizard for training single models with the syntax + e.g. ShowWizard FindFeature/ProjectData/Features/Feature1/Model For the tools + MeasureOnScreen, Calibrate and CameraOrigin you can specify a mount position + e.g. ShowWizard Calibrate Platen + API Status: published + Args: + ToolName:str = "" + MountPosition:str = "" + AskExecute:int = 0 + Returns: + Cancelled:int + Command Timeout: 10000000 + Example:ShowWizard AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("ShowWizard",ToolName,MountPosition,AskExecute) + return int(rsp[0]) + +def ProbeToPadAlign(Position:str=""): + """ + Sets a new Home position. The command is used during ReAlign to search the + trained home reference controller and to calculate the new xy home position. + API Status: published + Args: + Position:str = "H" + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + Command Timeout: 120000 + Example:ProbeToPadAlign H + """ + rsp = MessageServerInterface.sendSciCommand("ProbeToPadAlign",Position) + global ProbeToPadAlign_Response + if not "ProbeToPadAlign_Response" in globals(): ProbeToPadAlign_Response = namedtuple("ProbeToPadAlign_Response", "XOffsetWafer,YOffsetWafer") + return ProbeToPadAlign_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ReadOcrString(): + """ + Reads the wafer ID string from the wafer's surface. Returns the read ID as + string. Requires IDTools license. + API Status: published + Returns: + OcrString:str + Command Timeout: 60000 + Example:ReadOcrString + """ + rsp = MessageServerInterface.sendSciCommand("ReadOcrString") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadBarCode(): + """ + Reads the wafers barcode and decodes it to a string. Requires IDTools license. + API Status: published + Returns: + BarCodeString:str + Command Timeout: 60000 + Example:ReadBarCode + """ + rsp = MessageServerInterface.sendSciCommand("ReadBarCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def Read2DMatrixCode(): + """ + Reads the wafers matrix code and decodes it to a string. Requires IDTools + license. + API Status: published + Returns: + MatrixCodeString:str + Command Timeout: 60000 + Example:Read2DMatrixCode + """ + rsp = MessageServerInterface.sendSciCommand("Read2DMatrixCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumRemote(Activate:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the Spectrum remote mode. In this mode all user interface elements are + hidden and disabled. This is used when Spectrum is hosted inside VeloxPro. + API Status: internal + Args: + Activate:int = 1 + Command Timeout: 10000 + Example:SetSpectrumRemote 1 + """ + MessageServerInterface.sendSciCommand("SetSpectrumRemote",Activate) + + +def GetCameraLight(Name:str=""): + """ + Returns light properties of choosen camera. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + State:int + Shutter:Decimal + Gain:Decimal + Brightness:int + Contrast:int + Sharpness:int + Illumination:int + Command Timeout: 6000 + Example:GetCameraLight Scope + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraLight",Name) + global GetCameraLight_Response + if not "GetCameraLight_Response" in globals(): GetCameraLight_Response = namedtuple("GetCameraLight_Response", "MountPosition,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination") + return GetCameraLight_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7])) + +def GetCameraView(Name:str=""): + """ + Returns the present camera view state of a desired tool or active view. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + Zoom:int + LiveVideo:int + WindowState:int + Command Timeout: 6000 + Example:GetCameraView AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraView",Name) + global GetCameraView_Response + if not "GetCameraView_Response" in globals(): GetCameraView_Response = namedtuple("GetCameraView_Response", "MountPosition,Zoom,LiveVideo,WindowState") + return GetCameraView_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetPattern(ToolName:str="", ModelName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Transforms the specific controller of a demanded tool into a bitmap. This bitmap will + be stored in the same folder as the project file. The command was originally + required by ReAlignWizard and is currently no longer in use. + API Status: internal + Args: + ToolName:str = "" + ModelName:str = "" + Returns: + BitmapPath:str + Command Timeout: 30000 + Example:GetPattern AlignWafer Model1 + """ + rsp = MessageServerInterface.sendSciCommand("GetPattern",ToolName,ModelName) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowPosition(MountPosition:str="", DistPositionX:Decimal="", DistPositionY:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the ChuckCenter under a given camera. When no camera mount position is + given, Spectrum uses active view. If there is an Offset different from zero, + this position will be moved under the camera. + API Status: internal + Args: + MountPosition:str = "" + DistPositionX:Decimal = 0 + DistPositionY:Decimal = 0 + Command Timeout: 60000 + Example:ShowPosition Scope + """ + MessageServerInterface.sendSciCommand("ShowPosition",MountPosition,DistPositionX,DistPositionY) + + +def GetCameraHomePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the home die coordinates when the home die is under the alignment camera + (for instance, the top camera). Command was used during TrainReAlign to get + the start position for Z-Profiling. Command is no longer used. + API Status: internal + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 6000 + Example:GetCameraHomePosition + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraHomePosition") + global GetCameraHomePosition_Response + if not "GetCameraHomePosition_Response" in globals(): GetCameraHomePosition_Response = namedtuple("GetCameraHomePosition_Response", "XPosition,YPosition,ZPosition") + return GetCameraHomePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SynchronizeCamera(MountPos:str="", SynchronizeXY:int="", SynchronizeZ:int=""): + """ + Synchronizes the Platen camera with the calibration mark. The mark is mounted on + the chuck camera. The chuck must be moved to get the mark in view of the + specified camera. + API Status: published + Args: + MountPos:str = "Scope" + SynchronizeXY:int = 0 + SynchronizeZ:int = 0 + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 120000 + Example:SynchronizeCamera S 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SynchronizeCamera",MountPos,SynchronizeXY,SynchronizeZ) + global SynchronizeCamera_Response + if not "SynchronizeCamera_Response" in globals(): SynchronizeCamera_Response = namedtuple("SynchronizeCamera_Response", "XPosition,YPosition,ZPosition") + return SynchronizeCamera_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ProbeCardOCS(UpdateZ:int="", MeasureBothGroups:int=""): + """ + Determines the chuck XYZ axis position where the needles of the probe card are + in focus. The output parameter is the Z axis value in microns from zero of the + new focus height. + API Status: published + Args: + UpdateZ:int = 1 + MeasureBothGroups:int = 1 + Returns: + ZPosition:Decimal + Command Timeout: 360000 + Example:ProbeCardOCS 1 + """ + rsp = MessageServerInterface.sendSciCommand("ProbeCardOCS",UpdateZ,MeasureBothGroups) + return Decimal(rsp[0]) + +def MoveChuckAutoXY(XPosition:Decimal="", YPosition:Decimal="", XSubsiteOffset:Decimal="", YSubsiteOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is sent by WaferMap to trigger AutoXY, AutoZ or VueTrack for each die + move. Automation must be activated/trained before command can be used. Response + is X, Y relative distance of adjustment from requested position. + API Status: internal + Args: + XPosition:Decimal = 0 + YPosition:Decimal = 0 + XSubsiteOffset:Decimal = 0 + YSubsiteOffset:Decimal = 0 + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:MoveChuckAutoXY 5000 10000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveChuckAutoXY",XPosition,YPosition,XSubsiteOffset,YSubsiteOffset) + global MoveChuckAutoXY_Response + if not "MoveChuckAutoXY_Response" in globals(): MoveChuckAutoXY_Response = namedtuple("MoveChuckAutoXY_Response", "XOffset,YOffset") + return MoveChuckAutoXY_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def VueTrackAlign(FullVueTrackAlign:int=""): + """ + Alignment for the next wafer when using VueTrack. + API Status: published + Args: + FullVueTrackAlign:int = 1 + Command Timeout: 6000000 + Example:VueTrackAlign + """ + MessageServerInterface.sendSciCommand("VueTrackAlign",FullVueTrackAlign) + + +def AutoFocusEVue(DistBelow:Decimal="", DistAbove:Decimal="", XOffsetCenter:int="", YOffsetCenter:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is only used internally for software testing and for providing backwards + compatibility with SCPI legacy commands. It executes a focus search using the + eVue focus drive. + API Status: internal + Args: + DistBelow:Decimal = 0 + DistAbove:Decimal = 0 + XOffsetCenter:int = 0 + YOffsetCenter:int = 0 + Returns: + FocusScore:Decimal + ZPosition:Decimal + Command Timeout: 30000 + Example:AutoFocusEVue 200 200 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("AutoFocusEVue",DistBelow,DistAbove,XOffsetCenter,YOffsetCenter) + global AutoFocusEVue_Response + if not "AutoFocusEVue_Response" in globals(): AutoFocusEVue_Response = namedtuple("AutoFocusEVue_Response", "FocusScore,ZPosition") + return AutoFocusEVue_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AutoAlignOffAxis(SetValue:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes the ReAlign Wafer Alignment tool to do a theta alignment of the wafer + with optional index calculation or thermal expansion measurement. AutoAlign is + performed using the Platen camera. Only supported for systems with off-axis + camera. + API Status: internal + Args: + SetValue:int = 0 + Command Timeout: 300000 + Example:AutoAlignOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AutoAlignOffAxis",SetValue) + + +def FindFocusOffAxis(StepCount:int="", Range:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Focus search is performed using the Platen camera. Only supported for + systems with off-axis camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusOffAxis 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusOffAxis",StepCount,Range) + global FindFocusOffAxis_Response + if not "FindFocusOffAxis_Response" in globals(): FindFocusOffAxis_Response = namedtuple("FindFocusOffAxis_Response", "ZPosition,Stage") + return FindFocusOffAxis_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAuxOffAxis(AuxSiteID:int=""): + """ + Performs an automated aux site alignment in XYZ using the Off Axis camera. Tool + can correct reference position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAuxOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AlignAuxOffAxis",AuxSiteID) + + +def FindFocusPlaten(StepCount:int="", Range:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Uses the FindFocus tool settings but always the Platen camera - + independent of the FindFocus mount. This command is used on e.g. BlueRay systems + that have a platen camera but can't use ReAlign/DetectWaferHeight as they don't + have an upward looking camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusPlaten 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusPlaten",StepCount,Range) + global FindFocusPlaten_Response + if not "FindFocusPlaten_Response" in globals(): FindFocusPlaten_Response = namedtuple("FindFocusPlaten_Response", "ZPosition,Stage") + return FindFocusPlaten_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignChipOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). This + command is using the off axis platen camera with functionality of ReAlign. + API Status: internal + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChipOffAxis + """ + rsp = MessageServerInterface.sendSciCommand("AlignChipOffAxis") + global AlignChipOffAxis_Response + if not "AlignChipOffAxis_Response" in globals(): AlignChipOffAxis_Response = namedtuple("AlignChipOffAxis_Response", "ThetaOffset,XOffset,YOffset") + return AlignChipOffAxis_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SelectAZoomLens(Lens:int=""): + """ + Selects 1 of 4 symbolic lenses (4 classified coarse ranges). + API Status: published + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:SelectAZoomLens 1 + """ + MessageServerInterface.sendSciCommand("SelectAZoomLens",Lens) + + +def GetAZoomLens(): + """ + Returns 1 of 4 symbolic lenses, coarse ranges. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:GetAZoomLens + """ + rsp = MessageServerInterface.sendSciCommand("GetAZoomLens") + return int(rsp[0]) + +def AZoomSetupDialog(): + """ + Opens the operator panel. In this window you can change the settings for all + defined lenses. + API Status: published + Command Timeout: 5000 + Example:AZoomSetupDialog + """ + MessageServerInterface.sendSciCommand("AZoomSetupDialog") + + +def MoveAZoomFocus(Focus:int="", Ref:str=""): + """ + Changes the focus magnitude. + API Status: published + Args: + Focus:int = 100 + Ref:str = "R" + Returns: + RetFocus:int + Command Timeout: 10000 + Example:MoveAZoomFocus 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomFocus",Focus,Ref) + return int(rsp[0]) + +def ReadAZoomFocus(): + """ + Returns the focus magnitude. + API Status: published + Returns: + Focus:int + Command Timeout: 5000 + Example:ReadAZoomFocus + """ + rsp = MessageServerInterface.sendSciCommand("ReadAZoomFocus") + return int(rsp[0]) + +def MoveAZoomVelocity(Direction:str="", Velocity:int=""): + """ + Moves the A-Zoom using the set focus speed. + API Status: published + Args: + Direction:str = "" + Velocity:int = 100 + Returns: + RetVelocity:Decimal + Command Timeout: 240000 + Example:MoveAZoomVelocity + 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomVelocity",Direction,Velocity) + return Decimal(rsp[0]) + +def StopAZoom(): + """ + Stops the A-Zoom movements. + API Status: published + Command Timeout: 5000 + Example:StopAZoom + """ + MessageServerInterface.sendSciCommand("StopAZoom") + + +def SetAZoomLight(Light:int=""): + """ + Switches all lights ON or OFF. ON means the values defined by the current lens. + 1 switches the light on, 0 switches the light off. Without parameter toggles + between on an off. + API Status: published + Args: + Light:int = 0 + Command Timeout: 5000 + Example:SetAZoomLight 1 + """ + MessageServerInterface.sendSciCommand("SetAZoomLight",Light) + + +def CloseAZoom(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the OpticalControl application. Used during Project File handling. + API Status: internal + Command Timeout: 5000 + Example:CloseAZoom + """ + MessageServerInterface.sendSciCommand("CloseAZoom") + + +def OCLightVal(Value:int="", Channel:int="", Segment:int=""): + """ + Set the brightness of given channel and segment to the given value. + API Status: published + Args: + Value:int = 0 + Channel:int = 1 + Segment:int = 1 + Command Timeout: 5000 + Example:OCLightVal 128 1 4 + """ + MessageServerInterface.sendSciCommand("OCLightVal",Value,Channel,Segment) + + +def OCLightOn(On:int="", Channel:int=""): + """ + Switch the light (if it has segments then all) in a given channel ON or OFF. + Switch ON - that means: light to the before adjusted brightness. + API Status: published + Args: + On:int = 0 + Channel:int = 1 + Command Timeout: 5000 + Example:OCLightOn 1 1 + """ + MessageServerInterface.sendSciCommand("OCLightOn",On,Channel) + + +def OCSetZoomLevel(Zoom:int="", Motor:int=""): + """ + Set logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Zoom:int = 0 + Motor:int = 1 + Command Timeout: 5000 + Example:OCSetZoomLevel 50 1 + """ + MessageServerInterface.sendSciCommand("OCSetZoomLevel",Zoom,Motor) + + +def OCGetZoomLevel(Motor:int=""): + """ + Get logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Motor:int = 1 + Returns: + Zoom:int + Command Timeout: 5000 + Example:OCGetZoomLevel 1 + """ + rsp = MessageServerInterface.sendSciCommand("OCGetZoomLevel",Motor) + return int(rsp[0]) + +def StartReAlignTemperature(TargetTemperature:Decimal="", ThetaAlignOnFinish:int="", ContactOnFinish:int=""): + """ + Starts temperature ramping using ReAlign. ReAlign will re-adjust the probes and + wafer during ramping to the new target temperature. Command returns immediately. + The status of temperature ramping must be checked using the + GetReAlignTemperatureStatus command. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + Command Timeout: 5000 + Example:StartReAlignTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartReAlignTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish) + + +def StopReAlignTemperature(): + """ + Stops temperature ramping using ReAlign. + API Status: published + Command Timeout: 10000 + Example:StopReAlignTemperature + """ + MessageServerInterface.sendSciCommand("StopReAlignTemperature") + + +def GetReAlignTemperatureStatus(): + """ + Returns the status of the current temperature ramping using ReAlign process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetReAlignTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignTemperatureStatus") + global GetReAlignTemperatureStatus_Response + if not "GetReAlignTemperatureStatus_Response" in globals(): GetReAlignTemperatureStatus_Response = namedtuple("GetReAlignTemperatureStatus_Response", "StatusId,StatusStr") + return GetReAlignTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReAlign(Repeats:int="", Mode:str="", AlignProbeCard:int="", CorrectZ:int=""): + """ + Performs an automatic realignment of the wafer. This includes measuring the + needle drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck + drift XYZ and optionally a Z-Profile. Alternatively the tool performs a + ProbeToDie Alignment to correct the needle position for the current die. Command + returns once ReAlign is finished or aborted because of an error. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + ZOffsetWafer:Decimal + XOffsetCard:Decimal + YOffsetCard:Decimal + ZOffsetCard:Decimal + Command Timeout: 1000000 + Example:ReAlign 2 H 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + global ReAlign_Response + if not "ReAlign_Response" in globals(): ReAlign_Response = namedtuple("ReAlign_Response", "XOffsetWafer,YOffsetWafer,ZOffsetWafer,XOffsetCard,YOffsetCard,ZOffsetCard") + return ReAlign_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def NextWafer(): + """ + Starts the NextWafer routine. + API Status: published + Returns: + Canceled:int + Command Timeout: 60000000 + Example:NextWafer + """ + rsp = MessageServerInterface.sendSciCommand("NextWafer") + return int(rsp[0]) + +def StartReAlign(Repeats:int="", Mode:str="", AlignProbeCard:int="", CorrectZ:int=""): + """ + Starts an automatic realignment of the wafer. This includes measuring the needle + drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck drift + XYZ and optionally a Z-Profile. Alternatively the tool performs a ProbeToPad + Alignment to correct the needle position for the current die. Command returns + immediately. The status of the asynchronous ReAlign execution must be checked + using the GetReAlignStatus command. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Command Timeout: 60000 + Example:StartReAlign 2 H 0 0 + """ + MessageServerInterface.sendSciCommand("StartReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + + +def StopReAlign(): + """ + Stops the ReAlign procedure. + API Status: published + Command Timeout: 120000 + Example:StopReAlign + """ + MessageServerInterface.sendSciCommand("StopReAlign") + + +def GetReAlignStatus(): + """ + Returns a status of the ReAlign procedure. If the return value is true, ReAlign + is running. + API Status: published + Returns: + Running:int + Command Timeout: 60000 + Example:GetReAlignStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignStatus") + return int(rsp[0]) + +def EnableOverlay(Overlay:int=""): + """ + Allows activating the overlay of the needles for the top camera. + API Status: published + Args: + Overlay:int = 0 + Command Timeout: 6000 + Example:EnableOverlay 0 + """ + MessageServerInterface.sendSciCommand("EnableOverlay",Overlay) + + +def SwitchOffset(Offset:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Switches the offset compensation. Applicable for MicroAlign stations only. + API Status: internal + Args: + Offset:int = 0 + Command Timeout: 60000 + Example:SwitchOffset 1 + """ + MessageServerInterface.sendSciCommand("SwitchOffset",Offset) + + +def TrainFeature(Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command was only implemented for supporting a SCPI legacy command. Does not make + sense in Velox, as there is no default training rectangle on the screen as in + Nucleus. + API Status: internal + Args: + Model:int = 1 + Returns: + Data:str + Command Timeout: 30000 + Example:TrainFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("TrainFeature",Model) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetEvueExposureLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Returns: + Exposure:Decimal + Command Timeout: 10000 + Example:GetEvueExposureLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueExposureLevel") + return Decimal(rsp[0]) + +def SetEvueExposureLevel(Exposure:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Args: + Exposure:Decimal = 0 + Command Timeout: 10000 + Example:SetEvueExposureLevel + """ + MessageServerInterface.sendSciCommand("SetEvueExposureLevel",Exposure) + + +def MoveEvueFocusStage(EvueZ:Decimal="", EvueVelocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the eVue focus stage to a specified position. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + EvueZ:Decimal = 0 + EvueVelocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveEvueFocusStage 1000 + """ + MessageServerInterface.sendSciCommand("MoveEvueFocusStage",EvueZ,EvueVelocity) + + +def GetEvueFocusStagePos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the eVue focus stage. Implemented for supporting + SCPI legacy command. + API Status: internal + Returns: + EvueZ:Decimal + Command Timeout: 5000 + Example:GetEvueFocusStagePos + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueFocusStagePos") + return Decimal(rsp[0]) + +def RunEvueAutoExpose(UseCB:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command runs the AutoExpose function for the eVue. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + UseCB:int = 1 + Command Timeout: 20000 + Example:RunEvueAutoExpose 1 + """ + MessageServerInterface.sendSciCommand("RunEvueAutoExpose",UseCB) + + +def GetEvueZoomLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope that is connected to Velox. On eVue + systems, this command, returns values ranging from 0.5 to 5.0 for a 10x system + and 0.5 to 20.0 for a 40x system. + API Status: internal + Returns: + Zoom:Decimal + Command Timeout: 5000 + Example:GetEvueZoomLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueZoomLevel") + return Decimal(rsp[0]) + +def SetEvueZoomLevel(Zoom:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope or an A-Zoom microscope that is connected to + Velox. On eVue systems, this command sets the proper CCD zoom level to the + appropriate optical path. + API Status: internal + Args: + Zoom:Decimal = 0 + Command Timeout: 5000 + Example:SetEvueZoomLevel 2.0 + """ + MessageServerInterface.sendSciCommand("SetEvueZoomLevel",Zoom) + + +def StartAutomationTemperature(TargetTemperature:Decimal="", ThetaAlignOnFinish:int="", ContactOnFinish:int="", AlignOnFinish:int=""): + """ + Starts temperature ramping using Automation. The Automation (mostly VueTrack) + will re-adjust the probes and wafer during ramping to the new target + temperature. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + AlignOnFinish:int = 1 + Command Timeout: 5000 + Example:StartAutomationTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartAutomationTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish,AlignOnFinish) + + +def StopAutomationTemperature(): + """ + Stops temperature ramping using Automation. + API Status: published + Command Timeout: 10000 + Example:StopAutomationTemperature + """ + MessageServerInterface.sendSciCommand("StopAutomationTemperature") + + +def GetAutomationTemperatureStatus(): + """ + Returns the status of the current temperature ramping using automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetAutomationTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationTemperatureStatus") + global GetAutomationTemperatureStatus_Response + if not "GetAutomationTemperatureStatus_Response" in globals(): GetAutomationTemperatureStatus_Response = namedtuple("GetAutomationTemperatureStatus_Response", "StatusId,StatusStr") + return GetAutomationTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationActive(): + """ + Command to read from Spectrum if Automation (AutoXY, AutoZ or VueTrack) is + active. Command is used by WaferMap to read if it must send MoveChuckAutoXY + instead of MoveChuck + API Status: published + Returns: + Active:int + Command Timeout: 1000 + Example:GetAutomationActive + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationActive") + return int(rsp[0]) + +def AutomationNeedleSearch(NeedleIndex:int="", MoveScope:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + VueTrack vision search of the given needle index. + API Status: internal + Args: + NeedleIndex:int = 1 + MoveScope:int = 1 + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + ZMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationNeedleSearch 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("AutomationNeedleSearch",NeedleIndex,MoveScope) + global AutomationNeedleSearch_Response + if not "AutomationNeedleSearch_Response" in globals(): AutomationNeedleSearch_Response = namedtuple("AutomationNeedleSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore,ZMatchScore") + return AutomationNeedleSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def AutomationReferenceSearch(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + AutomationReferenceSearch exposes the functionality of searching the Automation + reference target via remote command + API Status: internal + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationReferenceSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationReferenceSearch") + global AutomationReferenceSearch_Response + if not "AutomationReferenceSearch_Response" in globals(): AutomationReferenceSearch_Response = namedtuple("AutomationReferenceSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore") + return AutomationReferenceSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def MovePositionersSafe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the configured motorized positioners to a safe position + API Status: internal + Command Timeout: 60000 + Example:MovePositionersSafe + """ + MessageServerInterface.sendSciCommand("MovePositionersSafe") + + +def SetConstantContactMode(IsOn:int="", ForceLastCorrection:int=""): + """ + Starts Constant Contact mode using Automation. The Automation will re-adjust the + wafer during ramping to the new target temperature. + API Status: published + Args: + IsOn:int = 0 + ForceLastCorrection:int = 0 + Command Timeout: 5000 + Example:SetConstantContactMode 1 + """ + MessageServerInterface.sendSciCommand("SetConstantContactMode",IsOn,ForceLastCorrection) + + +def GetConstantContactModeStatus(): + """ + Returns the status of the current ConstantContact automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 5000 + Example:GetConstantContactModeStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetConstantContactModeStatus") + global GetConstantContactModeStatus_Response + if not "GetConstantContactModeStatus_Response" in globals(): GetConstantContactModeStatus_Response = namedtuple("GetConstantContactModeStatus_Response", "StatusId,StatusStr") + return GetConstantContactModeStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetAutomationActive(Activate:int=""): + """ + Command to set if Automation (AutoXY, AutoZ or VueTrack) is active. Command can + be used to e.g. deactivate automation programmatically in case it is no + longer used. When activating automation, the command will return an error in + case it is not possible (e.g. not trained) + API Status: published + Args: + Activate:int = 0 + Command Timeout: 1000 + Example:SetAutomationActive 1 + """ + MessageServerInterface.sendSciCommand("SetAutomationActive",Activate) + + +def AutomationSearchCurrentDie(): + """ + Performs an Automation search and position correction using the current chuck + position. Response is X, Y relative distance of adjustment. + API Status: published + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:AutomationSearchCurrentDie + """ + rsp = MessageServerInterface.sendSciCommand("AutomationSearchCurrentDie") + global AutomationSearchCurrentDie_Response + if not "AutomationSearchCurrentDie_Response" in globals(): AutomationSearchCurrentDie_Response = namedtuple("AutomationSearchCurrentDie_Response", "XOffset,YOffset") + return AutomationSearchCurrentDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def PreMapWafer(): + """ + PreMapWafer finds actual singulated die locations and updates positions used by + WaferMap. + API Status: published + Returns: + NumberOfDies:int + Command Timeout: 14400000 + Example:PreMapWafer + """ + rsp = MessageServerInterface.sendSciCommand("PreMapWafer") + return int(rsp[0]) + +def ISSProbeAlign(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs an probe to pad operation on the ISS with two RF positioners. + API Status: internal + Command Timeout: 6000000 + Example:ISSProbeAlign + """ + MessageServerInterface.sendSciCommand("ISSProbeAlign") + + +def FindWaferCenter(NoManualRecovery:int=""): + """ + FindWaferCenter finds the center of the wafer using edge detection. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:FindWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("FindWaferCenter",NoManualRecovery) + global FindWaferCenter_Response + if not "FindWaferCenter_Response" in globals(): FindWaferCenter_Response = namedtuple("FindWaferCenter_Response", "ChuckX,ChuckY") + return FindWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def LocateHomeDie(NoManualRecovery:int=""): + """ + LocateHomeDie finds the center of the wafer using edge detection and sets the + home position. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:LocateHomeDie + """ + rsp = MessageServerInterface.sendSciCommand("LocateHomeDie",NoManualRecovery) + global LocateHomeDie_Response + if not "LocateHomeDie_Response" in globals(): LocateHomeDie_Response = namedtuple("LocateHomeDie_Response", "ChuckX,ChuckY") + return LocateHomeDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetAutomationProbeLayout(LayoutName:str="", ProbeID:int="", XOffset:Decimal="", YOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stores the provided X or Y offset for the given probe for the specified layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Command Timeout: 10000 + Example:SetAutomationProbeLayout "layout1" 1 100.0 0 + """ + MessageServerInterface.sendSciCommand("SetAutomationProbeLayout",LayoutName,ProbeID,XOffset,YOffset) + + +def DeleteAutomationProbeLayout(LayoutName:str="", ProbeID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Delete the specfied layout. If LayoutName is empty then all layouts are deleted. + If optional ProbeID parmameter is set, it removes just that probe from the + layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 10000 + Example:DeleteAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("DeleteAutomationProbeLayout",LayoutName,ProbeID) + + +def CaptureAutomationProbeLayout(LayoutName:str="", ProbeID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Capture the specfied layout. If optional ProbeID parmameter is set, it captures + just that probe from the layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 30000 + Example:CaptureAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("CaptureAutomationProbeLayout",LayoutName,ProbeID) + + +def MoveToAutomationProbeLayout(LayoutName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move to the probes to specfied layout which are offsets from the trained + positions. + API Status: internal + Args: + LayoutName:str = "" + Command Timeout: 300000 + Example:MoveToAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("MoveToAutomationProbeLayout",LayoutName) + + +def ResetAutomation(): + """ + Reset automation data back to trained values. + API Status: published + Command Timeout: 10000 + Example:ResetAutomation + """ + MessageServerInterface.sendSciCommand("ResetAutomation") + + +def GetWaferCenter(): + """ + GetWaferCenter returns the chuck location (zero based) of the wafer center. It + returns 0 0 if FindWaferCenter has not been executed for the current wafer. + API Status: published + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 10000 + Example:GetWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferCenter") + global GetWaferCenter_Response + if not "GetWaferCenter_Response" in globals(): GetWaferCenter_Response = namedtuple("GetWaferCenter_Response", "ChuckX,ChuckY") + return GetWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def InitEvueFocusStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the eVue focus stage by finding the limit switches + API Status: internal + Command Timeout: 30000 + Example:InitEvueFocusStage + """ + MessageServerInterface.sendSciCommand("InitEvueFocusStage") + + +def EvueSetNumTraceEntriesPreTrigger(NumTraceEntriesPreTrigger:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Args: + NumTraceEntriesPreTrigger:int = 0 + Command Timeout: 30000 + Example:EvueSetNumTraceEntriesPreTrigger 14 + """ + MessageServerInterface.sendSciCommand("EvueSetNumTraceEntriesPreTrigger",NumTraceEntriesPreTrigger) + + +def EvueGetNumTraceEntriesPreTrigger(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Returns: + NumTraceEntriesPreTrigger:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntriesPreTrigger + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntriesPreTrigger") + return int(rsp[0]) + +def EvueStartCaptureServoTrace(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts capturing events in the eVue motion capture log. Capture continues until + the log is full. However, log entries will overwrite the oldest entry until the + trigger event is encountered. Then, {X} events are preserved prior to the + trigger event and the oldest events are only overwritten if they are not part of + that preserved set. + API Status: internal + Command Timeout: 30000 + Example:EvueStartCaptureServoTrace + """ + MessageServerInterface.sendSciCommand("EvueStartCaptureServoTrace") + + +def EvueGetTraceMachineStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current status of the trace machine. Bit fields - bit0 is 1 and bit4 is + 16, etc. bit0 - active and in pre-trigger state bit1 - active and in post- + trigger state bit2 - stopped by servo error, lens crash or lens removal bit3 - + stopped on requested server state entry bit4 - stopped by immediate command + bit5..31 - reserved + API Status: internal + Returns: + TraceMachineStatus:int + Command Timeout: 30000 + Example:EvueGetTraceMachineStatus + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceMachineStatus") + return int(rsp[0]) + +def EvueSetTraceCaptureStopBits(TraceCaptureStopBits:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets condition bits to trigger servo trace capture. Bit fields - bit0 is 1 and + bit4 is 16, etc. bit0 - immediate stop bit1 - stop on servo error, lens crash or + lens removal bit2 - stop on requested server state (defined by bits 4..7) bit3 - + stop on motor move finish bit4..7 - servo state that triggers a trace stop (not + an index but the 4-bit state that, if seen, is the trigger for trace capture) + bit8..31 - reserved + API Status: internal + Args: + TraceCaptureStopBits:int = 0 + Command Timeout: 30000 + Example:EvueSetTraceCaptureStopBits + """ + MessageServerInterface.sendSciCommand("EvueSetTraceCaptureStopBits",TraceCaptureStopBits) + + +def EvueGetNumTraceEntries(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current status of the trace machine. + API Status: internal + Returns: + TraceEntries:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntries + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntries") + return int(rsp[0]) + +def EvueGetTraceEntry(EntryIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the N'th trace entry in the log. + API Status: internal + Args: + EntryIdx:int = 0 + Returns: + CommandedPositionMotorCounts:int + CommandedPositionMicrons:Decimal + MeasuredPositionMotorCounts:int + MeasuredPositionMicrons:Decimal + TimestampMicroseconds:int + ServoStatus:int + PwmVal:int + Command Timeout: 30000 + Example:EvueGetTraceEntry 32 + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceEntry",EntryIdx) + global EvueGetTraceEntry_Response + if not "EvueGetTraceEntry_Response" in globals(): EvueGetTraceEntry_Response = namedtuple("EvueGetTraceEntry_Response", "CommandedPositionMotorCounts,CommandedPositionMicrons,MeasuredPositionMotorCounts,MeasuredPositionMicrons,TimestampMicroseconds,ServoStatus,PwmVal") + return EvueGetTraceEntry_Response(int(rsp[0]),Decimal(rsp[1]),int(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def AutomationRFProbeSearch(ImageFilename:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the distance in X,Y between the center tips of the RF probes. + API Status: internal + Args: + ImageFilename:str = "" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 5000 + Example:AutomationRFProbeSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationRFProbeSearch",ImageFilename) + global AutomationRFProbeSearch_Response + if not "AutomationRFProbeSearch_Response" in globals(): AutomationRFProbeSearch_Response = namedtuple("AutomationRFProbeSearch_Response", "X,Y") + return AutomationRFProbeSearch_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def StartAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the AutoRF calibration sequence. + API Status: internal + Command Timeout: 3000 + Example:StartAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StartAutoRFCalibration") + + +def StopAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the currently running AutoRF calibraiton. + API Status: internal + Command Timeout: 10000 + Example:StopAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StopAutoRFCalibration") + + +def GetAutoRFCalibrationStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the status of the AutoRF calibration sequence. + API Status: internal + Returns: + StatusId:int + StatusStr:str + Command Timeout: 1000 + Example:GetAutoRFCalibrationStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutoRFCalibrationStatus") + global GetAutoRFCalibrationStatus_Response + if not "GetAutoRFCalibrationStatus_Response" in globals(): GetAutoRFCalibrationStatus_Response = namedtuple("GetAutoRFCalibrationStatus_Response", "StatusId,StatusStr") + return GetAutoRFCalibrationStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationLastStepDiagnostics(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the diagnostic state information for the provided index. + API Status: internal + Args: + Index:int = 0 + Returns: + DiagnosticInfo:str + Command Timeout: 5000 + Example:GetAutomationLastStepDiagnostics + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationLastStepDiagnostics",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMNanoChamberState(State:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the WLEM Nano Chamber State. + API Status: internal + Args: + State:str = "Free" + Command Timeout: 5000 + Example:SetWLEMNanoChamberState Free + """ + MessageServerInterface.sendSciCommand("SetWLEMNanoChamberState",State) + + +def GetWLEMNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the WLEM Nano Chamber State. + API Status: internal + Returns: + State:str + Command Timeout: 5000 + Example:GetWLEMNanoChamberState + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMState(State:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMState NCSeal 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMState",State,Value) + + +def GetWLEMState(State:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMState NCSeal + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMState",State) + return int(rsp[0]) + +def GetWLEMSensorValue(Sensor:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the value of a WLEM Sensor. + API Status: internal + Args: + Sensor:str = "O2Concentration" + Returns: + Value:Decimal + Command Timeout: 5000 + Example:GetWLEMSensorValue O2Concentration + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMSensorValue",Sensor) + return Decimal(rsp[0]) + +def SetWLEMOption(Option:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMOption MinimizeToTray 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMOption",Option,Value) + + +def GetWLEMOption(Option:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMOption MinimizeToTray + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMOption",Option) + return int(rsp[0]) + +def NewTesterProject(LotID:str="", TileID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a new Lot/Tile is to be tested. The tester + responds with the correct project name for the test. This is needed because the + prober needs to verify that the correct project is loaded. In case no valid + project is available, the command is returned with an error. + API Status: internal + Args: + LotID:str = "" + TileID:str = "" + Returns: + ProjectName:str + Command Timeout: 30000 + Example:NewTesterProject Lot01 Tile01 + """ + rsp = MessageServerInterface.sendSciCommand("NewTesterProject",LotID,TileID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StartMeasurement(DieColumn:int="", DieRow:int="", ActiveDies:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester to begin measuring (Needles are in correct + position and in contact). The command is responded when the measurement has + finished. The response string holds the binning information separated by comma. + For deactivated dies, a bin value of '0' should be responded. + API Status: internal + Args: + DieColumn:int = 0 + DieRow:int = 0 + ActiveDies:str = "" + Returns: + BinNumbers:str + Command Timeout: 100000 + Example:StartMeasurement 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("StartMeasurement",DieColumn,DieRow,ActiveDies) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def EndOfWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current substrate has + finished. It enables the tester application to save measurement data and/or + prepare for the next substrate. + API Status: internal + Command Timeout: 30000 + Example:EndOfWafer + """ + MessageServerInterface.sendSciCommand("EndOfWafer") + + +def EndOfLot(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current lot has finished. It + enables the tester application to save measurement data and/or prepare for the + next lot. + API Status: internal + Command Timeout: 30000 + Example:EndOfLot + """ + MessageServerInterface.sendSciCommand("EndOfLot") + + +def VerifyProductID(ProductID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProductID that is to be tested. The + tester can respond with an error in case the ProductID is not allowed for + testing. + API Status: internal + Args: + ProductID:str = "" + Command Timeout: 30000 + Example:VerifyProductID Product123 + """ + MessageServerInterface.sendSciCommand("VerifyProductID",ProductID) + + +def VerifyLotID(LotID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the LotID that is to be tested. The tester + can respond with an error in case the LotID is not allowed for testing. + API Status: internal + Args: + LotID:str = "" + Command Timeout: 30000 + Example:VerifyLotID Lot123 + """ + MessageServerInterface.sendSciCommand("VerifyLotID",LotID) + + +def VerifySubstrateID(SubstrateID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the SubstrateID that is to be tested. The + tester can respond with an error in case the SubstrateID is not allowed for + testing. + API Status: internal + Args: + SubstrateID:str = "" + Command Timeout: 30000 + Example:VerifySubstrateID Substrate123 + """ + MessageServerInterface.sendSciCommand("VerifySubstrateID",SubstrateID) + + +def VerifyProbecard(ProbeCard:str="", Touchdowns:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProbecardID and touchdowns that is + used for testing. The tester can respond with an error in case the Probecard is + not allowed for testing. + API Status: internal + Args: + ProbeCard:str = "" + Touchdowns:int = 0 + Command Timeout: 30000 + Example:VerifyProbecard Probecard123 10596 + """ + MessageServerInterface.sendSciCommand("VerifyProbecard",ProbeCard,Touchdowns) + + +def VerifyUserID(User:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the User ID. The tester can respond with + an error in case the User ID is not allowed for testing. + API Status: internal + Args: + User:str = "" + Command Timeout: 30000 + Example:VerifyUserID User123 + """ + MessageServerInterface.sendSciCommand("VerifyUserID",User) + + +def TesterAbort(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the job was aborted and no more test will + happen. + API Status: internal + Command Timeout: 30000 + Example:TesterAbort + """ + MessageServerInterface.sendSciCommand("TesterAbort") + + +def VerifySOTReady(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a wafer is ready for testing which will + immediately start. This command is sent in the recipe sequence "Verify + SOTReady". + API Status: internal + Command Timeout: 30000 + Example:VerifySOTReady + """ + MessageServerInterface.sendSciCommand("VerifySOTReady") + + +def VerifyWaferStart(SubstrateID:str="", CassettePlace:str="", LotID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent in the VeloxPro recipe sequence "Verify Wafer Start" and + informs the tester about the current wafer on the chuck. + API Status: internal + Args: + SubstrateID:str = "" + CassettePlace:str = "" + LotID:str = "" + Command Timeout: 30000 + Example:VerifyWaferStart Wafer01 1 Lot01 + """ + MessageServerInterface.sendSciCommand("VerifyWaferStart",SubstrateID,CassettePlace,LotID) + + +def TesterCassetteInfo(CassetteCmd:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command will be sent after the user selected which wafers are to be tested. + It contains a string which represents the state of each wafer: 0 = empty, 1 = + full (and selected), 2 = error (e.g. double slotted), 3 = unknown, 4 = + deselected + API Status: internal + Args: + CassetteCmd:str = "" + Returns: + CassetteRsp:str + Command Timeout: 30000 + Example:TesterCassetteInfo 0000001110000000010010111 + """ + rsp = MessageServerInterface.sendSciCommand("TesterCassetteInfo",CassetteCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def VerifyProject(ProjectName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent after selecting a project file in the VeloxPro product + setup page. The command sends the name of the project to tester for + verification. + API Status: internal + Args: + ProjectName:str = "" + Command Timeout: 30000 + Example:VerifyProject C:/Users/Public/Documents/Velox/Projects/Test.spp + """ + MessageServerInterface.sendSciCommand("VerifyProject",ProjectName) + + +def TesterAbortWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the test for the current wafer was aborted + and no more tests will happen with the current wafer. The job will continue + though. + API Status: internal + Command Timeout: 30000 + Example:TesterAbortWafer + """ + MessageServerInterface.sendSciCommand("TesterAbortWafer") + + +def DoTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts execution of one test. It returns a bin number or multple bin numbers + when clusters are enabled in the WaferMap (one number for each die in a + cluster). The command starts execution of one test. It returns a bin number or + multple bin numbers when clusters are enabled in the WaferMap (one number for + each die in a cluster). + API Status: internal + Returns: + BitNumber:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DoTTLTest") + return int(rsp[0]) + +def StartTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the test of a wafer. Depending on the cluster definitions queried from + the WaferMap, all clusters or all dies will be tested. The command starts the + test of a wafer. Depending on the cluster definitions queried from the WaferMap + all clusters or all dies will be tested. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("StartTTLTest") + + +def CancelTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the wafer test. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CancelTTLTest") + + +def SetTTLLine(Line:int="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the selected line of PA port. + API Status: internal + Args: + Line:int = 0 + Value:int = 0 + Command Timeout: 10000 + Example:SetTTLLine 2 0 + """ + MessageServerInterface.sendSciCommand("SetTTLLine",Line,Value) + + +def GetTTLLines(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the I/O lines as bit array. + API Status: internal + Returns: + LineA:int + LineB:int + LineC:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLLines") + global GetTTLLines_Response + if not "GetTTLLines_Response" in globals(): GetTTLLines_Response = namedtuple("GetTTLLines_Response", "LineA,LineB,LineC") + return GetTTLLines_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetTTLStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns returns the error 914 if the test is in progress. + API Status: internal + Returns: + ErrCode:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLStatus") + return int(rsp[0]) + +def StartScript(ScriptName:str=""): + """ + Starts the script and returns the response immediately. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000 + Example:StartScript myscript + """ + MessageServerInterface.sendSciCommand("StartScript",ScriptName) + + +def GetRunStatus(ScriptName:str=""): + """ + Command returns information about Communicator status. + API Status: published + Args: + ScriptName:str = "" + Returns: + Running:int + LastError:int + Title:str + Command Timeout: 5000 + Example:GetRunStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetRunStatus",ScriptName) + global GetRunStatus_Response + if not "GetRunStatus_Response" in globals(): GetRunStatus_Response = namedtuple("GetRunStatus_Response", "Running,LastError,Title") + return GetRunStatus_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def CloseCommunicator(): + """ + Command closes the program. Used during ProjectFile handling. + API Status: published + Command Timeout: 10000 + Example:CloseCommunicator + """ + MessageServerInterface.sendSciCommand("CloseCommunicator") + + +def DoScript(ScriptName:str=""): + """ + Executes the script and returns the response afterwards. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000000 + Example:DoScript myscript + """ + MessageServerInterface.sendSciCommand("DoScript",ScriptName) + + +def ReadKernelData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads Kernel Data to KernelSetup (Left Program pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReadKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReadKernelData",SilentMode) + + +def SaveKernelDataAs(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves Kernel Data (Left Program pane) to File. An existing File will be + overwritten. If the Folder does not exist, it will be created + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveKernelDataAs C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("SaveKernelDataAs",FileName) + + +def LoadConfigFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads File Data to KernelSetup (Right Program pane). + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:LoadConfigFile C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("LoadConfigFile",FileName) + + +def ReplaceKernelDataByFileData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces Kernel Data (Left pane) by File Data (Right pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceKernelDataByFileData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceKernelDataByFileData",SilentMode) + + +def ReplaceFileTreeByKernelData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces File Tree (Right pane) by Kernel Data (Left pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceFileTreeByKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceFileTreeByKernelData",SilentMode) + + +def SaveFileTreeAs(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves File Tree (Right pane) to File. An existing File will be overwritten. If + the Folder does not exist, it will be created. + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveFileTreeAs C:/Temp/RCConfigSample2.xml + """ + MessageServerInterface.sendSciCommand("SaveFileTreeAs",FileName) + + +def HeatChuck(Temperature:Decimal="", Unit:str="", ReduceContact:int=""): + """ + Sets a new target temperature and starts the heating or cooling of the chuck. An + answer to the command will be returned after reaching the given temperature and + waiting the soak time or an unexpected interrupt of the process. Given back is + the already reached temperature. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + ReduceContact:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 36000000 + Example:HeatChuck 61.3 C + """ + rsp = MessageServerInterface.sendSciCommand("HeatChuck",Temperature,Unit,ReduceContact) + global HeatChuck_Response + if not "HeatChuck_Response" in globals(): HeatChuck_Response = namedtuple("HeatChuck_Response", "RespTemperature,RespUnit") + return HeatChuck_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetHeaterTemp(Temperature:Decimal="", Unit:str="", UseContactSafety:int=""): + """ + Sets a new target temperature and starts the heating or cooling of the + temperature chuck. The new target temperature is returned immediately as the + command does not wait until heating is complete. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + UseContactSafety:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:SetHeaterTemp 55.5 C + """ + rsp = MessageServerInterface.sendSciCommand("SetHeaterTemp",Temperature,Unit,UseContactSafety) + global SetHeaterTemp_Response + if not "SetHeaterTemp_Response" in globals(): SetHeaterTemp_Response = namedtuple("SetHeaterTemp_Response", "RespTemperature,RespUnit") + return SetHeaterTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetHeaterTemp(Unit:str="", ExternalHeaterID:int=""): + """ + Reads the current temperature of the chuck and determines the status of the + thermal system. + API Status: published + Args: + Unit:str = "Celsius" + ExternalHeaterID:int = 0 + Returns: + RespTemperature:Decimal + RespUnit:str + Status:str + Command Timeout: 60000 + Example:GetHeaterTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterTemp",Unit,ExternalHeaterID) + global GetHeaterTemp_Response + if not "GetHeaterTemp_Response" in globals(): GetHeaterTemp_Response = namedtuple("GetHeaterTemp_Response", "RespTemperature,RespUnit,Status") + return GetHeaterTemp_Response(Decimal(rsp[0]),str(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def EnableHeaterHoldMode(HoldMode:int=""): + """ + Switches the Temperature Chuck devices hold mode on or off. In hold mode the + chuck is heated with a constant current to avoid noise from the temperature + control. The hold mode can be enabled only in HoldReady state. + API Status: published + Args: + HoldMode:int = 1 + Returns: + RespHoldMode:int + Command Timeout: 60000 + Example:EnableHeaterHoldMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterHoldMode",HoldMode) + return int(rsp[0]) + +def StopHeatChuck(): + """ + Stops a pending heating or cooling process. If the device is not at temperature, + the actual temperature is set as target temperature. + API Status: published + Command Timeout: 60000 + Example:StopHeatChuck + """ + MessageServerInterface.sendSciCommand("StopHeatChuck") + + +def GetDewPointTemp(Unit:str=""): + """ + Returns the current dew point temperature, if a dew point sensor is connected. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetDewPointTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetDewPointTemp",Unit) + global GetDewPointTemp_Response + if not "GetDewPointTemp_Response" in globals(): GetDewPointTemp_Response = namedtuple("GetDewPointTemp_Response", "RespTemperature,RespUnit") + return GetDewPointTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetTemperatureChuckOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the currently set temperature chuck options. + API Status: internal + Returns: + UseSoakTime:int + SyncTemp:int + CurrConnection:int + MinTemperature:Decimal + MaxTemperature:Decimal + UsePurge:int + UseDynamicSoakTime:int + UseFixedDieSoakTime:int + UseDynamicDieSoakTime:int + UseEcoMode:int + PurgeOnChamberDoor:int + ForceBypassPurge:int + DoorClosedTime:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTemperatureChuckOptions") + global GetTemperatureChuckOptions_Response + if not "GetTemperatureChuckOptions_Response" in globals(): GetTemperatureChuckOptions_Response = namedtuple("GetTemperatureChuckOptions_Response", "UseSoakTime,SyncTemp,CurrConnection,MinTemperature,MaxTemperature,UsePurge,UseDynamicSoakTime,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime") + return GetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12])) + +def SetTemperatureChuckOptions(UseFixedWaferSoak:int="", SyncTemp:int="", CurrConnection:int="", UsePurge:int="", UseDynamicWaferSoak:int="", UseFixedDieSoakTime:int="", UseDynamicDieSoakTime:int="", UseEcoMode:int="", PurgeOnChamberDoor:int="", ForceBypassPurge:int="", DoorClosedTime:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is used to change the currently set temperature chuck options. + API Status: internal + Args: + UseFixedWaferSoak:int = -1 + SyncTemp:int = -1 + CurrConnection:int = -1 + UsePurge:int = -1 + UseDynamicWaferSoak:int = -1 + UseFixedDieSoakTime:int = -1 + UseDynamicDieSoakTime:int = -1 + UseEcoMode:int = -1 + PurgeOnChamberDoor:int = -1 + ForceBypassPurge:int = -1 + DoorClosedTime:int = -1 + Returns: + UseFixedWaferSoakRsp:int + SyncTempRsp:int + CurrConnectionRsp:int + UsePurgeRsp:int + UseDynamicWaferSoakRsp:int + UseFixedDieSoakTimeRsp:int + UseDynamicDieSoakTimeRsp:int + UseEcoModeRsp:int + PurgeOnChamberDoorRsp:int + ForceBypassPurgeRsp:int + DoorClosedTimeRsp:int + Command Timeout: 300000 + Example:SetTemperatureChuckOptions 1 0 1 1 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetTemperatureChuckOptions",UseFixedWaferSoak,SyncTemp,CurrConnection,UsePurge,UseDynamicWaferSoak,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime) + global SetTemperatureChuckOptions_Response + if not "SetTemperatureChuckOptions_Response" in globals(): SetTemperatureChuckOptions_Response = namedtuple("SetTemperatureChuckOptions_Response", "UseFixedWaferSoakRsp,SyncTempRsp,CurrConnectionRsp,UsePurgeRsp,UseDynamicWaferSoakRsp,UseFixedDieSoakTimeRsp,UseDynamicDieSoakTimeRsp,UseEcoModeRsp,PurgeOnChamberDoorRsp,ForceBypassPurgeRsp,DoorClosedTimeRsp") + return SetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10])) + +def GetHeaterSoak(): + """ + Returns the current soak time values in seconds and the soaking status. + API Status: published + Returns: + FixedWaferSoakTime:int + FixedWaferSoakStatus:int + DynamicWaferSoakTime:Decimal + DynamicWaferSoakStatus:int + FixedDieSoakTime:Decimal + DynamicDieSoakTime:Decimal + FixedDieSoakStatus:int + DynamicDieSoakStatus:int + Command Timeout: 60000 + Example:GetHeaterSoak + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterSoak") + global GetHeaterSoak_Response + if not "GetHeaterSoak_Response" in globals(): GetHeaterSoak_Response = namedtuple("GetHeaterSoak_Response", "FixedWaferSoakTime,FixedWaferSoakStatus,DynamicWaferSoakTime,DynamicWaferSoakStatus,FixedDieSoakTime,DynamicDieSoakTime,FixedDieSoakStatus,DynamicDieSoakStatus") + return GetHeaterSoak_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),int(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),int(rsp[6]),int(rsp[7])) + +def SetHeaterSoak(FixedWaferSoakTime:int="", DynamicWaferSoakTime:Decimal="", FixedDieSoakTime:Decimal="", DynamicDieSoakTime:Decimal=""): + """ + Sets the new soak time values. The unit of the values is seconds. If soak time + is actually running, it may be affected by the change. + API Status: published + Args: + FixedWaferSoakTime:int = 60 + DynamicWaferSoakTime:Decimal = -1 + FixedDieSoakTime:Decimal = -1 + DynamicDieSoakTime:Decimal = -1 + Command Timeout: 60000 + Example:SetHeaterSoak 60 + """ + MessageServerInterface.sendSciCommand("SetHeaterSoak",FixedWaferSoakTime,DynamicWaferSoakTime,FixedDieSoakTime,DynamicDieSoakTime) + + +def EnableHeaterStandby(Standby:int=""): + """ + Switches the power save (standby) mode of the device on or off. If the device is + in power save mode, setting and reading temperatures switches off the power save + mode automatically. + API Status: published + Args: + Standby:int = 1 + Returns: + RespStandby:int + Command Timeout: 60000 + Example:EnableHeaterStandby 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterStandby",Standby) + return int(rsp[0]) + +def ReadTemperatureChuckStatus(): + """ + Returns values of the temperature chuck status. The status byte gives + information about the current controller's action. The dew point sensor status + encapsulates information, if such a sensor is connected, and if the actual dew + point difference temperature is readable (active). It can be used for purge + control. Soak time left (in seconds) is used when soak time is actually running. + API Status: published + Returns: + Status:str + DPSensor:int + SoakTimeLeft:int + HasEcoMode:int + Command Timeout: 60000 + Example:ReadTemperatureChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTemperatureChuckStatus") + global ReadTemperatureChuckStatus_Response + if not "ReadTemperatureChuckStatus_Response" in globals(): ReadTemperatureChuckStatus_Response = namedtuple("ReadTemperatureChuckStatus_Response", "Status,DPSensor,SoakTimeLeft,HasEcoMode") + return ReadTemperatureChuckStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetTargetTemp(Unit:str=""): + """ + Reads the target temperature of the chuck. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetTargetTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetTargetTemp",Unit) + global GetTargetTemp_Response + if not "GetTargetTemp_Response" in globals(): GetTargetTemp_Response = namedtuple("GetTargetTemp_Response", "RespTemperature,RespUnit") + return GetTargetTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetThermoWindow(Window:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command sets the window for the target temperture which is the window in which a + station is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Args: + Window:Decimal = 1 + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:SetThermoWindow 2.0 + """ + rsp = MessageServerInterface.sendSciCommand("SetThermoWindow",Window) + return Decimal(rsp[0]) + +def GetThermoWindow(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command returns the current thermo window which is the window in which a station + is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:GetThermoWindow + """ + rsp = MessageServerInterface.sendSciCommand("GetThermoWindow") + return Decimal(rsp[0]) + +def SendThermoCommand(Command:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends a command string to the thermal chuck using the thermal chuck protocol and + returns the thermal chucks response as command response. This command can be + used to access thermal chuck features that are not exposed as standalone SCI + commands. Command is currently implemented for ERS and ATT chucks. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:SendThermoCommand RH + """ + rsp = MessageServerInterface.sendSciCommand("SendThermoCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadAuxStatus(AuxID:int=""): + """ + Returns the status of a single AUX site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + FlagsMode:int + Comp:str + PresetHeight:str + AuxSiteType:str + Command Timeout: 10000 + Example:ReadAuxStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxStatus",AuxID) + global ReadAuxStatus_Response + if not "ReadAuxStatus_Response" in globals(): ReadAuxStatus_Response = namedtuple("ReadAuxStatus_Response", "AuxIDEcho,FlagsMode,Comp,PresetHeight,AuxSiteType") + return ReadAuxStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ReadAuxPosition(AuxID:int="", Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual AUX sites position in X, Y and Z. With AUX ID set to 0, the + position is read for the chuck stage. If no AUX ID is given, it tries to read + the position from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + AuxIDEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadAuxPosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxPosition",AuxID,Unit,PosRef,Comp) + global ReadAuxPosition_Response + if not "ReadAuxPosition_Response" in globals(): ReadAuxPosition_Response = namedtuple("ReadAuxPosition_Response", "AuxIDEcho,X,Y,Z") + return ReadAuxPosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadAuxHeights(AuxID:int="", Unit:str=""): + """ + Returns the actual technology heights from an AUX site. If AUX ID is set to 0, + all response values are read from chuck stage. If no AUX ID is given, it tries + to read the heights from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadAuxHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxHeights",AuxID,Unit) + global ReadAuxHeights_Response + if not "ReadAuxHeights_Response" in globals(): ReadAuxHeights_Response = namedtuple("ReadAuxHeights_Response", "AuxIDEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadAuxHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetAuxMode(AuxID:int="", Overtravel:int=""): + """ + Modes manage the way a stage behaves when it is in contact height. AUX site mode + holds only a single flag. Flags can be turned on by using the value 1 or turned + off by using the value 0. If you do not want to change the flag - use the value + of 2. If AUX ID is set to 0, all flags are set for chuck stage. AUX site will + move an additional overtravel on every contact move. + API Status: published + Args: + AuxID:int = -1 + Overtravel:int = 2 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxMode 1 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxMode",AuxID,Overtravel) + return int(rsp[0]) + +def SetAuxHome(AuxID:int="", Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the AUX sites Home position in X and Y. It defines the origin of the AUX + sites coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHome",AuxID,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetAuxIndex(AuxID:int="", XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the AUX sites index size. If AUX ID is set to 0, index size is set for + chuck stage. + API Status: published + Args: + AuxID:int = -1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxIndex",AuxID,XValue,YValue,Unit) + return int(rsp[0]) + +def SetAuxHeight(AuxID:int="", PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Sets the AUX sites contact height and corresponding gaps for overtravel, + alignment and separation height. A contact height search gap for contact search + with edge sensor can also be set. This search gap is always identical for all + AUX sites. Without any optional parameters the command sets contact height to + the current position. + API Status: published + Args: + AuxID:int = -1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHeight",AuxID,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadAuxIndex(AuxID:int="", Unit:str=""): + """ + Returns the actual AUX sites index values. If AUX ID is set to 0, the index size + is read from chuck stage. If no AUX ID is given, it tries to read the index from + the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 10000 + Example:ReadAuxIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxIndex",AuxID,Unit) + global ReadAuxIndex_Response + if not "ReadAuxIndex_Response" in globals(): ReadAuxIndex_Response = namedtuple("ReadAuxIndex_Response", "AuxIDEcho,IndexX,IndexY") + return ReadAuxIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetAuxThetaHome(AuxID:int="", Mode:str="", Unit:str="", Position:Decimal=""): + """ + Sets the AUX sites theta home position. It defines the origin of the AUX sites + theta coordinate system for later movements. If AUX ID is set to 0, theta home + position is set for chuck stage. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + Position:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxThetaHome 1 0 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxThetaHome",AuxID,Mode,Unit,Position) + return int(rsp[0]) + +def EnableOffset(Stage:str="", Enable:int="", Move:int=""): + """ + Enables or disables the Offset XY compensation for the selected stage. If the + compensation holds an offset different from zero, the chuck is automatically + moved the distance of the offset. The chuck also moves automatically to a safe + height. The move can be disabled by the third parameter. This may put the stage + outside the software fence. + API Status: published + Args: + Stage:str = "Chuck" + Enable:int = 1 + Move:int = 1 + Command Timeout: 60000 + Example:EnableOffset C 1 + """ + MessageServerInterface.sendSciCommand("EnableOffset",Stage,Enable,Move) + + +def SetOffset(Stage:str="", OffsetX:Decimal="", OffsetY:Decimal=""): + """ + Sets the offset values for the Offset XY compensation for the selected stage. + The changes take effect immediately. Note that the Offset XY compensation must + be enabled for the values to take effect. The compensation is enabled or + disabled using EnableOffset command. + API Status: published + Args: + Stage:str = "Chuck" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Command Timeout: 5000 + Example:SetOffset C 100000.0 0.0 + """ + MessageServerInterface.sendSciCommand("SetOffset",Stage,OffsetX,OffsetY) + + +def GetOffsetInfo(Stage:str=""): + """ + Gets information about the Offset XY compensation of the selected stage, + including the stored offset values and whether the compensation is enabled or + disabled. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Enable:int + OffsetX:Decimal + OffsetY:Decimal + Command Timeout: 5000 + Example:GetOffsetInfo C + """ + rsp = MessageServerInterface.sendSciCommand("GetOffsetInfo",Stage) + global GetOffsetInfo_Response + if not "GetOffsetInfo_Response" in globals(): GetOffsetInfo_Response = namedtuple("GetOffsetInfo_Response", "Enable,OffsetX,OffsetY") + return GetOffsetInfo_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetSwitchPosition(Stage:str="", AuxSite:int="", X:Decimal="", Y:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the switch position of a stage. This is the position to move to if an aux + site gets active. This is only supported for the chuck and it's aux sites. Aux + index 0 means wafer site, 1 means aux site 1 and so on. + API Status: internal + Args: + Stage:str = "Chuck" + AuxSite:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 5000 + Example:SetSwitchPosition C 0 5000 5000 + """ + MessageServerInterface.sendSciCommand("SetSwitchPosition",Stage,AuxSite,X,Y) + + +def MoveAuxSite(AuxID:int=""): + """ + Moves the chuck to the position of a given AUX site. A safe height is used for + the move. If AUX ID is set to 0, the target of the move is the wafer site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Command Timeout: 60000 + Example:MoveAuxSite 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAuxSite",AuxID) + return int(rsp[0]) + +def SetAuxSiteCount(AuxSiteCount:int=""): + """ + Sets the number of available AUX sites. For preparing for example two cal + chucks, the count must be set to 2. For the changes to take effect the system + needs to be restarted. + API Status: published + Args: + AuxSiteCount:int = 0 + Command Timeout: 10000 + Example:SetAuxSiteCount 2 + """ + MessageServerInterface.sendSciCommand("SetAuxSiteCount",AuxSiteCount) + + +def GetAuxSiteCount(): + """ + Reads the number of available AUX sites and the ID of the actual active AUX + site. If this is 0, the chuck stage is currently active. + API Status: published + Returns: + AuxSiteCount:int + ActualAuxSite:int + Command Timeout: 10000 + Example:GetAuxSiteCount + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteCount") + global GetAuxSiteCount_Response + if not "GetAuxSiteCount_Response" in globals(): GetAuxSiteCount_Response = namedtuple("GetAuxSiteCount_Response", "AuxSiteCount,ActualAuxSite") + return GetAuxSiteCount_Response(int(rsp[0]),int(rsp[1])) + +def SetAuxSiteName(AuxID:int="", AuxSiteName:str=""): + """ + Sets the description of an AUX site. With AUX ID zero, the description of the + wafer site can be set. + API Status: published + Args: + AuxID:int = -1 + AuxSiteName:str = "" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteName 1 Aux site 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteName",AuxID,AuxSiteName) + return int(rsp[0]) + +def GetAuxSiteName(AuxID:int=""): + """ + This command reads the description of an AUX site. If AUX ID is set to 0, the + description of the chuck stage is given back. If no AUX ID is given, it tries to + read from the active site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + AuxSiteName:str + Command Timeout: 10000 + Example:GetAuxSiteName 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteName",AuxID) + global GetAuxSiteName_Response + if not "GetAuxSiteName_Response" in globals(): GetAuxSiteName_Response = namedtuple("GetAuxSiteName_Response", "AuxIDEcho,AuxSiteName") + return GetAuxSiteName_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def CleanProbeTip(AuxID:str=""): + """ + Starts a probe tip cleaning on the given AUX site. The cleaning algorithm is + dependent from the type of the AUX site and from the duration and the cleaning + count that is set in configuration. The cleaning algorithm includes both a move + to the pad site and a move back to the source site. + API Status: published + Args: + AuxID:str = "-1" + Returns: + AuxIDEcho:int + Command Timeout: 300000 + Example:CleanProbeTip 1 + """ + rsp = MessageServerInterface.sendSciCommand("CleanProbeTip",AuxID) + return int(rsp[0]) + +def SetAuxSiteType(AuxID:int="", AuxSiteType:str=""): + """ + Sets the type for a given AUX site. It depends on the type of the AUX site, if + there is a cleaning algorithm available. It is not possible to set the type of + the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + AuxSiteType:str = "AuxUnknown" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteType 1 G + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteType",AuxID,AuxSiteType) + return int(rsp[0]) + +def SetCleaningParams(AuxID:int="", Count:int="", Time:int=""): + """ + Sets the cleaning parameters for a given AUX site. It is not possible to set the + cleaning parameters of the wafer site (AUX site 0). If no AUX ID is given, it + tries to set the parameters of the active site. The cleaning count defines, + how much times the cleaning is performed repeatedly. The cleaning time defines, + how much milliseconds the needles wait in cleaning position during each + cleaning cycle. + API Status: published + Args: + AuxID:int = -1 + Count:int = 1 + Time:int = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetCleaningParams 1 5 1000 + """ + rsp = MessageServerInterface.sendSciCommand("SetCleaningParams",AuxID,Count,Time) + return int(rsp[0]) + +def GetCleaningParams(AuxID:int=""): + """ + Reads the cleaning parameters of a given AUX site. It is not possible to read + cleaning parameters of the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Count:int + Time:int + Remaining:int + Command Timeout: 30000 + Example:GetCleaningParams + """ + rsp = MessageServerInterface.sendSciCommand("GetCleaningParams",AuxID) + global GetCleaningParams_Response + if not "GetCleaningParams_Response" in globals(): GetCleaningParams_Response = namedtuple("GetCleaningParams_Response", "AuxIDEcho,Count,Time,Remaining") + return GetCleaningParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def UpdateAuxSitePositions(AuxID:int="", XOffset:Decimal="", YOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Rotate the switch, home, and fence positions to match the current chuck theta + angle and adjust Home/Switch by XY offset. Should only be used for Aux sites + that don't move theta. + API Status: internal + Args: + AuxID:int = -1 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 5000 + Example:UpdateAuxSitePositions 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateAuxSitePositions",AuxID,XOffset,YOffset) + return int(rsp[0]) + +def ResetCleaningPosition(AuxID:str="", OffsetX:Decimal="", OffsetY:Decimal=""): + """ + Resets the cleaning position to the beginning of the cleaning aux site (home). + API Status: published + Args: + AuxID:str = "-1" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:ResetCleaningPosition 5 + """ + rsp = MessageServerInterface.sendSciCommand("ResetCleaningPosition",AuxID,OffsetX,OffsetY) + return int(rsp[0]) + +def BnR_EchoData(ControllerID:int="", TestCmd:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Test Command for the Kernel Communication. It is like a ping command. The given + text string is returned unchanged. + API Status: internal + Args: + ControllerID:int = 1 + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:BnR_EchoData 1 Hello World + """ + rsp = MessageServerInterface.sendSciCommand("BnR_EchoData",ControllerID,TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_ReportKernelVersion(ControllerID:int="", Module:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual version information of the controller software. + The 'Version' value contains version number and revision level of the actual + implementation. The text string contains a + code description, version number and the revision date. + The 'Module' byte is optional (default is K). + API Status: internal + Args: + ControllerID:int = 1 + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:BnR_ReportKernelVersion 1 K + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReportKernelVersion",ControllerID,Module) + global BnR_ReportKernelVersion_Response + if not "BnR_ReportKernelVersion_Response" in globals(): BnR_ReportKernelVersion_Response = namedtuple("BnR_ReportKernelVersion_Response", "Version,Description") + return BnR_ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetStationType(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns information about the connected station. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StationType:str + Type:str + Command Timeout: 5000 + Example:BnR_GetStationType 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStationType",ControllerID) + global BnR_GetStationType_Response + if not "BnR_GetStationType_Response" in globals(): BnR_GetStationType_Response = namedtuple("BnR_GetStationType_Response", "StationType,Type") + return BnR_GetStationType_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_ResetController(ControllerID:int="", Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the BnR controller. + API Status: internal + Args: + ControllerID:int = 1 + Mode:str = "X" + Command Timeout: 10000 + Example:BnR_ResetController 1 + """ + MessageServerInterface.sendSciCommand("BnR_ResetController",ControllerID,Mode) + + +def BnR_SetOutput(ControllerID:int="", Channel:str="", State:int="", CycleTime:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + State:int = 0 + CycleTime:int = 0 + Command Timeout: 5000 + Example:BnR_SetOutput 1 1000 1 2000 + """ + MessageServerInterface.sendSciCommand("BnR_SetOutput",ControllerID,Channel,State,CycleTime) + + +def BnR_GetOutput(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an output channel. By using the string identifier DO_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + Returns: + State:int + AllOutputs:str + Command Timeout: 5000 + Example:BnR_GetOutput 1 DO_WaferVacuum + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetOutput",ControllerID,Channel) + global BnR_GetOutput_Response + if not "BnR_GetOutput_Response" in globals(): BnR_GetOutput_Response = namedtuple("BnR_GetOutput_Response", "State,AllOutputs") + return BnR_GetOutput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetInput(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an input channel. By using the string identifier DI_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DI_MotorPower" + Returns: + State:int + AllInputs:str + Command Timeout: 5000 + Example:BnR_GetInput 1 DI_MotorPower + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInput",ControllerID,Channel) + global BnR_GetInput_Response + if not "BnR_GetInput_Response" in globals(): BnR_GetInput_Response = namedtuple("BnR_GetInput_Response", "State,AllInputs") + return BnR_GetInput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_SetAnalogOutput(ControllerID:int="", Channel:str="", OutputPercent:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an analog output channel to a given value. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + OutputPercent:Decimal = 50 + Command Timeout: 5000 + Example:BnR_SetAnalogOutput 1 AO_PurgeDewPoint 50 + """ + MessageServerInterface.sendSciCommand("BnR_SetAnalogOutput",ControllerID,Channel,OutputPercent) + + +def BnR_GetAnalogIO(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current value of an analog output or input. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + Returns: + Value:Decimal + UnderOverflow:int + Command Timeout: 5000 + Example:BnR_GetAnalogIO 1 AO_PurgeDewPoint + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAnalogIO",ControllerID,Channel) + global BnR_GetAnalogIO_Response + if not "BnR_GetAnalogIO_Response" in globals(): BnR_GetAnalogIO_Response = namedtuple("BnR_GetAnalogIO_Response", "Value,UnderOverflow") + return BnR_GetAnalogIO_Response(Decimal(rsp[0]),int(rsp[1])) + +def BnR_GetStartupStatus(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the startup status of the BnR controller to determine if the controller + is properly booted or still starting. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StartupStatus:str + AdditionalStatusInfo:str + Command Timeout: 5000 + Example:BnR_GetStartupStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStartupStatus",ControllerID) + global BnR_GetStartupStatus_Response + if not "BnR_GetStartupStatus_Response" in globals(): BnR_GetStartupStatus_Response = namedtuple("BnR_GetStartupStatus_Response", "StartupStatus,AdditionalStatusInfo") + return BnR_GetStartupStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_CreateSdmSystemDump(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Creates a Sdm System Dump file on the B&R flash + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 60000 + Example:BnR_CreateSdmSystemDump + """ + MessageServerInterface.sendSciCommand("BnR_CreateSdmSystemDump",ControllerID) + + +def BnR_GetControllerData(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets controller data from the B&R controller. Currently used for init + information. + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 10000 + Example:BnR_GetControllerData 1 + """ + MessageServerInterface.sendSciCommand("BnR_GetControllerData",ControllerID) + + +def BnR_WriteMessage(ControllerID:int="", MessageType:str="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to write a (native) message to Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Message:str = "" + Command Timeout: 5000 + Example:BnR_WriteMessage 1 mtCryoLoader SampleMessage + """ + MessageServerInterface.sendSciCommand("BnR_WriteMessage",ControllerID,MessageType,Message) + + +def BnR_ReadMessage(ControllerID:int="", MessageType:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to read a (native) message from Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Returns: + Message:str + Command Timeout: 5000 + Example:BnR_ReadMessage 1 mtCryoLoader + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadMessage",ControllerID,MessageType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetDataIterator(ControllerID:int="", ShowAll:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters + and requires the BnR_GetNextDatum command. + API Status: internal + Args: + ControllerID:int = 1 + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 5000 + Example:BnR_GetDataIterator 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDataIterator",ControllerID,ShowAll) + global BnR_GetDataIterator_Response + if not "BnR_GetDataIterator_Response" in globals(): BnR_GetDataIterator_Response = namedtuple("BnR_GetDataIterator_Response", "IdentityToken,SizeNoAll") + return BnR_GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def BnR_GetNextDatum(ControllerID:int="", IdentityToken:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + ControllerID:int = 1 + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:BnR_GetNextDatum 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetNextDatum",ControllerID,IdentityToken) + global BnR_GetNextDatum_Response + if not "BnR_GetNextDatum_Response" in globals(): BnR_GetNextDatum_Response = namedtuple("BnR_GetNextDatum_Response", "IsLastDatum,DatumCode,PathNameDescrValue") + return BnR_GetNextDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def BnR_SetDatum(ControllerID:int="", PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + ControllerID:int = 1 + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:BnR_SetDatum 1 Chuck_XAxisData:CurrentMaximal:70 + """ + MessageServerInterface.sendSciCommand("BnR_SetDatum",ControllerID,PathNameAndValue) + + +def BnR_GetDatum(ControllerID:int="", PathName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + ControllerID:int = 1 + PathName:str = "" + Returns: + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:BnR_GetDatum 1 Chuck_XAxisData:CurrentMaximal + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDatum",ControllerID,PathName) + global BnR_GetDatum_Response + if not "BnR_GetDatum_Response" in globals(): BnR_GetDatum_Response = namedtuple("BnR_GetDatum_Response", "DatumCode,ValueDesc") + return BnR_GetDatum_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_DoInternalTask(ControllerID:int="", Task:str="", PCmdInt1:int="", PCmdInt2:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes an internal BnR Task + API Status: internal + Args: + ControllerID:int = 1 + Task:str = "" + PCmdInt1:int = 0 + PCmdInt2:int = 0 + Returns: + RspInt:int + RspString:str + Command Timeout: 10000 + Example:BnR_DoInternalTask 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_DoInternalTask",ControllerID,Task,PCmdInt1,PCmdInt2) + global BnR_DoInternalTask_Response + if not "BnR_DoInternalTask_Response" in globals(): BnR_DoInternalTask_Response = namedtuple("BnR_DoInternalTask_Response", "RspInt,RspString") + return BnR_DoInternalTask_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetPosition(Stage:str="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current positions for the X,Y,Z (or T) axis for the specified stage + as well as the commanded positions. + API Status: internal + Args: + Stage:str = "Chuck" + Unit:str = "Microns" + Returns: + XorT:Decimal + Y:Decimal + Z:Decimal + CommandedXorT:Decimal + CommandedY:Decimal + CommandedZ:Decimal + Command Timeout: 5000 + Example:BnR_GetPosition 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetPosition",Stage,Unit) + global BnR_GetPosition_Response + if not "BnR_GetPosition_Response" in globals(): BnR_GetPosition_Response = namedtuple("BnR_GetPosition_Response", "XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ") + return BnR_GetPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def BnR_Move(Stage:str="", XValue:Decimal="", YValue:Decimal="", VelX:Decimal="", VelY:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a XY movement for a specified stage. This can be either a + blocking or non blocking move. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + VelX:Decimal = 0 + VelY:Decimal = 0 + WaitFinished:int = 1 + Returns: + X:Decimal + Y:Decimal + Command Timeout: 60000 + Example:BnR_Move 1 C 5000 5000 Z 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_Move",Stage,XValue,YValue,VelX,VelY,WaitFinished) + global BnR_Move_Response + if not "BnR_Move_Response" in globals(): BnR_Move_Response = namedtuple("BnR_Move_Response", "X,Y") + return BnR_Move_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def BnR_MoveZ(Stage:str="", ZValue:Decimal="", Vel:Decimal="", Dec:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the stage Z axis to a new position. + API Status: internal + Args: + Stage:str = "Chuck" + ZValue:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + Z:Decimal + Command Timeout: 600000 + Example:BnR_MoveZ 1 C 12000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZ",Stage,ZValue,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_ScanMoveZ(ControllerID:int="", Stage:str="", ZDistance:Decimal="", TriggerEveryNthCycle:int="", Vel:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a scan movement of the Z axis that sets a digital output + every couple microns to trigger e.g. a camera. After the move is finished, the + command returns a list of Z heights at which the digital output was set. + API Status: internal + Args: + ControllerID:int = 1 + Stage:str = "Chuck" + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 2 + Vel:Decimal = 10 + Command Timeout: 300000 + Example:BnR_ScanMoveZ 1 C 1000 6 10 + """ + MessageServerInterface.sendSciCommand("BnR_ScanMoveZ",ControllerID,Stage,ZDistance,TriggerEveryNthCycle,Vel) + + +def BnR_MoveT(TValue:Decimal="", Vel:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes a movement of the theta axis, either blocking or non blocking + API Status: internal + Args: + TValue:Decimal = 0 + Vel:Decimal = 0 + WaitFinished:int = 1 + Returns: + T:Decimal + Command Timeout: 60000 + Example:BnR_MoveT 1 1.003 10 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveT",TValue,Vel,WaitFinished) + return Decimal(rsp[0]) + +def BnR_StopAxis(Stage:str="", FlagsStop:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops 1... all axes of a stage + API Status: internal + Args: + Stage:str = "Chuck" + FlagsStop:int = 15 + Command Timeout: 5000 + Example:BnR_StopAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_StopAxis",Stage,FlagsStop) + + +def BnR_InitAxis(Stage:str="", FlagsInit:int="", FlagsDirection:int="", FlagsInitInPlace:int="", LowLimitX:Decimal="", LowLimitY:Decimal="", LowLimitZ:Decimal="", LowLimitTh:Decimal="", InitInPlaceMoveRangeX:Decimal="", InitInPlaceMoveRangeY:Decimal="", InitInPlaceMoveRangeZ:Decimal="", InitInPlaceMoveRangeTh:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Machine Coordinate System: X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - + _FlagsInitInPlace_: X, Y, Z, Theta All flags can be accessed by indirect + members. Initializes the stage and resets current coordinate system. Should be + used only in cases when the reported coordinates do not correspond to real + position of mechanics. Init in Place performs the initialization without any + movements. + API Status: internal + Args: + Stage:str = "Chuck" + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsInitInPlace:int = 0 + LowLimitX:Decimal = 0 + LowLimitY:Decimal = 0 + LowLimitZ:Decimal = 0 + LowLimitTh:Decimal = 0 + InitInPlaceMoveRangeX:Decimal = 0 + InitInPlaceMoveRangeY:Decimal = 0 + InitInPlaceMoveRangeZ:Decimal = 0 + InitInPlaceMoveRangeTh:Decimal = 0 + Command Timeout: 300000 + Example:BnR_InitAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_InitAxis",Stage,FlagsInit,FlagsDirection,FlagsInitInPlace,LowLimitX,LowLimitY,LowLimitZ,LowLimitTh,InitInPlaceMoveRangeX,InitInPlaceMoveRangeY,InitInPlaceMoveRangeZ,InitInPlaceMoveRangeTh) + + +def BnR_GetAxisState(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of an axis (disabled/standstill/errorstop/stoppin + g/homing/continuousmotion/discretemotion/synchronizedmotion) + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + State:str + AdditionalStateInfo:str + Command Timeout: 5000 + Example:BnR_GetAxisState 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisState",Stage,Axis) + global BnR_GetAxisState_Response + if not "BnR_GetAxisState_Response" in globals(): BnR_GetAxisState_Response = namedtuple("BnR_GetAxisState_Response", "State,AdditionalStateInfo") + return BnR_GetAxisState_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetAxisStatus(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns some axis status information + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + Initialized:int + PositiveEndlimit:int + NegativeEndlimit:int + Command Timeout: 5000 + Example:BnR_GetAxisStatus 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisStatus",Stage,Axis) + global BnR_GetAxisStatus_Response + if not "BnR_GetAxisStatus_Response" in globals(): BnR_GetAxisStatus_Response = namedtuple("BnR_GetAxisStatus_Response", "Initialized,PositiveEndlimit,NegativeEndlimit") + return BnR_GetAxisStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def BnR_SetQuietMode(Stage:str="", QuietMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to enable the quiet mode for a stage (quiet turns motors powerless) + API Status: internal + Args: + Stage:str = "Chuck" + QuietMode:int = 0 + Command Timeout: 5000 + Example:BnR_SetQuietMode 1 C 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetQuietMode",Stage,QuietMode) + + +def BnR_GetQuietMode(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to query the quiet mode for a stage + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + QuietMode:int + Command Timeout: 5000 + Example:BnR_GetQuietMode 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetQuietMode",Stage) + return int(rsp[0]) + +def BnR_GetInternalAxisInfo(Stage:str="", Axis:str="", InfoType:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns various axis information, dependent on the InfoType + parameter + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + InfoType:str = "StallInfo" + Returns: + RspString:str + Command Timeout: 5000 + Example:BnR_GetInternalAxisInfo 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInternalAxisInfo",Stage,Axis,InfoType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetWiringTesterData(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to get various information required for the BnR wiring tester tool. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + STIn_ModuleOK:int + STIn_LifeCnt:int + STIn_DrvOK:int + STIn_OvertemperatureError:int + STIn_CurrentError:int + STIn_OvercurrentError:int + STIn_RefPulsePos:int + STIn_RefPulseCnt:int + STIn_ModulePowerSupplyError:int + STOut_SetTime:int + STOut_MotorStep0:int + STOut_DriveEnable:int + STOut_BoostCurrent:int + STOut_StandStillCurrent:int + STOut_ClearError:int + CMIn_ModuleOK:int + CMIn_SDCLifeCount:int + CMIn_Encoder:int + CMIn_EncoderTimeValid:int + CMIn_DigitalInput1:int + CMIn_DigitalInput2:int + CMIn_BWChannelA:int + CMIn_BWChannelB:int + CMIn_PowerSupply2:int + CMOut_QuitChannelA:int + CMOut_QuitChannelB:int + SWAxisErrorID:int + SWAxisErrorDesc:str + Command Timeout: 5000 + Example:BnR_GetWiringTesterData 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetWiringTesterData",Stage,Axis) + global BnR_GetWiringTesterData_Response + if not "BnR_GetWiringTesterData_Response" in globals(): BnR_GetWiringTesterData_Response = namedtuple("BnR_GetWiringTesterData_Response", "STIn_ModuleOK,STIn_LifeCnt,STIn_DrvOK,STIn_OvertemperatureError,STIn_CurrentError,STIn_OvercurrentError,STIn_RefPulsePos,STIn_RefPulseCnt,STIn_ModulePowerSupplyError,STOut_SetTime,STOut_MotorStep0,STOut_DriveEnable,STOut_BoostCurrent,STOut_StandStillCurrent,STOut_ClearError,CMIn_ModuleOK,CMIn_SDCLifeCount,CMIn_Encoder,CMIn_EncoderTimeValid,CMIn_DigitalInput1,CMIn_DigitalInput2,CMIn_BWChannelA,CMIn_BWChannelB,CMIn_PowerSupply2,CMOut_QuitChannelA,CMOut_QuitChannelB,SWAxisErrorID,SWAxisErrorDesc") + return BnR_GetWiringTesterData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),int(rsp[14]),int(rsp[15]),int(rsp[16]),int(rsp[17]),int(rsp[18]),int(rsp[19]),int(rsp[20]),int(rsp[21]),int(rsp[22]),int(rsp[23]),int(rsp[24]),int(rsp[25]),int(rsp[26]),str("" if len(rsp) < 28 else ' '.join(rsp[27:]))) + +def BnR_MoveAxis(Stage:str="", Axis:str="", Value:Decimal="", Vel:Decimal="", Dec:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows moving a single axis to and e.g. in case of X does not + trigger a Y movement + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Value:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + PositionAfterMove:Decimal + Command Timeout: 60000 + Example:BnR_MoveAxis 1 C X 20000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveAxis",Stage,Axis,Value,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_MoveZCombined(ChuckTargetZ:Decimal="", WaitFinished:int="", ForcedAbsVelocity:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move Chuck-Z and (by fixed factor) Scope X, Y and Z + API Status: internal + Args: + ChuckTargetZ:Decimal = 0 + WaitFinished:int = 1 + ForcedAbsVelocity:int = 0 + Returns: + ChuckZ:Decimal + ScopeX:Decimal + ScopeY:Decimal + ScopeZ:Decimal + Command Timeout: 600000 + Example:BnR_MoveZCombined 1 17592.5 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZCombined",ChuckTargetZ,WaitFinished,ForcedAbsVelocity) + global BnR_MoveZCombined_Response + if not "BnR_MoveZCombined_Response" in globals(): BnR_MoveZCombined_Response = namedtuple("BnR_MoveZCombined_Response", "ChuckZ,ScopeX,ScopeY,ScopeZ") + return BnR_MoveZCombined_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def BnR_StepMove(Stage:str="", ZDown:Decimal="", XValue:Decimal="", YValue:Decimal="", ZUp:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command does a combined Z-XY-Z- move completely on the BnR-controller + without WinKernel interaction. This is a part of an ongoing optimization. + API Status: internal + Args: + Stage:str = "Chuck" + ZDown:Decimal = 0 + XValue:Decimal = 0 + YValue:Decimal = 0 + ZUp:Decimal = 0 + Command Timeout: 60000 + Example:BnR_StepMove 1 C 250 1000 1000 250 + """ + MessageServerInterface.sendSciCommand("BnR_StepMove",Stage,ZDown,XValue,YValue,ZUp) + + +def BnR_SearchEdgeSensor(SearchEndPos:Decimal="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a search move until the search end position is reached or the edge + sensor triggers. If the edge sensor triggers during the move, the trigger + position is returned.Otherwise, an edge sensor not found error is returned. + API Status: internal + Args: + SearchEndPos:Decimal = 0 + Velocity:Decimal = 0 + Returns: + EdgeSensorTriggerPos:Decimal + Command Timeout: 300000 + Example:BnR_SearchEdgeSensor 3000 10 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_SearchEdgeSensor",SearchEndPos,Velocity) + return Decimal(rsp[0]) + +def BnR_GetTraceData(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a collection of trace data + API Status: internal + Args: + ControllerID:int = 1 + Returns: + Data:str + Command Timeout: 5000 + Example:BnR_GetTraceData 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetTraceData",ControllerID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_SetTraceMode(ControllerID:int="", Mode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Commands sets the trace mode + API Status: internal + Args: + ControllerID:int = 1 + Mode:int = 0 + Command Timeout: 5000 + Example:BnR_SetTraceMode 1 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetTraceMode",ControllerID,Mode) + + +def BnR_WriteAxisModuleRegister(Stage:str="", Axis:str="", MotorModule:int="", RegisterName:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to change a module register value without controller restart + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Value:int = 0 + Command Timeout: 5000 + Example:BnR_WriteAxisModuleRegister 1 C X 1 ConfigOutput03 70 + """ + MessageServerInterface.sendSciCommand("BnR_WriteAxisModuleRegister",Stage,Axis,MotorModule,RegisterName,Value) + + +def BnR_ReadAxisModuleRegister(Stage:str="", Axis:str="", MotorModule:int="", RegisterName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to get any desired module register value + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Returns: + Value:int + Command Timeout: 5000 + Example:BnR_ReadAxisModuleRegister 1 C X 1 ConfigOutput03 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadAxisModuleRegister",Stage,Axis,MotorModule,RegisterName) + return int(rsp[0]) + +def ProcessStationGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns process station status (UNKNOWN, IDLE, BUSY, ERROR, PAUSED, Not + Initialized) and error code with error message when error. + API Status: internal + Returns: + Status:str + SubstratePresent:int + LastError:int + UseLoaderModule:int + WaferSizes:str + StatusMessage:str + IsLoaderJobRunning:int + Command Timeout: 25000 + Example:ProcessStationGetStatus + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetStatus") + global ProcessStationGetStatus_Response + if not "ProcessStationGetStatus_Response" in globals(): ProcessStationGetStatus_Response = namedtuple("ProcessStationGetStatus_Response", "Status,SubstratePresent,LastError,UseLoaderModule,WaferSizes,StatusMessage,IsLoaderJobRunning") + return ProcessStationGetStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ProcessStationInit(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initialize process station machine. This is not the prober init it is a fast + program initialization. Only applies to fully auto systems. + API Status: internal + Command Timeout: 2400000 + Example:ProcessStationInit + """ + MessageServerInterface.sendSciCommand("ProcessStationInit") + + +def ProcessStationFinish(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Finishes a process station process. This resets some internal test information + for the probe station. Some data is only reset in case this command is sent + after the last wafer in the job was tested. Only applies to fully auto systems. + API Status: internal + Command Timeout: 7500000 + Example:ProcessStationFinish + """ + MessageServerInterface.sendSciCommand("ProcessStationFinish") + + +def ProcessStationPrepareForLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command moves the chuck of the probe station to the secondary load position and + if available also checks the table level sensor. Only applies to fully auto + systems. + API Status: internal + Command Timeout: 120000 + Example:ProcessStationPrepareForLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForLoad") + + +def ProcessStationLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck out of the load position and checks if a wafer is placed. Only + applies to fully auto systems. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadComplete") + + +def ProcessStationPrepareForUnLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should do whatever is necessary to prepare the current wafer for + unload. Typically this includes things such as moving lift pins and opening + doors. + API Status: internal + Command Timeout: 1000000 + Example:ProcessStationPrepareForUnLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForUnLoad") + + +def ProcessStationUnLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should so whatever is necessary after a wafer is unloaded. This may + for example include closing doors. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationUnLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationUnLoadComplete") + + +def ProcessStationLoadRecipe(ForceReOpenProject:int="", ProjectFileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The recipe is a zipped archive that includes all project data. This command + tells the device to load the recipe. + API Status: internal + Args: + ForceReOpenProject:int = 0 + ProjectFileName:str = "" + Command Timeout: 60000 + Example:ProcessStationLoadRecipe 1 SampleProject.spp + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadRecipe",ForceReOpenProject,ProjectFileName) + + +def ProcessStationVerifyRecipe(ProjectFileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Requests that the device verify that the recipe given can be executed on the + device. It should check that the recipe is correctly formed and conforms to the + hardware of the device. It should not check for transient things such as whether + there is sufficient media or facilities available. those kinds of checks should + be done in PrepareForProcess + API Status: internal + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 60000 + Example:ProcessStationVerifyRecipe SampleProject.spp + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationVerifyRecipe",ProjectFileName) + global ProcessStationVerifyRecipe_Response + if not "ProcessStationVerifyRecipe_Response" in globals(): ProcessStationVerifyRecipe_Response = namedtuple("ProcessStationVerifyRecipe_Response", "Verified,ErrorDescription") + return ProcessStationVerifyRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ProcessStationStartRecipe(CurrentWaferInJob:int="", TotalWafersInJob:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells VeloxPro to start the current recipe. The station will switch to error if + an error occurs. If VeloxPro recipe execution is currently paused, this command + tells the system to continue execution. + API Status: internal + Args: + CurrentWaferInJob:int = -1 + TotalWafersInJob:int = -1 + Command Timeout: 25000 + Example:ProcessStationStartRecipe 1 + """ + MessageServerInterface.sendSciCommand("ProcessStationStartRecipe",CurrentWaferInJob,TotalWafersInJob) + + +def ProcessStationStopRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the device to stop the current recipe. The station will switch to error if + an error occurs. + API Status: internal + Command Timeout: 25000 + Example:ProcessStationStopRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationStopRecipe") + + +def ProcessStationRecoverError(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the module to do whatever is necessary to recover from an error condition. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationRecoverError + """ + MessageServerInterface.sendSciCommand("ProcessStationRecoverError") + + +def ProcessStationGetWaferResult(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get substrate information from process station controller application. + API Status: internal + Returns: + Result:str + PercentDone:Decimal + AllowSkipWafer:int + TestInformation:str + Command Timeout: 25000 + Example:ProcessStationGetWaferResult + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetWaferResult") + global ProcessStationGetWaferResult_Response + if not "ProcessStationGetWaferResult_Response" in globals(): ProcessStationGetWaferResult_Response = namedtuple("ProcessStationGetWaferResult_Response", "Result,PercentDone,AllowSkipWafer,TestInformation") + return ProcessStationGetWaferResult_Response(str(rsp[0]),Decimal(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def QueryWaferInfo(): + """ + Returns information about the wafer that is currently on the probe station. It + will return an error when there is no wafer currently on the chuck. + API Status: published + Returns: + Size:int + Angle:Decimal + ID:str + LotID:str + ProductID:str + Command Timeout: 25000 + Example:QueryWaferInfo + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferInfo") + global QueryWaferInfo_Response + if not "QueryWaferInfo_Response" in globals(): QueryWaferInfo_Response = namedtuple("QueryWaferInfo_Response", "Size,Angle,ID,LotID,ProductID") + return QueryWaferInfo_Response(int(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ProcessStationPauseRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the process station to PAUSE mode + API Status: internal + Command Timeout: 25000 + Example:ProcessStationPauseRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationPauseRecipe") + + +def GetProbingStatus(): + """ + Retrieves the current status of the prober. If probing status is AtFirstDie the + tester can take control. + API Status: published + Returns: + Status:str + Command Timeout: 25000 + Example:GetProbingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetProbingStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedProbing(): + """ + Tells the prober to proceed the recipe when current status is AtFirstDie. + API Status: published + Command Timeout: 25000 + Example:ProceedProbing + """ + MessageServerInterface.sendSciCommand("ProceedProbing") + + +def GetCassetteStatus(Cassette:int=""): + """ + Provides all available wafer information. It returns a set of data for each + wafer in either cassette. The data contains the cassette and the slot number + where the wafer is located, the status of the wafer, and identification + information. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 25000 + Example:GetCassetteStatus 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def QueryWaferID(Module:str="", Slot:int=""): + """ + Queries the wafer ID of a given module and slot. + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryWaferID Cassette1 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferID",Module,Slot) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def UpdateWaferID(Module:str="", Slot:int="", ID:str=""): + """ + Overrides the wafer ID of the given module and slot. If the wafer id is empty + and the module is a Loadport, the id will be read by the idreader if possible. + This process behaves as follows: - the current wafer id is reset - if the read- + wafer-process would be delayed (e.g. there is already a wafer on the idreader) + the process will be aborted and an error will be returned - if the id- + reading fails, the process behaves like a normal inventory triggered by the UI: + skip (returns success), abort (returns error) or "ask user". It is + recomended to use either skip or abort for remote id reading. If the + module is a Loadport and the slot is set to -1, a regular inventory will be + triggered. This behaves similar to an inventory triggered by the UI: The ID + won't be reset and already scanned wafers won't be reset. Setting an ID + explicitly with slot -1 is an error: - Okay, read id of wafer in slot 3 even if + it is already set: UpdateWaferID Cassette1 3 - Okay, set id of wafer in slot 3 + to XYZ123: UpdateWaferID Cassette1 3 XYZ123 - Okay, start full inventory: + UpdateWaferID Cassette1 -1 - Error: UpdateWaferID Cassette1 -1 XYZ123 + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + ID:str = "" + Command Timeout: 1500000 + Example:UpdateWaferID Cassette1 1 Wafer01 + """ + MessageServerInterface.sendSciCommand("UpdateWaferID",Module,Slot,ID) + + +def ConfirmRecipe(ProjectFileName:str=""): + """ + Queries whether the given project/flow name is a valid project/flow at the probe + station. Using file and folder names without white spaces is recommended. For + folders and files whith white spaces use quotation marks for the path. Example + for using white spaces: ConfirmRecipe + "C:/Users/Public/Documents/Velox/Projects/White Spaces.spp" + API Status: published + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 25000 + Example:ConfirmRecipe C:/Temp/Test.spp + """ + rsp = MessageServerInterface.sendSciCommand("ConfirmRecipe",ProjectFileName) + global ConfirmRecipe_Response + if not "ConfirmRecipe_Response" in globals(): ConfirmRecipe_Response = namedtuple("ConfirmRecipe_Response", "Verified,ErrorDescription") + return ConfirmRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def StartWaferJob(RecipeName:str="", WaferIDs:str=""): + """ + Creates and starts a new job by specifying the flow/spp file and the wafers to + be included in the job. + API Status: published + Args: + RecipeName:str = "" + WaferIDs:str = "" + Returns: + JobID:str + Command Timeout: 25000 + Example:StartWaferJob C:/Users/Public/Documents/Velox/Test.flow 1;1 2;1 + """ + rsp = MessageServerInterface.sendSciCommand("StartWaferJob",RecipeName,WaferIDs) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetJobParams(JobID:str=""): + """ + Get job information for a specific job ID including the flow file and the list + of wafers. + API Status: published + Args: + JobID:str = "" + Returns: + RecipeName:str + WaferIDs:str + Command Timeout: 25000 + Example:GetJobParams 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetJobParams",JobID) + global GetJobParams_Response + if not "GetJobParams_Response" in globals(): GetJobParams_Response = namedtuple("GetJobParams_Response", "RecipeName,WaferIDs") + return GetJobParams_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def JobStatus(JobID:str=""): + """ + Retrieves the status of a specific job by its ID. If the status is ErrorWaiting, + an error string is returned. + API Status: published + Args: + JobID:str = "" + Returns: + Status:str + JobStatusInfo:str + Command Timeout: 25000 + Example:JobStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("JobStatus",JobID) + global JobStatus_Response + if not "JobStatus_Response" in globals(): JobStatus_Response = namedtuple("JobStatus_Response", "Status,JobStatusInfo") + return JobStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AbortJob(JobID:str="", Unload:int=""): + """ + Aborts the job given by the job ID. The status of the job will be set to + "Aborted". The "Unload" parameter defines whether the wafer remains on the chuck + or not. + API Status: published + Args: + JobID:str = "" + Unload:int = 0 + Command Timeout: 25000 + Example:AbortJob 2 1 + """ + MessageServerInterface.sendSciCommand("AbortJob",JobID,Unload) + + +def ProcessStationCloseApplication(NoUserPrompt:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the VeloxPro application. + API Status: internal + Args: + NoUserPrompt:int = 0 + Command Timeout: 25000 + Example:ProcessStationCloseApplication + """ + MessageServerInterface.sendSciCommand("ProcessStationCloseApplication",NoUserPrompt) + + +def UnloadWafer(): + """ + Unolads a Wafer from the chuck to its origin. If no origin is known, the first + free Slot of a loadport will be chosen. A Wafer should be on the chuck. + API Status: published + Command Timeout: 600000 + Example:UnloadWafer + """ + MessageServerInterface.sendSciCommand("UnloadWafer") + + +def GetJobList(JobType:str=""): + """ + Returns a string for the relevant JobIDs. + API Status: published + Args: + JobType:str = "Probing" + Returns: + GetJobList:str + Command Timeout: 25000 + Example:GetJobList + """ + rsp = MessageServerInterface.sendSciCommand("GetJobList",JobType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedJob(ProceedJob:str=""): + """ + Continues a job that is waiting on an error (Job Status ErrorWaiting). The mode + determines how the job continues. + API Status: published + Args: + ProceedJob:str = "AbortJob" + Command Timeout: 25000 + Example:ProceedJob AbortJob + """ + MessageServerInterface.sendSciCommand("ProceedJob",ProceedJob) + + +def QueryCassetteID(Cassette:int=""): + """ + Returns the ID of a cassette that is placed on the load port. The loadport and + the cassette must support RFID reading (additional hardware needed). + API Status: published + Args: + Cassette:int = 1 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryCassetteID 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryCassetteID",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DockCassette(LoadPortId:int="", DockUndock:int=""): + """ + Docks or undocks a cassette which is placed on a LoadPort (CM300 only). It will + return an error if no cassette is placed: the LoadPort is not ready/available or + the docking failed. The command will do the docking/undocking and return when + this is done. + API Status: published + Args: + LoadPortId:int = 0 + DockUndock:int = 0 + Command Timeout: 60000 + Example:DockCassette 1 1 + """ + MessageServerInterface.sendSciCommand("DockCassette",LoadPortId,DockUndock) + + +def LoadWafer(LoadportID:int="", SlotID:int="", AlignmentAngle:Decimal=""): + """ + Load a wafer from a given loadport onto the prober. If no slot id is defined, + the first available wafer with the lowest slot id will be loaded. If no loadport + is defined, it will try to use the first loadport. If there is no suitable + wafer, it will try the second. Returns an error if the loading process fails or + no suitable wafer is found. To define an alignment angle and still use the + "autoselect" behaviour, use -1 for loadport and slot. + API Status: published + Args: + LoadportID:int = -1 + SlotID:int = -1 + AlignmentAngle:Decimal = 0 + Command Timeout: 600000 + Example:LoadWafer 1 1 + """ + MessageServerInterface.sendSciCommand("LoadWafer",LoadportID,SlotID,AlignmentAngle) + + +def UpdateCassetteStatus(Cassette:int=""): + """ + Updates the cassette status with a simple scan. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 1200000 + Example:UpdateCassetteStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def TransportWafer(SourceLocation:str="", SourceSlot:int="", DestinationLocation:str="", DestinationSlot:int=""): + """ + Transport a wafer from one location to another. This command behaves like the + wafer-transport inside the LoaderModule. The Slot must always be set. + API Status: published + Args: + SourceLocation:str = "Cassette1" + SourceSlot:int = 1 + DestinationLocation:str = "Cassette1" + DestinationSlot:int = 1 + Command Timeout: 600000 + Example:TransportWafer Cassette1 1 PreAligner 1 + """ + MessageServerInterface.sendSciCommand("TransportWafer",SourceLocation,SourceSlot,DestinationLocation,DestinationSlot) + + +def ProcessWafer(Module:str="", ProcessParam:str=""): + """ + "Process" a wafer on a given location. What is done depends on the current + station: - IDReader: read ID - PreAligner: align wafer (alignment angle + mandatory) - Prober: Perform current recipe + API Status: published + Args: + Module:str = "Cassette1" + ProcessParam:str = "" + Command Timeout: 100000 + Example:ProcessWafer PreAligner 90.0 + """ + MessageServerInterface.sendSciCommand("ProcessWafer",Module,ProcessParam) + + +def GetIDReaderPos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the IDReader + API Status: internal + Returns: + IDReaderPos:str + Command Timeout: 2000 + """ + rsp = MessageServerInterface.sendSciCommand("GetIDReaderPos") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetIDReaderPos(IDReaderPos:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the current position of the IDReader + API Status: internal + Args: + IDReaderPos:str = "Bottom" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetIDReaderPos",IDReaderPos) + + +def CryoCommand(Process:str=""): + """ + CryoCommand controls automatic cooling and warm up. + API Status: published + Args: + Process:str = "CD" + Command Timeout: 60000 + Example:CryoCommand CD + """ + MessageServerInterface.sendSciCommand("CryoCommand",Process) + + +def CryoReadTemperature(Stage:str=""): + """ + Reads the current temperature from sensor chuck or shield. + API Status: published + Args: + Stage:str = "C" + Returns: + Temp:Decimal + Command Timeout: 10000 + Example:CryoReadTemperature C + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadTemperature",Stage) + return Decimal(rsp[0]) + +def CryoSetTemperature(Stage:str="", Temp:Decimal=""): + """ + Sets temperature value for TIC chuck or shield. (Only available in process state + 'Idle' or 'Cold'.) + API Status: published + Args: + Stage:str = "C" + Temp:Decimal = 320 + Command Timeout: 10000 + Example:CryoSetTemperature C 70.5 + """ + MessageServerInterface.sendSciCommand("CryoSetTemperature",Stage,Temp) + + +def CryoStartRefill(Stage:str=""): + """ + Enables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStartRefill C + """ + MessageServerInterface.sendSciCommand("CryoStartRefill",Stage) + + +def CryoStopRefill(Stage:str=""): + """ + Disables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStopRefill C + """ + MessageServerInterface.sendSciCommand("CryoStopRefill",Stage) + + +def CryoReadState(): + """ + Reads current state. + API Status: published + Returns: + State:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CryoMoveBBPark(): + """ + Moves the black body to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBPark") + + +def CryoMoveBBWork(NbrPosition:int=""): + """ + Moves the black body to working position. + API Status: published + Args: + NbrPosition:int = 1 + Command Timeout: 60000 + Example:CryoMoveBBWork 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBWork",NbrPosition) + + +def CryoMoveShutter(Position:str="", Shutter:int=""): + """ + Moves one of the two shutters. + API Status: published + Args: + Position:str = "C" + Shutter:int = 1 + Command Timeout: 60000 + Example:CryoMoveShutter F 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveShutter",Position,Shutter) + + +def CryoMoveScopeWork(): + """ + Moves the microscope to working position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopeWork") + + +def CryoMoveScopePark(): + """ + Moves the microscope to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopePark") + + +def CryoReadPressure(): + """ + Reads the current pressure of the vacuum chamber. + API Status: published + Returns: + Pressure:Decimal + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadPressure") + return Decimal(rsp[0]) + +def MoveZCombined(Height:Decimal="", Percent:Decimal="", Async:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move both Chuck and Scope to a new absolute z-Height. The position must be + within 0 and a predefined maximum height (e.g. 3000um). Moves are performed with + maximum velocity for now + API Status: internal + Args: + Height:Decimal = 0 + Percent:Decimal = 0 + Async:int = 0 + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("MoveZCombined",Height,Percent,Async) + + +def GetSoftwareStop(): + """ + Get the state of the software stop. + API Status: published + Returns: + StopState:int + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareStop") + return int(rsp[0]) + +def MoveZCombinedSetStatus(Status:str="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Used to set the system either in off, on, error or locked state. For lock, a + key is required. To unlock this key, doe a 'SetStatus' with the same key. So, + SetStatus without message means enable/ recover from error, with message it + means unlock. If the system wasn't enabled or in error state before an unlock, + it will remain in this state after the unlock. + API Status: internal + Args: + Status:str = "Off" + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedSetStatus",Status,Message) + + +def GetScopeWorkingStage(): + """ + Get the currently active ScopeWorkingStage or -1 if unknown. Normally, this + should be the same as the currently active ScopeSilo + API Status: published + Returns: + ScopeWorkingStage:int + Command Timeout: 5000 + Example:GetScopeWorkingStage + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeWorkingStage") + return int(rsp[0]) + +def SetPerformanceMode(Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the performance mode in use by remote command. If this feature is not + supported and the mode is anything but Standard, an error is returned. + API Status: internal + Args: + Mode:str = "Standard" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetPerformanceMode",Mode) + + +def SetScopeWorkingStage(ScopeWorkingStage:int=""): + """ + Move to the target working stage + API Status: published + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 30000 + Example:SetScopeWorkingStage 1 + """ + MessageServerInterface.sendSciCommand("SetScopeWorkingStage",ScopeWorkingStage) + + +def GetPerformanceMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured performance mode. If this feature is not supported + on a station, Standard will be returned + API Status: internal + Returns: + Mode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPerformanceMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def MoveZCombinedGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the current status of the combined-z-move-system + API Status: internal + Returns: + Status:str + PlatenSafe:int + Height:Decimal + HeightMax:Decimal + HeightRelative:Decimal + SafeHeight:Decimal + Message:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveZCombinedGetStatus") + global MoveZCombinedGetStatus_Response + if not "MoveZCombinedGetStatus_Response" in globals(): MoveZCombinedGetStatus_Response = namedtuple("MoveZCombinedGetStatus_Response", "Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message") + return MoveZCombinedGetStatus_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str("" if len(rsp) < 7 else ' '.join(rsp[6:]))) + +def LoadScopeFenceConfiguration(Enable:int="", Path:str=""): + """ + Load a previously saved Scope-Fence-configuration or remove the current + configuration + API Status: published + Args: + Enable:int = 0 + Path:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoadScopeFenceConfiguration",Enable,Path) + + +def SetSoftwareStop(StopState:int=""): + """ + Set the state of the software stop. + API Status: published + Args: + StopState:int = 0 + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareStop",StopState) + + +#End of module +def trace(frame, event, arg): + print("%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno)) + return trace + + +class MessageServerInterface(object): + # For storing things + current_die = 1 + current_die_coords = [0, 0] + + chuck_home = [0, 0] + current_chuck_position = {'x': 0, 'y': 0, 'z': 0} + map_home = [0, 0] + + contact_height = -10 + # constants + dies = { + "1": [-6,4], + "2": [-5,4], + "3": [-4,4], + "4": [-3,4], + "5": [-2,4], + "6": [-8,3], + "7": [-7,3], + "8": [-6,3], + "9": [-5,3], + "10": [-4,3], + "11": [-3,3], + "12": [-2,3], + "13": [-1,3], + "14": [-9,2], + "15": [-8,2], + "16": [-7,2], + "17": [-6,2], + "18": [-5,2], + "19": [-4,2], + "20": [-3,2], + "21": [-2,2], + "22": [-1,2], + "23": [0,2], + "24": [-9,1], + "25": [-8,1], + "26": [-7,1], + "27": [-6,1], + "28": [-5,1], + "29": [-2,1], + "30": [-3,1], + "31": [-2,1], + "32": [-1,1], + "33": [0,1], + "34": [-9,0], + "35": [-8,0], + "36": [-7,0], + "37": [-6,0], + "38": [-5,0], + "39": [-4,0], + "40": [-3,0], + "41": [-2,0], + "42": [-1,0], + "43": [0,0], + "44": [-9,-1], + "45": [-8,-1], + "46": [-7,-1], + "47": [-6,-1], + "48": [-5,-1] + } + + def __init__(self): + print ("MessageServerInterface: initializing") + + def __enter__(self): + #-uc-# print ("MessageServerInterface: entering") + return self + + def __exit__(self, *args, **kwargs): + print ("MessageServerInterface: closed %s %s %s" % (args, kwargs, self)) + + @staticmethod + def generate_powermeter_values(weights=[10, 10, 20, 10, 35]): + + power = [0, 0] + for i in [0, 1]:# generate a random values between -75 and -22 dBm + power_75_70 = round(random.randint(-75, -70) + random.random(), 4) + power_70_65 = round(random.randint(-70, -65) + random.random(), 4) + power_65_55 = round(random.randint(-65, -60) + random.random(), 4) + power_30_25 = round(random.randint(-30, -25) + random.random(), 4) + power_25_20 = round(random.randint(-25, -20) + random.random(), 4) + # Choose randomly between the values, but weighted + data_list = [power_75_70] * weights[0] + [power_70_65] * weights[1] + [power_65_55] * weights[2] + [power_30_25] * weights[3] + [power_25_20] * weights[4] + power[i] = random.choice(data_list) + + return power[0], power[1] + + @staticmethod + def sendSciCommand(*args, **kwargs): + + try: + #-uc-# print (">> [SENDING SCI COMMAND static] args: %s, kwargs: %s" % (args, kwargs)) + if len(kwargs) > 0: + args_split = str(kwargs['rparams']).split() + func = getattr(MessageServerInterface, args[0]) + return func(*args_split) + else: + func = getattr(MessageServerInterface, args[0]) + return func(*args[1:]) + except Exception as e: + print(">> [SENDING SCI COMMAND static] Exception: %s" % e) + return None + + @staticmethod + def MoveOpticalProbe(probe, x, y, PosRef = "C"): + ''' Move selected probe motor in XY. + Input Parameter + probe 0=Input, 1=Output (I) + x motor command [um] (D) + y motor command [um] (D) + PosRef R=Relative, H=Home, Z=Zero (C) + Output Parameter + x motor position [um] (D) + y motor position [um] (D) + z motor position [um] (D) + ''' + #-uc-# print (" |-> [MoveOpticalProbe] probe: %s x: %s y: %s PosRef: %s: " % (probe, x, y, PosRef)) + z = 500 + return x, y, z + + @staticmethod + def SetOpticalProbeHome(probe): + z = 500 + return 0, 0, 0, 1, 1, 1 + + + @staticmethod + def ReadOpticalProbePowerMeter(channel): + '''Read computed power level from probe control. + + API Status: + dummy testing + Parameters: + channel: (Optional) analog input channel (I) + Returns: + power: calibrated power meter value [dBm] (D) + ''' + #-uc-# print (" |-> [ReadOpticalProbePowerMeter] channel: %s" % (channel)) + # return a value between -75 and -22 dBm + + # generate a random values between -75 and -22 dBm + power, _ = MessageServerInterface.generate_powermeter_values() + return power + + @staticmethod + def FindOpticalProbeHeight(probe, height, tracking_on=False): + '''Find motor and PZT positions to set desired fiber height above wafer. + + Parameters: + probe: 0=Input, 1=Output (I) + height: Fiber height [um] (D) + tracking on: (Optional) Enable fly height control (B) + Returns: + height: fiber height [um] (D) + Z sensor: Z sensor value (D) + motorZ: motor Z position [um] (D) + PZTZ: PZT Z position [um] (D) + ''' + #-uc-# print (" |-> [FindOpticalProbeHeight] channel: probe %s, height %s, tracking_on %s" % (probe, height, tracking_on)) + # Add a small delay, to simulate a real measurement up to 1 sec + time.sleep(random.random()) + return height, 0, 0, 0 + + @staticmethod + def RecenterOpticalProbe(probe): + '''Recenter XYZ motor position by the distance PZT is off center and recenter PZT + + Parameters: + probe: 0=Input, 1=Output (I) + ''' + #-uc-# print (" |-> [RecenterOpticalProbe] probe: %s +" % (probe)) + # Add a small delay, to simulate a real measurement up to 0,25 sec + time.sleep(random.random()*0.25) + + @staticmethod + def AreaScan(input, output, filename = None): + '''Perform Area ScanPerform. + Parameters: + Input: Input scan enabled (B) + Output: Output scan enabled (B) + Filename: (Optional) Data file name (S) + Returns: + x: x Input PZT position [um] (D) + y: y Input PZT position [um] (D) + x: x Output PZT position [um] (D) + y: y Output PZT position [um] (D) + InputPower: Input scan power [dBm] (D) + OutputPower: Output scan power [dBm] (D) + ''' + #-uc-# print (" |-> [AreaScan] input %s, output %s, filename %s" % (input, output, filename)) + # Add a small delay, to simulate a real measurement up to 4 sec + #time.sleep(3) + #time.sleep(random.random()) + power_in, power_out = MessageServerInterface.generate_powermeter_values(weights=[30, 0, 0, 20, 50]) + #power_in, power_out = MessageServerInterface.generate_powermeter_values(weights=[0, 0, 0, 0, 100]) + + return 0, 0, 0, 0, power_in, power_out + + @staticmethod + def ReadOpticalProbePos(probe, posRef = "C"): + '''Read optical probe position. + + Parameters: + probe: 0=Input, 1=Output (I) + PosRef: H=Home, Z=Zero (C) + Returns: + x: x motor position [um] (D) + y: y motor position [um] (D) + z: z motor position [um] (D) + x: x PZT position [um] (D) + y: y PZT position [um] (D) + z: z PZT position [um] (D) + ''' + #-uc-# print (" |-> [ReadOpticalProbePos] probe: %s %s" % (probe, posRef)) + # Add a small delay, to simulate a real measurement up to 1 sec + time.sleep(random.random()) + return 0, 0, 0, 0, 0, 0 + + @staticmethod + def EchoData(string): + ''' + Args: + TestCmd:str = "Test" + Returns: + TestRsp: str + ''' + #-uc-# print (" |-> [EchoData] string: %s" % (string)) + return string + + @staticmethod + def ReportKernelVersion(module): + #-uc-# print (" |-> [ReportKernelVersion] module: %s" % (module)) + return "1.0 Velox Simulator " + + @staticmethod + def TrackOpticalProbeHeight(probe, enable): + '''Track current fiber height. + Parameters: + probe: 0=Input, 1=Output (I) + enable: enable fly height control (B) + ''' + #-uc-# print (" |-> [TrackOpticalProbeHeight] probe: %s enable: %s" % (probe, enable)) + # Add a small delay, to simulate a real measurement up to 1 sec + time.sleep(random.random()) + + @staticmethod + def StepToDie(die_number:int="", site:int=""): + """ + Steps the chuck to the die location specified by the die number of the wafer + map. If no command data is passed, the chuck automatically steps to the next + logical wafer map die location. Returns the row and column number of the actual + die location after the move is completed. In addition, the SubDie location, and + total number of SubDies is also returned. + API Status: published + Args: + die_number:int = -1 + site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + + + #-uc-# print (" |-> [StepToDie] die_number: %s, site:%s" % (die_number, site)) + # Step to this die + MessageServerInterface.current_die = die_number + # Set the coordinates accordingly + MessageServerInterface.current_die_coords = [MessageServerInterface.dies[str(die_number)][0], MessageServerInterface.dies[str(die_number)][1]] + # Add a small delay, to simulate a real measurement up to 1 sec + time.sleep(random.random()) + return MessageServerInterface.current_die_coords[0], MessageServerInterface.current_die_coords[1], 0, 0 + + @staticmethod + def GetDieDataAsColRow(c_die_x="", c_die_y=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Column and Row are absent it uses the + current die on the wafer. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + #-uc-# print (" |-> [GetDieDataAsColRow] c_die_x: %s, c_die_y:%s" % (c_die_x, c_die_y)) + if c_die_x == "" and c_die_y == "": + return MessageServerInterface.current_die, MessageServerInterface.current_die_coords[0], MessageServerInterface.current_die_coords[1], 0, "OK" + + for die in MessageServerInterface.dies: + if MessageServerInterface.dies[die][0] == c_die_x and MessageServerInterface.dies[die][1] == c_die_y: + return int(die), MessageServerInterface.dies[die][0], MessageServerInterface.dies[die][1], 0, "OK" + + @staticmethod + def SetChuckHome(mode="0", unit="Microns", x_value="0", y_value="0"): + """ + Sets wafer and die home position, which can be used later as coordinate system + for movements. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHome 0 Y + """ + #-uc-# print (" |-> [SetChuckHome] mode %s, unit %s, x_value %s, y_value %s" % (mode, unit, x_value, y_value)) + MessageServerInterface.current_cuck_position = {'x': 0, 'y': 0, 'z': -500} + if mode == 0: + MessageServerInterface.chuck_home = [] + + @staticmethod + def SetMapHome(die_x = "", die_y = ""): + """ + If the command has no parameters it sets the current position as home position + both for the wafer map and for the chuck. Otherwise, it changes the wafer map + home position using the given die coordinates. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.map_home = [die_x, die_y] + #-uc-# print (" |-> [SetMapHome] die_x %s, die_y %s" % (die_x, die_y)) + + def ReadChuckPosition(Unit="Microns", PosRef="Home", Comp="Default"): + """ + Returns the current chuck stage position in X, Y and Z. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadChuckPosition Y Z + """ + #-uc-# print (" |-> [ReadChuckPosition] unit %s, pos_ref %s, comp %s" % (Unit, PosRef, Comp)) + return ( + MessageServerInterface.current_chuck_position['x'], + MessageServerInterface.current_chuck_position['y'], + MessageServerInterface.current_chuck_position['z'] + ) + + @staticmethod + def ReadChuckHeights(Unit=""): + """ + Returns the current settings used for the chuck Z movement. `Contact` is the + contact-height from zero in default compensation. The other heights are relative + to this. If no contact is set, the value will be -1. + API Status: published + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + SearchGap:Decimal + Command Timeout: 5000 + Example:ReadChuckHeights Y + """ + print(" |-> [ReadChuckHeights] unit %s" % (Unit)) + #print(" |-> [ReadChuckHeights] unit") + #print(" |<- [ReadChuckHeights] return %" % (res)) + return -20, 0, 0, 0, 0 + + @staticmethod + def MoveChuck(XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the chuck stage to the specified X,Y position. If chuck Z is in contact + height or higher, Interlock and Auto Z flags will be analyzed and stage will + behave correspondingly - can move to separation first or return an error: + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MoveChuck 5000. 5000. R Y 100 + """ + #-uc-# print (" |-> [MoveChuck] XValue %s, YValue %s, PosRef %s, Unit %s, Velocity %s, Comp %s" % (XValue, YValue, PosRef, Unit, Velocity, Comp)) + MessageServerInterface.current_chuck_position = {'x': XValue, 'y': YValue, 'z': MessageServerInterface.contact_height} + + @staticmethod + def SnapImage(MountPos:str="", FullPath:str="", SnapShotMode:int=""): + """ + Saves the currently displayed image to the specified file. The image is stored + in the requested file format (bmp, jpg or png). By default. it will save the raw + camera image and an image with the overlays that are currently visible on the + camera view. Using a parameter, one can decide to only save either raw image, + overlay image or both. By Specifying 'ALL' as the mount position, the captured + screenshot will consist of the currently selected camera layout without + providing the raw image. If MountPos and FullPath are empty then the current + camera view with overlays is copied to the clipboard. + API Status: published + Args: + MountPos:str = "Scope" + FullPath:str = "Image.bmp" + SnapShotMode:int = 2 + Command Timeout: 60000 + Example:SnapImage Scope C:/Temp/Image.bmp + """ + #-uc-# print (" |-> [SnapImage] MountPos: %s, FullPath %s, SnapShotMode%s" % (MountPos, FullPath, SnapShotMode)) diff --git a/src/FlexSensor/Prober/velox_api/velox/__init__.py b/src/FlexSensor/Prober/velox_api/velox/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..82d8e1f77fd39d9732964623ec949c196623afbb --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/__init__.py @@ -0,0 +1,9 @@ + +"""Determines the version of the sci module to import""" +from sys import version_info +from Prober.velox_api.velox.vxmessageserver import * + +if (version_info[0] > 2 and version_info[1] >= 5): + from Prober.velox_api.velox.sci35 import * +else: + from Prober.velox_api.velox.sci27 import * diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/1-SynchronousCommand.py b/src/FlexSensor/Prober/velox_api/velox/samples/1-SynchronousCommand.py new file mode 100644 index 0000000000000000000000000000000000000000..f4eb99eecf0d2ef248dc343843e894763e5d7763 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/1-SynchronousCommand.py @@ -0,0 +1,10 @@ +# Demonstrate simple synchronous commands + +import velox +with velox.MessageServerInterface() as msgServer: + response = velox.IsAppRegistered('Kernel') + if response < 0 : + print('Could not register application.') + + x,y,z = velox.ReadChuckPosition("Microns") + print(x,y,z) diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/2-AsynchronousCommand.py b/src/FlexSensor/Prober/velox_api/velox/samples/2-AsynchronousCommand.py new file mode 100644 index 0000000000000000000000000000000000000000..674e47292f2f15491642df41f481c57b63ae79ff --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/2-AsynchronousCommand.py @@ -0,0 +1,3 @@ +# Asyncronous commands require the user to implement async Python routines +# There is no special support for asynchronous commands biult in to the +# velox Python libraries. diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/3-Notifications.py b/src/FlexSensor/Prober/velox_api/velox/samples/3-Notifications.py new file mode 100644 index 0000000000000000000000000000000000000000..537df71bfad7233afc12b42c198197b14fb8dc3e --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/3-Notifications.py @@ -0,0 +1,4 @@ +# There is no support for SCI Notifications in the velox Python +# library. If notification handling is required, consider the +# C, C++, or C# libraires of the Velox Integration Toolkit. + diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/4-CustomCommands.py b/src/FlexSensor/Prober/velox_api/velox/samples/4-CustomCommands.py new file mode 100644 index 0000000000000000000000000000000000000000..0a612fe5229cea34af9e68e1bc67ddb357933357 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/4-CustomCommands.py @@ -0,0 +1,26 @@ +# Demonstrate Custom User Commands +# +# Custom commands are commands added to the commands.user.txt file. +# See the Velox Integration Toolkit documentation for details +# +# Because custom user commands are not part of the velox Python library, +# use the generic sendSciCommand of the MessageServer class to send the command. +# +# The code below shows two ways to call sendSciCommand: one using the msgServer +# object from the 'with' statement on the second line of code, and one using the +# full path velox.MessageServerInterface.sendSciCommand() +# +# The parameters are a string containing the name of the command and a string +# containing any arguemnts that should be sent to the command. +# +# rsp = msgServer.sendSciCommand('commandName', 'arguments separated by spaces') +# +# The example blow does not use a custom command, but demonstrates calling the +# echodata test commmd to demonstrate the use os sendSciCommand + +import velox +with velox.MessageServerInterface() as msgServer: + rsp = msgServer.sendSciCommand('EchoData', 'Hello') + print(rsp) + rsp = velox.MessageServerInterface.sendSciCommand('echodata', 'World') + print(rsp) diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/5-WaferStepping.py b/src/FlexSensor/Prober/velox_api/velox/samples/5-WaferStepping.py new file mode 100644 index 0000000000000000000000000000000000000000..794e07a013322ea6b8d15f72fc33efffb719d8b9 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/5-WaferStepping.py @@ -0,0 +1,38 @@ +# Demonstrate Die Stepping in WaferMap + +import velox + +def perform_measurement(die): + if die.CurSite > 0: + print(f'Measure at die <{die[0], die[1]}> subdie {die.CurSite} of {die.LastSiteIndex}') + else: + print(f'Measure at die <{die[0], die[1]}>') + +with velox.MessageServerInterface() as msgServer: + try: + rsp = velox.IsAppRegistered('Kernel') + print('IsAppRegistered Kernel: %s' % rsp) + + + rsp = velox.StepFirstDie() + perform_measurement(rsp) + + while(True): + rsp = velox.StepNextDie() + perform_measurement(rsp) + + x,y,z = velox.ReadChuckPosition('Y','H', 'D') + print('The Chuck is at <%s,%s,%s>'% (x, y, z)) + + except velox.SciException as e: + if (e.code == '703'): + print('Die Stepping Completed') + elif e.code == '512': + print('There was an error. The error code was %s.' % e.code) + print('This may mean that the WaferMAp application is not running.') + print('Make sure that the WaferMap application is running and try again.') + print(e) + else: + print('We caught an exception with error code %s as:' % e.code) + print(e) + diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/6-TesterInterface.py b/src/FlexSensor/Prober/velox_api/velox/samples/6-TesterInterface.py new file mode 100644 index 0000000000000000000000000000000000000000..03448e3546a50092e476414243278b3be17ef625 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/6-TesterInterface.py @@ -0,0 +1,3 @@ +# The velox Python library does not support incomming SCI +# Commands at this time. To implement incomming command functionality, +# see the examples for C++ and C# in the Vlox Integration Toolkit. diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/7-TesterControl.py b/src/FlexSensor/Prober/velox_api/velox/samples/7-TesterControl.py new file mode 100644 index 0000000000000000000000000000000000000000..2c45e935dbe8161e0ba4c068c5eaddf0e05758e4 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/7-TesterControl.py @@ -0,0 +1 @@ +# There is no specific Python example for Tester Control diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/8-SimpleUIExample.py b/src/FlexSensor/Prober/velox_api/velox/samples/8-SimpleUIExample.py new file mode 100644 index 0000000000000000000000000000000000000000..537c80d6897058660138fd5f8b0cc38e4837e061 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/8-SimpleUIExample.py @@ -0,0 +1,3 @@ +# User interface applications in Python often use TKinter +# or some other GUI framework. Users should see Python UI +# Dccumentstion for examples. diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/SiPTools_test.py b/src/FlexSensor/Prober/velox_api/velox/samples/SiPTools_test.py new file mode 100644 index 0000000000000000000000000000000000000000..2cfe247894d61359ff5edd41c76e614f95af714c --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/SiPTools_test.py @@ -0,0 +1,88 @@ +# import velox will choose the correct version of the library +# based on the version of Python being executed +import velox +import inspect + +# import sys for this example, but it is not required for VPI +import sys + + + +# print the version of Python that is running, just to see that it is working +print('Using Python Version ' + sys.version) + +# Connect to the message server using a 'with' statement. +# The application name registered with the Velox Message Server +# will be the name of our script. Keep a reference to +# the object returned by velox.MessageServerInterface +# - in this example, we call it msgServer + +# the parameters to MessageServerInterface are optional. +# For a local connection, you can leave them blank. If +# connecting to a remote machine, add keyword parameters and set the +# address and socket +# velox.MessageServerInterface(ipaddr='localhost',targetSocket=1412) + +with velox.MessageServerInterface() as msgServer: + # as long as the connection was successful, we can send some commands. + # if it was not successful, an exception is thrown. + + + # try some SCI Command Examples + + # The SCI commands in the velox module have docstrings to describe + # their function, inputs, and outputs. + # You can print them from a Python command to see what the function does. + + # print the docstring for the ReportKernelVersion command + # ReportKernelVersion returns 2 values. + # here is the description of the command + + print(velox.ReportKernelVersion.__doc__) + + # SCI commands return a namedtuple if multiple values are returned. + # ReportKernelVersion returns a version number and a description. + # You can acess the return values by name or by indexing the tuple. + + v = velox.ReportKernelVersion() + print('The kernel version is', v.Version, 'and', v.Description) + print('The kernel version array is', v[0], 'and', v[1]) + + # a more convenient example is to unpack the tuple into variables + # as part of the function call. + # here we get variables named ver and desc and use them directly + ver, desc = velox.ReportKernelVersion() + print('Got ', ver, 'and', desc) + + # The Echo Data command just returns its own first input. + # Echo data only returns the first string in the parameter list. + # To get a string with spaces to display, we need to add double quotes. + # Try it both ways to see the difference. The first one below does + # what we expect. The second only prints the first word. + # The third assigns a return value to a variable + + print(velox.EchoData('"Hi World1"')) + + print(velox.EchoData("AreaScan(1,1)")) + + print(velox.EchoData("Hi World2")) + evalue = velox.EchoData("Echo_This") + + # ReadChuckPosition returns 3 values. Here we print the entire tuple + # to show the tuple name and the names of the 3 return values + print(velox.ReadChuckPosition("Microns")) + + + + #velox.MoveChuck(-2000,-2000,"Relative") + + # it is possible to send raw command strings with the + # sendSciCommand function. + # it isn't recommended, but in some cases, it might be necessary. + # it is much easier and 'safer' to use the defined SCI functions. + # note that this is a function of MessageServerInterface, + # not a velox module function + + print(msgServer.sendSciCommand("echodata", rparams='"RawHello Velox"')) + + print(msgServer.sendSciCommand("SearchFirstLight",rparams='1 0')) \ No newline at end of file diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/__init__.py b/src/FlexSensor/Prober/velox_api/velox/samples/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/velox.tar.gz b/src/FlexSensor/Prober/velox_api/velox/samples/velox.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3d40814fd761e46f15751cca86ef1edfe1e9ebb7 Binary files /dev/null and b/src/FlexSensor/Prober/velox_api/velox/samples/velox.tar.gz differ diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/vpi-ExceptionHandlingSample.py b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-ExceptionHandlingSample.py new file mode 100644 index 0000000000000000000000000000000000000000..a518b179b579b94a68caad65035c0b49092f8bb9 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-ExceptionHandlingSample.py @@ -0,0 +1,12 @@ +import velox + +with velox.MessageServerInterface() as msgServer: + + # FindFocus will throw an exception because we aren't properly set up yet. + # This is to demonstrate exception handling. + try: + print(velox.FindFocus()) + except velox.SciException as e: + print('We caught an exception as expected:') + print(e) + diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/vpi-MinimalSample.py b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-MinimalSample.py new file mode 100644 index 0000000000000000000000000000000000000000..e7f242892e9e154b7ae8364a6f680d5867b159a4 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-MinimalSample.py @@ -0,0 +1,9 @@ +import velox + +with velox.MessageServerInterface() as msgServer: + + ver, desc = velox.ReportKernelVersion() + print('Got ', ver, 'and', desc) + x,y,z = velox.ReadChuckPosition("Inches") + print(x,y,z) + diff --git a/src/FlexSensor/Prober/velox_api/velox/samples/vpi-StartHereSample.py b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-StartHereSample.py new file mode 100644 index 0000000000000000000000000000000000000000..f0f1bc9227cad4600659da5d8e511846e8698b1e --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/samples/vpi-StartHereSample.py @@ -0,0 +1,85 @@ +# import velox will choose the correct version of the library +# based on the version of Python being executed +import velox + +# import sys for this example, but it is not required for VPI +import sys + +# print the version of Python that is running, just to see that it is working +print('Using Python Version ' + sys.version) + +# Connect to the message server using a 'with' statement. +# The application name registered with the Velox Message Server +# will be the name of our script. Keep a reference to +# the object returned by velox.MessageServerInterface +# - in this example, we call it msgServer + +# the parameters to MessageServerInterface are optional. +# For a local connection, you can leave them blank. If +# connecting to a remote machine, add keyword parameters and set the +# address and socket +# velox.MessageServerInterface(ipaddr='localhost',targetSocket=1412) + +with velox.MessageServerInterface() as msgServer: + # as long as the connection was successful, we can send some commands. + # if it was not successful, an exception is thrown. + + + # try some SCI Command Examples + + # The SCI commands in the velox module have docstrings to describe + # their function, inputs, and outputs. + # You can print them from a Python command to see what the function does. + + # print the docstring for the ReportKernelVersion command + # ReportKernelVersion returns 2 values. + # here is the description of the command + + print(velox.ReportKernelVersion.__doc__) + + # SCI commands return a namedtuple if multiple values are returned. + # ReportKernelVersion returns a version number and a description. + # You can acess the return values by name or by indexing the tuple. + + v = velox.ReportKernelVersion() + print('The kernel version is', v.Version, 'and', v.Description) + print('The kernel version array is', v[0], 'and', v[1]) + + # a more convenient example is to unpack the tuple into variables + # as part of the function call. + # here we get variables named ver and desc and use them directly + ver, desc = velox.ReportKernelVersion() + print('Got ', ver, 'and', desc) + + # The Echo Data command just returns its own first input. + # Echo data only returns the first string in the parameter list. + # To get a string with spaces to display, we need to add double quotes. + # Try it both ways to see the difference. The first one below does + # what we expect. The second only prints the first word. + # The third assigns a return value to a variable + + print(velox.EchoData('"Hi World1"')) + + print(velox.EchoData("AreaScan(1,1)")) + + print(velox.EchoData("Hi World2")) + evalue = velox.EchoData("Echo_This") + + # ReadChuckPosition returns 3 values. Here we print the entire tuple + # to show the tuple name and the names of the 3 return values + print(velox.ReadChuckPosition("Microns")) + + + + velox.MoveChuck(-2000,-2000,"Relative") + + # it is possible to send raw command strings with the + # sendSciCommand function. + # it isn't recommended, but in some cases, it might be necessary. + # it is much easier and 'safer' to use the defined SCI functions. + # note that this is a function of MessageServerInterface, + # not a velox module function + + print(msgServer.sendSciCommand("echodata", rparams='"RawHello Velox"')) + + print(msgServer.sendSciCommand("SearchFirstLight",rparams='1 0')) \ No newline at end of file diff --git a/src/FlexSensor/Prober/velox_api/velox/sci27.py b/src/FlexSensor/Prober/velox_api/velox/sci27.py new file mode 100644 index 0000000000000000000000000000000000000000..16dac8e5d5e2643b8a8b4b1e6485bd4c06e97b6d --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/sci27.py @@ -0,0 +1,11998 @@ +from velox.vxmessageserver import * +from decimal import Decimal +from collections import namedtuple + +""" +Velox SCI Commands +This module provides a function interface to the Cascade Microtech Velox software suite. +The module was auto-generated from the commands.info.xml file on 2019-11-09. +737 SCI commands were found and included. + +To use this module, your code must import the veloxsci.py module. +Create a connection to the Velox Message Server using the 'with MessageServerInterface():' +command as shown in the sample below. + +The Velox Message Server must be running prior to establishing a connection. +To start the Message Server, run Velox. + +The sample code to use this module is: + +import velox +with velox.MessageServerInterface() as msgServer: + + # Your Code: try some SCI Commands - such as: + response = velox.ReportKernelVersion() + print ('The kernel version is', response.Version, 'and', response.Description) + +""" +def EchoData(TestCmd=""): + """ + Test Command for the Kernel Communication. Like a ping command, the given text + string is returned unchanged. + API Status: published + Args: + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:EchoData Test + """ + rsp = MessageServerInterface.sendSciCommand("EchoData",TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportKernelVersion(Module=""): + """ + Returns the version information of the kernel or the control box code. The + "Version" value contains version number and revision level of the actual Kernel + implementation. The text string contains a code description, version number and + the revision date. + API Status: published + Args: + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:ReportKernelVersion K + """ + rsp = MessageServerInterface.sendSciCommand("ReportKernelVersion",Module) + global ReportKernelVersion_Response + if not "ReportKernelVersion_Response" in globals(): ReportKernelVersion_Response = namedtuple("ReportKernelVersion_Response", "Version,Description") + return ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReadProberStatus(): + """ + Returns an actual status information of the prober. + API Status: published + Returns: + FlagsBusy:int + FlagsContact:int + Mode:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadProberStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadProberStatus") + global ReadProberStatus_Response + if not "ReadProberStatus_Response" in globals(): ReadProberStatus_Response = namedtuple("ReadProberStatus_Response", "FlagsBusy,FlagsContact,Mode,IsQuiet") + return ReadProberStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3])) + +def EnableMotorQuiet(WantQuietModeOn="", Stage=""): + """ + Toggles the motor power for quiet probing. In most applications this feature is + not required. However, for special measurements it may be necessary to reduce + the noise of the system. Quiet on turns off the motor power for all stages (or + the one specified with the optional parameter). Quiet off will turn on the motor + power of all stages (or the one specified with the optional parameter) for + subsequent movements. A move command will also turn on the motor power of the + moved stage automatically. For automatical switching of the quiet mode refer to + Auto Quiet functionality. Sending 'EnableMotorQuiet 1' will enable the quiet + mode for all stages. Sending 'EnableMotorQuiet 1 C' will only enable the quiet + mode for the chuck stage. Sending 'EnableMotorQuiet 1 1' will only enable the + quiet mode for the Positioner1 stage. Sending 'EnableMotorQuiet 0 S' will only + disable the quiet mode for the scope stage. + API Status: published + Args: + WantQuietModeOn:int = 0 + Stage:str = "None" + Command Timeout: 10000 + Example:EnableMotorQuiet 1 + """ + MessageServerInterface.sendSciCommand("EnableMotorQuiet",WantQuietModeOn,Stage) + + +def SetChuckVacuum(WantChuckVacuumOn=""): + """ + Toggles the chuck vacuum on (1) or off (0). Can return vacuum timeout error for + stations with wafer vacuum sensors in case no wafer was detected. + API Status: published + Args: + WantChuckVacuumOn:int = 0 + Command Timeout: 10000 + Example:SetChuckVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetChuckVacuum",WantChuckVacuumOn) + + +def SetMicroLight(WantIlluminatorOn=""): + """ + Toggles the microscope light channel of the peripheral output board and all + cameras. Notifications: 7 + API Status: published + Args: + WantIlluminatorOn:int = 2 + Command Timeout: 5000 + Example:SetMicroLight 1 + """ + MessageServerInterface.sendSciCommand("SetMicroLight",WantIlluminatorOn) + + +def SetBeaconStatus(FlagsMode="", PulseWidthRed="", PulseWidthGreen="", PulseWidthYellow="", PulseWidthBlue="", PulseWidthWhite=""): + """ + This command controls the beacon channel of the peripheral output board. All + lights can be switched on, off, or blinking. Setting an interval to zero means, + that the corresponding light will be statically on or off. The minimum blinking + interval is 50ms. + API Status: published + Args: + FlagsMode:int = 0 + PulseWidthRed:int = 1000 + PulseWidthGreen:int = 0 + PulseWidthYellow:int = 0 + PulseWidthBlue:int = 0 + PulseWidthWhite:int = 0 + Command Timeout: 5000 + Example:SetBeaconStatus 1 1000 + """ + MessageServerInterface.sendSciCommand("SetBeaconStatus",FlagsMode,PulseWidthRed,PulseWidthGreen,PulseWidthYellow,PulseWidthBlue,PulseWidthWhite) + + +def SetOutput(Channel="", WantOutputOn="", PulseTime=""): + """ + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: published + Args: + Channel:int = 1 + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetOutput 4 0 + """ + MessageServerInterface.sendSciCommand("SetOutput",Channel,WantOutputOn,PulseTime) + + +def StopAllMovements(): + """ + Stops all Prober movements immediately. The response status value of any pending + movement will signify that the stop command was executed. + API Status: published + Command Timeout: 5000 + Example:StopAllMovements + """ + MessageServerInterface.sendSciCommand("StopAllMovements") + + +def InkDevice(FlagsInker="", PulseWidth=""): + """ + Inks the current device under test. The range of PulseWidth is 20ms to 2000ms. + For correct function, the inkers have to be linked to default outputs. + API Status: published + Args: + FlagsInker:int = 0 + PulseWidth:int = 50 + Command Timeout: 10000 + Example:InkDevice 1 40 + """ + MessageServerInterface.sendSciCommand("InkDevice",FlagsInker,PulseWidth) + + +def ReadProbeSetup(): + """ + Returns the current positioner configuration. The output pattern is: 1. Type + Positioner 1 2. Type Positioner 2 3. Type Positioner 3 4. Type Positioner 4 5. + Type Positioner 5 6. Axis Positioner 1 (Bit 0: XY, Bit 1: Z) 7. Axis Positioner + 2 (Bit 0: XY, Bit 1: Z) 8. Axis Positioner 3 (Bit 0: XY, Bit 1: Z) 9. Axis + Positioner 4 (Bit 0: XY, Bit 1: Z) 10. Axis Positioner 5 (Bit 0: XY, Bit 1: Z) + 11. Type Positioner 6 12. Axis Positioner 6 (Bit 0: XY, Bit 1: Z) + API Status: published + Returns: + TypePositioner1:int + TypePositioner2:int + TypePositioner3:int + TypePositioner4:int + TypePositioner5:int + AxisPositioner1:int + AxisPositioner2:int + AxisPositioner3:int + AxisPositioner4:int + AxisPositioner5:int + TypePositioner6:int + AxisPositioner6:int + Command Timeout: 5000 + Example:ReadProbeSetup + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSetup") + global ReadProbeSetup_Response + if not "ReadProbeSetup_Response" in globals(): ReadProbeSetup_Response = namedtuple("ReadProbeSetup_Response", "TypePositioner1,TypePositioner2,TypePositioner3,TypePositioner4,TypePositioner5,AxisPositioner1,AxisPositioner2,AxisPositioner3,AxisPositioner4,AxisPositioner5,TypePositioner6,AxisPositioner6") + return ReadProbeSetup_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11])) + +def ReadSystemStatus(): + """ + Returns the system options which are currently enabled at the prober. + API Status: published + Returns: + Name:str + System:str + ChuckXY:int + ChuckZ:int + ChuckTheta:int + ScopeXY:int + ScopeZ:int + EdgeSensor:int + OperationalMode:str + Turret:int + TemperatureChuck:int + AuxSiteCount:int + PlatenXY:int + PlatenZ:int + LoaderGateState:str + NucleusType:str + Command Timeout: 10000 + Example:ReadSystemStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadSystemStatus") + global ReadSystemStatus_Response + if not "ReadSystemStatus_Response" in globals(): ReadSystemStatus_Response = namedtuple("ReadSystemStatus_Response", "Name,System,ChuckXY,ChuckZ,ChuckTheta,ScopeXY,ScopeZ,EdgeSensor,OperationalMode,Turret,TemperatureChuck,AuxSiteCount,PlatenXY,PlatenZ,LoaderGateState,NucleusType") + return ReadSystemStatus_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),str(rsp[14]),str("" if len(rsp) < 16 else ' '.join(rsp[15:]))) + +def SetExternalMode(Mode=""): + """ + If 'R' is sent, it sets the external mode of the kernel. This disables most of + the control box functions (except the LOCAL function key). Otherwise, this + command re-enables all functions of the control box. + API Status: published + Args: + Mode:str = "L" + Command Timeout: 5000 + Example:SetExternalMode L + """ + MessageServerInterface.sendSciCommand("SetExternalMode",Mode) + + +def SetStageLock(Stage="", WantStageLock="", Application=""): + """ + Enables or disables the stage lock functionality. Stages which are locked can't + be moved in any way. If the joystick controller is locked, the display and the + keys are deactivated. The name of the application can be stored by using the + Application Name parameter and is shown in lock-caused error messages. + API Status: published + Args: + Stage:str = "0" + WantStageLock:int = 1 + Application:str = "" + Command Timeout: 10000 + Example:SetStageLock C 0 WaferMap + """ + MessageServerInterface.sendSciCommand("SetStageLock",Stage,WantStageLock,Application) + + +def ReadSensor(Channel="", Type=""): + """ + Returns the actual status of the specified input channel, output channel or edge + sensor. The signal table is described in the Hardware Manual. Each used IO-board + has 16 channels (max. 4 IO-boards are supported), what results in a domain of 64 + channel numbers. Beyond this range there are pseudo channels, which are used for + special purposes. Pseudo channels: + API Status: published + Args: + Channel:int = 1 + Type:str = "Input" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadSensor 11 I + """ + rsp = MessageServerInterface.sendSciCommand("ReadSensor",Channel,Type) + return int(rsp[0]) + +def GetStageLock(Stage=""): + """ + Reads whether stages or joystick controller are locked. + API Status: published + Args: + Stage:str = "0" + Returns: + Locks:int + Application:str + Command Timeout: 10000 + Example:GetStageLock C + """ + rsp = MessageServerInterface.sendSciCommand("GetStageLock",Stage) + global GetStageLock_Response + if not "GetStageLock_Response" in globals(): GetStageLock_Response = namedtuple("GetStageLock_Response", "Locks,Application") + return GetStageLock_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetBackSideMode(WantBackSideMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets bottomside mode. In this mode the Z axis is reverse and the + command MoveChuckLoad is not allowed. + API Status: internal + Args: + WantBackSideMode:int = 0 + Command Timeout: 5000 + Example:SetBackSideMode 1 + """ + MessageServerInterface.sendSciCommand("SetBackSideMode",WantBackSideMode) + + +def GetBackSideMode(): + """ + Returns the current side mode. + API Status: published + Returns: + IsBackSideModeOn:int + Command Timeout: 5000 + Example:GetBackSideMode + """ + rsp = MessageServerInterface.sendSciCommand("GetBackSideMode") + return int(rsp[0]) + +def SetDarkMode(WantSetDarkMode=""): + """ + Switches off all LEDs on the Control Box, on the positioners, and on the screen + of the Control Box and also the light of the cameras. + API Status: published + Args: + WantSetDarkMode:int = 0 + Command Timeout: 5000 + Example:SetDarkMode 1 + """ + MessageServerInterface.sendSciCommand("SetDarkMode",WantSetDarkMode) + + +def GetDarkMode(): + """ + Returns the current mode of the light sources. + API Status: published + Returns: + IsDarkMode:int + Command Timeout: 5000 + Example:GetDarkMode + """ + rsp = MessageServerInterface.sendSciCommand("GetDarkMode") + return int(rsp[0]) + +def DockChuckCamera(ConnectCamera="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Connect or disconnect the chuck camera to the chuck stage. The command is only + available for the Prober type PA300BEP. + API Status: internal + Args: + ConnectCamera:str = "ParkPos" + Velocity:Decimal = 100 + Command Timeout: 300000 + Example:DockChuckCamera P 75 + """ + MessageServerInterface.sendSciCommand("DockChuckCamera",ConnectCamera,Velocity) + + +def ReadCBoxStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current selected stage of the joystick controller. + API Status: internal + Returns: + Stage:str + Command Timeout: 5000 + Example:ReadCBoxStage + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxStage") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxStage(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current stage of the joystick controller. + API Status: internal + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:SetCBoxStage C + """ + MessageServerInterface.sendSciCommand("SetCBoxStage",Stage) + + +def ReadCBoxPosMonConf(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current setting of the joystick controllers position monitor for the + secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + PosRef:str + Unit:str + Command Timeout: 5000 + Example:ReadCBoxPosMonConf C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxPosMonConf",Stage) + global ReadCBoxPosMonConf_Response + if not "ReadCBoxPosMonConf_Response" in globals(): ReadCBoxPosMonConf_Response = namedtuple("ReadCBoxPosMonConf_Response", "PosRef,Unit") + return ReadCBoxPosMonConf_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetCBoxPosMonConf(Stage="", PosRef="", Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Configures the joystick controller position monitor for the secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + PosRef:str = "Zero" + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetCBoxPosMonConf C Z Y + """ + MessageServerInterface.sendSciCommand("SetCBoxPosMonConf",Stage,PosRef,Unit) + + +def ReadCBoxCurrSpeed(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CBoxSpeed:str + Command Timeout: 5000 + Example:ReadCBoxCurrSpeed C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxCurrSpeed",Stage) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxCurrSpeed(Stage="", CBoxSpeed=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CBoxSpeed:str = "Speed4" + Command Timeout: 5000 + Example:SetCBoxCurrSpeed C 3 + """ + MessageServerInterface.sendSciCommand("SetCBoxCurrSpeed",Stage,CBoxSpeed) + + +def MoveChuckAsync(XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck stage to the specified X,Y position without waiting for the move + to be finished If chuck Z is in contact height or higher, the chuck will drop to + separation. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveChuckAsync 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeAsync(XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the scope stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveScopeAsync 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveProbeAsync(Probe="", XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the probe stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAsync",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def ReadChuckStatus(): + """ + Returns the current chuck status. Every bit in the bit fields works like a + boolean value: One <1> means true/on and zero <0> means false/off. + Its counted from LSB to MSB. - _FlagsInit_: X, Y, Z, Theta - _FlagsMode_: + HasOvertravel, HasAutoZ, HasInterlock, ContactSearch, IsContactSet, + EdgeInterlock, QuietContact, IsLocked - _FlagsLimit_: XHigh, XLow, YHigh, YLow, + ZHigh, ZLow, ThetaHigh, ThetaLow - _FlagsMoving_: X, Y, Z, Theta All parameters + are provided as indirect access (e.g. first bit of M_pvecFlagsInit can be + accessed by M_pbIsInitX). + API Status: published + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsVacuumOn:int + PresetHeight:str + LoadPos:str + IsLiftDown:int + CameraConnection:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckStatus") + global ReadChuckStatus_Response + if not "ReadChuckStatus_Response" in globals(): ReadChuckStatus_Response = namedtuple("ReadChuckStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,IsVacuumOn,PresetHeight,LoadPos,IsLiftDown,CameraConnection,IsQuiet") + return ReadChuckStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),int(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),str(rsp[9]),int(rsp[10])) + +def ReadChuckPosition(Unit="", PosRef="", Comp=""): + """ + Returns the current chuck stage position in X, Y and Z. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadChuckPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckPosition",Unit,PosRef,Comp) + global ReadChuckPosition_Response + if not "ReadChuckPosition_Response" in globals(): ReadChuckPosition_Response = namedtuple("ReadChuckPosition_Response", "X,Y,Z") + return ReadChuckPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadChuckHeights(Unit=""): + """ + Returns the current settings used for the chuck Z movement. `Contact` is the + contact-height from zero in default compensation. The other heights are relative + to this. If no contact is set, the value will be -1. + API Status: published + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + SearchGap:Decimal + Command Timeout: 5000 + Example:ReadChuckHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckHeights",Unit) + global ReadChuckHeights_Response + if not "ReadChuckHeights_Response" in globals(): ReadChuckHeights_Response = namedtuple("ReadChuckHeights_Response", "Contact,Overtravel,AlignDist,SepDist,SearchGap") + return ReadChuckHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def InitChuck(FlagsInit="", FlagsDirection="", FlagsMoveRange=""): + """ + Machine Coordinate System: Chuck X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - _FlagsMoveRange_: + X, Y, Z, Theta All flags can be accessed by indirect members. Initializes the + chuck stage and resets current coordinate system. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 150000 + Example:InitChuck 7 0 0 + """ + MessageServerInterface.sendSciCommand("InitChuck",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveChuck(XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the chuck stage to the specified X,Y position. If chuck Z is in contact + height or higher, Interlock and Auto Z flags will be analyzed and stage will + behave correspondingly - can move to separation first or return an error: + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MoveChuck 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuck",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveChuckIndex(XSteps="", YSteps="", PosRef="", Velocity=""): + """ + Moves the chuck stage in index steps. This command modifies Die Home Position. + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveChuckSubsite(XValue="", YValue="", Unit="", Velocity=""): + """ + Moves the chuck stage to the specified X, Y sub-site position. Die home position + is defined by destination position of last successful MoveChuck or + MoveChuckIndex commands. MoveChuckVelocity does not touch die home position. If + you have moved chuck with MoveChuckVelocity, "MoveChuckSubsite 0 0" will move it + back to die home position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckSubsite 200 200 Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSubsite",XValue,YValue,Unit,Velocity) + + +def MoveChuckContact(Velocity=""): + """ + Performs a movement of chuck Z axis to preset contact height or will return + error if no contact height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckContact 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckContact",Velocity) + + +def MoveChuckAlign(Velocity=""): + """ + Moves the chuck Z axis to the align height. If no Contact height is set will + return an error. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAlign",Velocity) + + +def MoveChuckSeparation(Velocity=""): + """ + Moves the chuck Z axis to the separation height. Returns error if no Contact + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSeparation",Velocity) + + +def MoveChuckLoad(LoadPosition=""): + """ + Moves the Chuck stage in X, Y, Z and Theta to the load position. + API Status: published + Args: + LoadPosition:str = "First" + Command Timeout: 60000 + Example:MoveChuckLoad 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckLoad",LoadPosition) + + +def MoveChuckZ(Height="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the chuck Z axis to the specified height. If contact is set, only moves up + to contact height will be allowed. If overtravel is enabled - up to overtravel + height. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 60000 + Example:MoveChuckZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckZ",Height,PosRef,Unit,Velocity,Comp) + + +def SearchChuckContact(Height="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the chuck Z axis to the specified height and sets contact. The move stops + immediately if the Contact Sensor ( Edge Sensor) is triggered. If no contact has + been found and an old one was set before the old contact will not get lost, it + will be reset. + API Status: published + Args: + Height:Decimal = 100 + PosRef:str = "Relative" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 60000 + Example:SearchChuckContact 1000 R Y 10 + """ + rsp = MessageServerInterface.sendSciCommand("SearchChuckContact",Height,PosRef,Unit,Velocity,Comp) + return Decimal(rsp[0]) + +def MoveChuckVelocity(PolarityX="", PolarityY="", PolarityZ="", VelocityX="", VelocityY="", VelocityZ=""): + """ + Moves the chuck stage in velocity mode. The motion continues until the + StopChuckMovement command is received, or the end limit is reached. + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveChuckVelocity + + 0 100 30 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopChuckMovement(FlagsStop=""): + """ + Stops chuck movement for the given axis. Notifications: 31 / 32 / 5 + API Status: published + Args: + FlagsStop:int = 15 + Command Timeout: 5000 + Example:StopChuckMovement 7 + """ + MessageServerInterface.sendSciCommand("StopChuckMovement",FlagsStop) + + +def SetChuckMode(Overtravel="", AutoZ="", Interlock="", ContactSearch="", EdgeInterlock="", QuietContact=""): + """ + Mode manages the way the chuck behaves when it is in contact height. Chuck mode + is made from 6 flags and you can control all of them using this command. Every + flag can be turned on by using value 1 or turned off by using value 0. If you do + not want to change a flag - use value of 2. + API Status: published + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + ContactSearch:int = 2 + EdgeInterlock:int = 2 + QuietContact:int = 2 + Command Timeout: 5000 + Example:SetChuckMode 2 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetChuckMode",Overtravel,AutoZ,Interlock,ContactSearch,EdgeInterlock,QuietContact) + + +def SetChuckHome(Mode="", Unit="", XValue="", YValue=""): + """ + Sets wafer and die home position, which can be used later as coordinate system + for movements. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetChuckHome",Mode,Unit,XValue,YValue) + + +def SetChuckIndex(XValue="", YValue="", Unit=""): + """ + Sets the wafer index size. Normally the size of one die. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetChuckIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetChuckIndex",XValue,YValue,Unit) + + +def SetChuckHeight(PresetHeight="", Mode="", Unit="", Value=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation. A predefined contact search gap is able to write. No data + in the optional parameters sets contact height at current position. If Mode is + '0', contact height can be set at current position. The levels O, A, S and T + support no Mode '0'. If Mode is 'V' and no value for height is specified - + default 0 will be used, what potentially can be not what you expect. If Mode is + 'R', contact height can be invalidated. The levels O, A, S and T support no Mode + 'R'. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHeight C V Y 5000. + """ + MessageServerInterface.sendSciCommand("SetChuckHeight",PresetHeight,Mode,Unit,Value) + + +def ReadChuckIndex(Unit=""): + """ + The command gets the current die size which is stored in the kernel. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadChuckIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckIndex",Unit) + global ReadChuckIndex_Response + if not "ReadChuckIndex_Response" in globals(): ReadChuckIndex_Response = namedtuple("ReadChuckIndex_Response", "IndexX,IndexY") + return ReadChuckIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveChuckTransfer(): + """ + Moves the Chuck to the Transfer Position. If the movement starts in Load + Position (where it's possible to pull out the chuck) the handling of the Add On + Platen or the Pin Chuck is integrated. + API Status: published + Command Timeout: 90000 + Example:MoveChuckTransfer + """ + MessageServerInterface.sendSciCommand("MoveChuckTransfer") + + +def MoveChuckLift(SetLift=""): + """ + Moves the chuck to the upper (0) or lower = lifted (1) position. This initiates + motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveChuckLift 1 + """ + MessageServerInterface.sendSciCommand("MoveChuckLift",SetLift) + + +def SetChuckThermoScale(ScaleX="", ScaleY=""): + """ + Thermo drifts of the wafer will be compensated. The compensation is not + persistent, (power off - this compensation is deleted). The algorithm works as + an additional one. This is for an iterative usage, so: 1. `ResetProber H` 2. + `SetChuckThermoScale 1.5 1.5` 3. `SetChuckThermoScale 1.5 1.5` will result in a + scale of 2.25 in both directions. The thermal scale can also be reset using the + command 'SetChcukThermoValue 20 C' + API Status: published + Args: + ScaleX:Decimal = 1 + ScaleY:Decimal = 1 + Command Timeout: 5000 + Example:SetChuckThermoScale 1.000005 1.0000045 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoScale",ScaleX,ScaleY) + + +def ReadChuckThermoScale(): + """ + Read the linear scaling value of the chuck. + API Status: published + Returns: + ScaleX:Decimal + ScaleY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoScale + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoScale") + global ReadChuckThermoScale_Response + if not "ReadChuckThermoScale_Response" in globals(): ReadChuckThermoScale_Response = namedtuple("ReadChuckThermoScale_Response", "ScaleX,ScaleY") + return ReadChuckThermoScale_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetChuckThermoValue(Temperature="", Unit="", ExpCoeffX="", ExpCoeffY=""): + """ + Set a temperature and optional the expansion coefficient. The temperature for + normal level is 20 degree. The scaling factor at this temperature is 1.0. If you + set the temperature directly the controller calculates the stage difference in + the coordinate system. For the calculation use the set coefficient of expansion + from the controller. The default coefficient of expansion is based on silicon: + 2.33E-06 1/K. + API Status: published + Args: + Temperature:Decimal = 0 + Unit:str = "Celsius" + ExpCoeffX:Decimal = 0 + ExpCoeffY:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckThermoValue 250 C 2.43 2.32 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoValue",Temperature,Unit,ExpCoeffX,ExpCoeffY) + + +def ReadChuckThermoValue(Unit=""): + """ + Read the current temperature (either set or calculated) for the thermal scaling. + With SetChuckThermoScale in use, the value will be calculated by the current + scale and the expansion factor of silicium. The temperature that is read with + this command is not identical to the current chuck temperature. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + Temperature:Decimal + ExpCoeffX:Decimal + ExpCoeffY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoValue C + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoValue",Unit) + global ReadChuckThermoValue_Response + if not "ReadChuckThermoValue_Response" in globals(): ReadChuckThermoValue_Response = namedtuple("ReadChuckThermoValue_Response", "Temperature,ExpCoeffX,ExpCoeffY") + return ReadChuckThermoValue_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetChuckTableID(TableName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ChuckTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetChuckTableID ChuckTable + """ + rsp = MessageServerInterface.sendSciCommand("GetChuckTableID",TableName) + return int(rsp[0]) + +def MoveChuckTablePoint(TableID="", PointID="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move the chuck to the next stored table site. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckTablePoint 3 10 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckTablePoint",TableID,PointID,Velocity) + + +def ReadChuckTablePoint(TableID="", PointID="", Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the table site information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadChuckTablePoint 10 250 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTablePoint",TableID,PointID,Unit) + global ReadChuckTablePoint_Response + if not "ReadChuckTablePoint_Response" in globals(): ReadChuckTablePoint_Response = namedtuple("ReadChuckTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadChuckTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetChuckTablePoint(TableID="", PointID="", CoordX="", CoordY="", Unit="", CoordSystem=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the chuck table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetChuckTablePoint 10 12000.0 2344.0 Y F + """ + rsp = MessageServerInterface.sendSciCommand("SetChuckTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearChuckTablePoint(TableID="", StartPoint="", EndPoint=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of chuck table site points in the in the Kernel. If Start + Point is -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearChuckTablePoint 5 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearChuckTablePoint",TableID,StartPoint,EndPoint) + global ClearChuckTablePoint_Response + if not "ClearChuckTablePoint_Response" in globals(): ClearChuckTablePoint_Response = namedtuple("ClearChuckTablePoint_Response", "ClearNumber,ValidNumber") + return ClearChuckTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def AttachAmbientWafer(MoveTimeMs=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is moved to slowly attach a wafer that is at ambient temperature while + the chuck is hot. The command acts similar to MoveChuckTransfer when moving + out of Load 2 but will use a much slower Z velocity. This is only supported + for BnR-machines (CM300 and Summit200) at the moment. + API Status: internal + Args: + MoveTimeMs:Decimal = 30000 + Command Timeout: 300000 + Example:AttachAmbientWafer + """ + MessageServerInterface.sendSciCommand("AttachAmbientWafer",MoveTimeMs) + + +def ReadThetaStatus(): + """ + Returns the actual status of the chuck Theta axis. + API Status: published + Returns: + IsInit:int + FlagsLimit:int + IsMoving:int + Command Timeout: 5000 + Example:ReadThetaStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaStatus") + global ReadThetaStatus_Response + if not "ReadThetaStatus_Response" in globals(): ReadThetaStatus_Response = namedtuple("ReadThetaStatus_Response", "IsInit,FlagsLimit,IsMoving") + return ReadThetaStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadThetaPosition(Unit="", PosRef=""): + """ + Returns the actual Theta position. + API Status: published + Args: + Unit:str = "Degrees" + PosRef:str = "Home" + Returns: + Position:Decimal + Command Timeout: 5000 + Example:ReadThetaPosition D Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaPosition",Unit,PosRef) + return Decimal(rsp[0]) + +def InitTheta(FlagsDoPlus="", FlagsMoveRange=""): + """ + Performs an initialization move and resets the coordinate system of the Theta + axis. + API Status: published + Args: + FlagsDoPlus:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitTheta 0 0 + """ + MessageServerInterface.sendSciCommand("InitTheta",FlagsDoPlus,FlagsMoveRange) + + +def MoveTheta(Position="", PosRef="", Unit="", Velocity=""): + """ + Moves the chuck Theta axis to the specified position. The positive direction is + counter-clockwise. + API Status: published + Args: + Position:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Degrees" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveTheta 1000. R E + """ + MessageServerInterface.sendSciCommand("MoveTheta",Position,PosRef,Unit,Velocity) + + +def MoveThetaVelocity(Polarity="", Velocity=""): + """ + Moves the chuck Theta axis in velocity mode. The positive direction is counter- + clockwise. The motion continues until the StopThetaMovement command is received, + or the end limit (error condition) is reached. This command is mostly used for + joystick movements that do not have a target destination. + API Status: published + Args: + Polarity:str = "Fixed" + Velocity:Decimal = 0 + Command Timeout: 240000 + Example:MoveThetaVelocity + 67 + """ + MessageServerInterface.sendSciCommand("MoveThetaVelocity",Polarity,Velocity) + + +def StopThetaMovement(): + """ + Stops any type (velocity, position etc.) of chuck Theta axis movement. This is + treated as a smooth stop rather than an emergency stop. + API Status: published + Command Timeout: 5000 + Example:StopThetaMovement + """ + MessageServerInterface.sendSciCommand("StopThetaMovement") + + +def SetThetaHome(Mode="", Unit="", Position=""): + """ + Sets the chuck Theta position to home. This position is usable as reference + position for other commands. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Degrees" + Position:Decimal = 0 + Command Timeout: 5000 + Example:SetThetaHome 0 + """ + MessageServerInterface.sendSciCommand("SetThetaHome",Mode,Unit,Position) + + +def ScanChuckZ(ZDistance="", TriggerEveryNthCycle="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts moving the chuck from the current position with Velocity [%] over + ZDistance (sign is important, as a negative sign will move chuck down during + scan) - Predefined camera trigger pulses (TTL active high for at least 5us) will + be sent during the scan every passed number of BnR cyclics (800us per cyclic) + until the ZDistance has been reached. Command returns number of positions and + all compensated Z Positions from Zero, where the trigger was sent. + API Status: internal + Args: + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 3 + Velocity:Decimal = 10 + Returns: + NumberOfPositions:int + TriggerPositions:str + Command Timeout: 60000 + Example:ScanChuckZ 300 3 1.5 + """ + rsp = MessageServerInterface.sendSciCommand("ScanChuckZ",ZDistance,TriggerEveryNthCycle,Velocity) + global ScanChuckZ_Response + if not "ScanChuckZ_Response" in globals(): ScanChuckZ_Response = namedtuple("ScanChuckZ_Response", "NumberOfPositions,TriggerPositions") + return ScanChuckZ_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def MoveChuckZSafe(): + """ + Moves the chuck Z axis to a z height considered safe. This is either the lower + Z-Fence or the kernel setup item Chuck:SafeTransferHeight (which ever is larger) + API Status: published + Command Timeout: 60000 + Example:MoveChuckZSafe + """ + MessageServerInterface.sendSciCommand("MoveChuckZSafe") + + +def SetPlatenMode(Overtravel="", AutoZ="", Interlock="", AutoZFollow="", AutoQuiet=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The mode manages the way the platen behaves when it is in contact height. Platen + mode is made up from 5 flags and the user can control all of them by using this + command. Every flag can be turned on by setting value 1 or turned off by setting + value 0. If no change for a flag is wanted, use the value of 2. + API Status: internal + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Command Timeout: 5000 + Example:SetPlatenMode 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetPlatenMode",Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + + +def MovePlatenLift(SetLift=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen to the high (0) or low = lifted (1) position. This initiates + motion; the actual movement may take some seconds. + API Status: internal + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MovePlatenLift 1 + """ + MessageServerInterface.sendSciCommand("MovePlatenLift",SetLift) + + +def SearchPlatenContact(Height="", PosRef="", Unit="", Velocity="", CompLayer=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Searches contact height using the edge sensor using a z movement of the platen + stage + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + CompLayer:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("SearchPlatenContact",Height,PosRef,Unit,Velocity,CompLayer) + return Decimal(rsp[0]) + +def ReadPlatenStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current platen status. + API Status: internal + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + PresetHeight:str + IsLiftDown:int + Command Timeout: 10000 + Example:ReadPlatenStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenStatus") + global ReadPlatenStatus_Response + if not "ReadPlatenStatus_Response" in globals(): ReadPlatenStatus_Response = namedtuple("ReadPlatenStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,PresetHeight,IsLiftDown") + return ReadPlatenStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ReadPlatenPosition(Unit="", PosRef="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the platens X, Y and Z axes. The default + compensation is the currently selected compensation for the stage. + API Status: internal + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadPlatenPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenPosition",Unit,PosRef,Comp) + global ReadPlatenPosition_Response + if not "ReadPlatenPosition_Response" in globals(): ReadPlatenPosition_Response = namedtuple("ReadPlatenPosition_Response", "X,Y,Z") + return ReadPlatenPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadPlatenHeights(Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual settings for the probe Z movement. + API Status: internal + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadPlatenHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenHeights",Unit) + global ReadPlatenHeights_Response + if not "ReadPlatenHeights_Response" in globals(): ReadPlatenHeights_Response = namedtuple("ReadPlatenHeights_Response", "Contact,Overtravel,AlignDist,SepDist") + return ReadPlatenHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def InitPlaten(FlagsInit="", FlagsDirection="", FlagsMoveRange=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the platens X, Y and Z axes. Currently the initialization in + negative direction and the move range scan are not supported. + API Status: internal + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitPlaten 4 + """ + MessageServerInterface.sendSciCommand("InitPlaten",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MovePlatenZ(Height="", PosRef="", Unit="", Velocity="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the specified height. If contact is set, only moves + up to contact height will be allowed. If overtravel is enabled - up to + overtravel height. + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MovePlatenZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MovePlatenZ",Height,PosRef,Unit,Velocity,Comp) + + +def MovePlatenContact(Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a movement of platen Z axis to preset contact height or returns an + error, if no contact height is set. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenContact 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenContact",Velocity) + + +def MovePlatenAlign(Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the align height. If no contact height is set, the + command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenAlign 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenAlign",Velocity) + + +def MovePlatenSeparation(Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the separation height. If no contact height is set, + the command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenSeparation 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenSeparation",Velocity) + + +def MovePlatenVelocity(PolarityX="", PolarityY="", PolarityZ="", VelocityX="", VelocityY="", VelocityZ=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen stage in velocity mode. The motion continues until the + StopPlatenMovement command is received, or the software fence is reached. + API Status: internal + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 240000 + Example:MovePlatenVelocity + + 0 67 50 0 + """ + MessageServerInterface.sendSciCommand("MovePlatenVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopPlatenMovement(FlagsStop=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the movement of a set of platen axes immediately. + API Status: internal + Args: + FlagsStop:int = 7 + Command Timeout: 10000 + Example:StopPlatenMovement 4 + """ + MessageServerInterface.sendSciCommand("StopPlatenMovement",FlagsStop) + + +def SetPlatenHeight(PresetHeight="", Mode="", Unit="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation height. A command without data sets contact height at + current position. + API Status: internal + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 10000 + Example:SetPlatenHeight C V Y 5000 + """ + MessageServerInterface.sendSciCommand("SetPlatenHeight",PresetHeight,Mode,Unit,Value) + + +def ReadManualPlatenState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the current status of the manual platen. THis is only supported for + Nucleus and Summit200. + API Status: internal + Returns: + IsUp:int + IsDown:int + IsSafe:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadManualPlatenState") + global ReadManualPlatenState_Response + if not "ReadManualPlatenState_Response" in globals(): ReadManualPlatenState_Response = namedtuple("ReadManualPlatenState_Response", "IsUp,IsDown,IsSafe") + return ReadManualPlatenState_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadScopeStatus(): + """ + Returns the current scope status. + API Status: published + Returns: + FlagsInit:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsScopeLiftUp:int + PresetHeight:str + IsScopeLight:int + FlagsMode:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadScopeStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeStatus") + global ReadScopeStatus_Response + if not "ReadScopeStatus_Response" in globals(): ReadScopeStatus_Response = namedtuple("ReadScopeStatus_Response", "FlagsInit,FlagsLimit,FlagsMoving,Comp,IsScopeLiftUp,PresetHeight,IsScopeLight,FlagsMode,IsQuiet") + return ReadScopeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),str(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def ReadScopePosition(Unit="", PosRef="", Comp=""): + """ + Returns the actual scope stage position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadScopePosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopePosition",Unit,PosRef,Comp) + global ReadScopePosition_Response + if not "ReadScopePosition_Response" in globals(): ReadScopePosition_Response = namedtuple("ReadScopePosition_Response", "X,Y,Z") + return ReadScopePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeHeights(Unit=""): + """ + Returns the actual settings of the focus height, align gap, and separation gap + for the scope Z axis. + API Status: published + Args: + Unit:str = "Microns" + Returns: + FocusHeight:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadScopeHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeHeights",Unit) + global ReadScopeHeights_Response + if not "ReadScopeHeights_Response" in globals(): ReadScopeHeights_Response = namedtuple("ReadScopeHeights_Response", "FocusHeight,AlignDist,SepDist") + return ReadScopeHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def InitScope(FlagsInit="", FlagsDirection="", FlagsMoveRange=""): + """ + Initializes the microscope stage in X, Y and Z. The Axis default is all axes and + the Direction default is XY in minus and Z in plus. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 240000 + Example:InitScope 3 0 0 + """ + MessageServerInterface.sendSciCommand("InitScope",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveScope(XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 70000 + Example:MoveScope 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScope",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeIndex(XSteps="", YSteps="", PosRef="", Velocity=""): + """ + Moves the microscope stage in index steps. If no PositionReference byte is + passed the scope will step relative to the wafer home position. ('R' means the + step relative to current position). + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveScopeZ(Height="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves the microscope Z axis to the specified height. Default velocity is 100%. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 120000 + Example:MoveScopeZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeZ",Height,PosRef,Unit,Velocity,Comp) + + +def SetScopeMode(QuietMode="", FollowMode=""): + """ + Scope mode is made up of two flags which can be controlled using this command. + Each flag can be turned on by using value 1 or turned off by using value 0. If + you do not want to change a flag, use value of 2. + API Status: published + Args: + QuietMode:int = 2 + FollowMode:int = 2 + Command Timeout: 5000 + Example:SetScopeMode 2 2 + """ + MessageServerInterface.sendSciCommand("SetScopeMode",QuietMode,FollowMode) + + +def MoveScopeVelocity(PolarityX="", PolarityY="", PolarityZ="", VelocityX="", VelocityY="", VelocityZ=""): + """ + Moves the microscope stage in velocity mode. The motion continues until the + StopScopeMovement command is received, or the end limit (error condition) is + reached. Axes parameter: '+' move this axis in plus direction '-' move this axis + in minus direction '0' Do not change this axis + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveScopeVelocity + + 0 67 100 0 + """ + MessageServerInterface.sendSciCommand("MoveScopeVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopScopeMovement(FlagsStop=""): + """ + Stops scope movement for the given axis. A smooth stop is executed, no emergency + stop. + API Status: published + Args: + FlagsStop:int = 7 + Command Timeout: 5000 + Example:StopScopeMovement 7 + """ + MessageServerInterface.sendSciCommand("StopScopeMovement",FlagsStop) + + +def SetScopeHome(Mode="", Unit="", XValue="", YValue=""): + """ + Sets the scope Home position in X and Y. It identifies the scope coordinate + system for later movements. Usually this position is identical to the die home + location. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHome",Mode,Unit,XValue,YValue) + + +def SetScopeIndex(XValue="", YValue="", Unit=""): + """ + Sets the microscope index size. Normally set in relation to the wafer index + size. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetScopeIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetScopeIndex",XValue,YValue,Unit) + + +def SetScopeHeight(PresetHeight="", Mode="", Unit="", Value=""): + """ + This command defines scope focus height and the corresponding gaps for alignment + or separation. No data sets focus height at current position. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHeight F 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHeight",PresetHeight,Mode,Unit,Value) + + +def ReadScopeIndex(Unit=""): + """ + Returns the actual scope stage index values in X and Y. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadScopeIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeIndex",Unit) + global ReadScopeIndex_Response + if not "ReadScopeIndex_Response" in globals(): ReadScopeIndex_Response = namedtuple("ReadScopeIndex_Response", "IndexX,IndexY") + return ReadScopeIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveScopeFocus(Velocity=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 25000 + Example:MoveScopeFocus 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeFocus",Velocity) + + +def MoveScopeAlign(Velocity=""): + """ + Moves the Scope Z axis to the alignment height. If no focus height is set an + error will bereturned. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 10000 + Example:MoveScopeAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAlign",Velocity) + + +def MoveScopeSeparation(Velocity=""): + """ + Moves the scope Z axis to the separation height. Returns an error if no focus + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveScopeSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeSeparation",Velocity) + + +def MoveScopeLift(SetLift=""): + """ + Moves the microscope lift to the lower (0) or upper = lifted (1) position. This + initiates the motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveScopeLift 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeLift",SetLift) + + +def ReadTurretStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current status of the motorized turret. + API Status: internal + Returns: + IsMoving:int + Command Timeout: 5000 + Example:ReadTurretStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTurretStatus") + return int(rsp[0]) + +def SelectLens(Lens=""): + """ + Parfocality and para-centricity are adjusted according to the stored values. + This can be used with manual turrets to compensate for XYZ differences between + lenses. + API Status: published + Args: + Lens:int = 1 + Command Timeout: 30000 + Example:SelectLens 1 + """ + MessageServerInterface.sendSciCommand("SelectLens",Lens) + + +def GetScopeTable(TableName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ScopeTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetScopeTable ScopeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeTable",TableName) + return int(rsp[0]) + +def MoveScopeTablePoint(TableID="", PointID="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeTablePoint 10 5 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeTablePoint",TableID,PointID,Velocity) + + +def ReadScopeTablePoint(TableID="", PointID="", Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the scope table site Information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadScopeTablePoint 2 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTablePoint",TableID,PointID,Unit) + global ReadScopeTablePoint_Response + if not "ReadScopeTablePoint_Response" in globals(): ReadScopeTablePoint_Response = namedtuple("ReadScopeTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadScopeTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def ReadCurrentLens(): + """ + Returns the number of the current microscope lens. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:ReadCurrentLens + """ + rsp = MessageServerInterface.sendSciCommand("ReadCurrentLens") + return int(rsp[0]) + +def SetScopeTablePoint(TableID="", PointID="", CoordX="", CoordY="", Unit="", CoordSystem=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the scope table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetScopeTablePoint 10 10 8992.5 7883.0 Y H + """ + rsp = MessageServerInterface.sendSciCommand("SetScopeTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearScopeTablePoint(TableID="", StartPoint="", EndPoint=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of scope table site points in the Kernel. If Start Point is + -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearScopeTablePoint 2 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearScopeTablePoint",TableID,StartPoint,EndPoint) + global ClearScopeTablePoint_Response + if not "ClearScopeTablePoint_Response" in globals(): ClearScopeTablePoint_Response = namedtuple("ClearScopeTablePoint_Response", "ClearNumber,ValidNumber") + return ClearScopeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ReadScopeSiloCount(): + """ + Returns the number of silos in the scope fence. Will be zero if no silos are + configured. + API Status: published + Returns: + Count:int + Command Timeout: 5000 + Example:ReadScopeSiloCount + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSiloCount") + return int(rsp[0]) + +def ReadProbeStatus(Probe=""): + """ + Returns the current positioner's status. + API Status: published + Args: + Probe:int = 1 + Returns: + ProbeEcho:int + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + Side:str + PresetHeight:str + IsLiftUp:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadProbeStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeStatus",Probe) + global ReadProbeStatus_Response + if not "ReadProbeStatus_Response" in globals(): ReadProbeStatus_Response = namedtuple("ReadProbeStatus_Response", "ProbeEcho,FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,Side,PresetHeight,IsLiftUp,IsQuiet") + return ReadProbeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadProbePosition(Probe="", Unit="", PosRef="", Comp=""): + """ + Returns the actual positioner's position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + ProbeEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadProbePosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbePosition",Probe,Unit,PosRef,Comp) + global ReadProbePosition_Response + if not "ReadProbePosition_Response" in globals(): ReadProbePosition_Response = namedtuple("ReadProbePosition_Response", "ProbeEcho,X,Y,Z") + return ReadProbePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadProbeHeights(Probe="", Unit=""): + """ + Returns the actual settings for the probe Z movement. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadProbeHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeHeights",Probe,Unit) + global ReadProbeHeights_Response + if not "ReadProbeHeights_Response" in globals(): ReadProbeHeights_Response = namedtuple("ReadProbeHeights_Response", "ProbeEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadProbeHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def OrientProbe(Probe="", Side=""): + """ + Defines the orientation of the positioner's coordinate system and turns the + Y-axis of the probe coordinate system. + API Status: published + Args: + Probe:int = 1 + Side:str = "Left" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:OrientProbe 1 R + """ + rsp = MessageServerInterface.sendSciCommand("OrientProbe",Probe,Side) + return int(rsp[0]) + +def InitProbe(Probe="", FlagsInit="", FlagsDirection="", FlagsMoveRange="", FlagsInitInPlace=""): + """ + Performs an initialization move and resets the coordinate system of the given + positioner. + API Status: published + Args: + Probe:int = 1 + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + FlagsInitInPlace:int = 0 + Returns: + ProbeEcho:int + Command Timeout: 120000 + Example:InitProbe 1 7 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("InitProbe",Probe,FlagsInit,FlagsDirection,FlagsMoveRange,FlagsInitInPlace) + return int(rsp[0]) + +def MoveProbe(Probe="", XValue="", YValue="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbe 1 1000. 1000. R Y 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbe",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeIndex(Probe="", XSteps="", YSteps="", PosRef="", Velocity=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeIndex 1 1 1 R 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeIndex",Probe,XSteps,YSteps,PosRef,Velocity) + return int(rsp[0]) + +def MoveProbeContact(Probe="", Velocity=""): + """ + Moves the given ProbeHeads Z axis to the preset contact height. If no contact + height is set, the kernel will return a 'Contact height not set' error. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeContact 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeContact",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeAlign(Probe="", Velocity=""): + """ + Moves the given ProbeHeads Z axis to the align height. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeAlign 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAlign",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeSeparation(Probe="", Velocity=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeSeparation 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeSeparation",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeZ(Probe="", Height="", PosRef="", Unit="", Velocity="", Comp=""): + """ + Moves a given ProbeHeads Z axis to a defined Z height. + API Status: published + Args: + Probe:int = 1 + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeZ 1 1000. R Y 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeZ",Probe,Height,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeLift(Probe="", SetLift=""): + """ + Moves the positioner to the lower (0) or upper = lifted (1) position. The + command initiates the motion only, the whole movement may take some seconds. + API Status: published + Args: + Probe:int = 1 + SetLift:int = 1 + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:MoveProbeLift 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeLift",Probe,SetLift) + return int(rsp[0]) + +def MoveProbeVelocity(Probe="", PolarityX="", PolarityY="", PolarityZ="", VelocityX="", VelocityY="", VelocityZ=""): + """ + '+' Move this axis into plus direction '-' Move this axis into minus direction + '0' Do not change this axis + API Status: published + Args: + Probe:int = 1 + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeVelocity 1 + + Z 67 100 0 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeVelocity",Probe,PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + return int(rsp[0]) + +def StopProbeMovement(Probe="", FlagsStop=""): + """ + Stops positioner movement for the given axes immediately. A smooth stop is + performed. + API Status: published + Args: + Probe:int = 1 + FlagsStop:int = 7 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:StopProbeMovement 1 7 + """ + rsp = MessageServerInterface.sendSciCommand("StopProbeMovement",Probe,FlagsStop) + return int(rsp[0]) + +def SetProbeMode(Probe="", Overtravel="", AutoZ="", Interlock="", AutoZFollow="", AutoQuiet=""): + """ + The mode manages the way the chuck behaves when it is in contact height. + Positioner mode is made up from 5 flags and the user can control all of them by + using this command. Every flag can be turned on by setting value 1, or turned + off by setting value 0. Use the value 2 if no change for a flag is needed. + API Status: published + Args: + Probe:int = 1 + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeMode 1 2 2 2 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeMode",Probe,Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + return int(rsp[0]) + +def SetProbeHome(Probe="", Mode="", Unit="", XValue="", YValue=""): + """ + Sets the positioner's Home position in X and Y. This position identifies the + probe coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + Probe:int = 1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHome",Probe,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetProbeIndex(Probe="", XValue="", YValue="", Unit=""): + """ + Sets the positioner's index size or the location of the reference die relative + to the home die. + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeIndex",Probe,XValue,YValue,Unit) + return int(rsp[0]) + +def SetProbeHeight(Probe="", PresetHeight="", Mode="", Unit="", Value=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align, load and separation height. No data sets contact height at current + position. + API Status: published + Args: + Probe:int = 1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHeight",Probe,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadProbeIndex(Probe="", Unit=""): + """ + Returns the current positioner's wafer index values or the current positioner's + index positions for X and Y. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadProbeIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeIndex",Probe,Unit) + global ReadProbeIndex_Response + if not "ReadProbeIndex_Response" in globals(): ReadProbeIndex_Response = namedtuple("ReadProbeIndex_Response", "ProbeEcho,IndexX,IndexY") + return ReadProbeIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetProbeLED(Probe="", NewLEDState=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the positioner LED On or Off. + API Status: internal + Args: + Probe:int = 1 + NewLEDState:int = 0 + Returns: + ProbeEcho:int + LEDState:int + Command Timeout: 5000 + Example:SetProbeLED 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeLED",Probe,NewLEDState) + global SetProbeLED_Response + if not "SetProbeLED_Response" in globals(): SetProbeLED_Response = namedtuple("SetProbeLED_Response", "ProbeEcho,LEDState") + return SetProbeLED_Response(int(rsp[0]),int(rsp[1])) + +def GetProbeTableID(Probe="", TableName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the ID of a stored probe table or creates a new table. The ID is unique + for the name and the probe. The table itself has a string name. This name is not + case sensitive. The command has to be used before all other table commands can + be used. Access to tables is possible only with an ID Number (name dependent). + API Status: internal + Args: + Probe:int = 1 + TableName:str = "ProbeTable" + Returns: + ProbeEcho:int + TableID:int + Command Timeout: 5000 + Example:GetProbeTableID 1 ProbeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetProbeTableID",Probe,TableName) + global GetProbeTableID_Response + if not "GetProbeTableID_Response" in globals(): GetProbeTableID_Response = namedtuple("GetProbeTableID_Response", "ProbeEcho,TableID") + return GetProbeTableID_Response(int(rsp[0]),int(rsp[1])) + +def MoveProbeTablePoint(Probe="", TableID="", PointID="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: internal + Args: + Probe:int = 1 + TableID:int = 1 + PointID:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeTablePoint 3 14 10 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeTablePoint",Probe,TableID,PointID,Velocity) + return int(rsp[0]) + +def ReadProbeTablePoint(Probe="", TableID="", PointID="", Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the data from a point of a stored table in the Kernel. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadProbeTablePoint 2 4 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTablePoint",Probe,TableID,PointID,Unit) + global ReadProbeTablePoint_Response + if not "ReadProbeTablePoint_Response" in globals(): ReadProbeTablePoint_Response = namedtuple("ReadProbeTablePoint_Response", "ProbeEcho,CoordX,CoordY,CoordSystem") + return ReadProbeTablePoint_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetProbeTablePoint(Probe="", TableID="", PointID="", CoordX="", CoordY="", Unit="", CoordSystem=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets one point of a ProbeHeads table inside the Kernel. If there is still a + point with this index loaded, the Kernel returns an error. Number of positions + and number of tables are dependet on the internal memory. All positions are + stored persistent, that means after switching power on or off the positions are + still available. The table starts with point number 1 and ends with the ID 16. + The table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ProbeEcho:int + ValidPoint:int + Command Timeout: 5000 + Example:SetProbeTablePoint 3 12 10 8992.5 7883.0 Y Z M + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeTablePoint",Probe,TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + global SetProbeTablePoint_Response + if not "SetProbeTablePoint_Response" in globals(): SetProbeTablePoint_Response = namedtuple("SetProbeTablePoint_Response", "ProbeEcho,ValidPoint") + return SetProbeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ClearProbeTablePoint(Probe="", TableID="", StartPoint="", EndPoint=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of ProbeHead table site points in the Kernel. If StartPoint + is a negative value, the whole table will be deleted. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ProbeEcho:int + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearProbeTablePoint 3 4 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearProbeTablePoint",Probe,TableID,StartPoint,EndPoint) + global ClearProbeTablePoint_Response + if not "ClearProbeTablePoint_Response" in globals(): ClearProbeTablePoint_Response = namedtuple("ClearProbeTablePoint_Response", "ProbeEcho,ClearNumber,ValidNumber") + return ClearProbeTablePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def MoveScopeSilo(Index=""): + """ + Move the scope to the reference position of the given silo. The reference + position should be - if not defined otherwise - 200 um above the safe z-height + in the center of the scope. + API Status: published + Args: + Index:int = 1 + Command Timeout: 70000 + Example:MoveScopeSilo 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeSilo",Index) + + +def SetScopeSiloReference(Index="", X="", Y="", Z=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the reference position of a silo. The next time the scope moves to this + silo, it woll go to this position. The Referenceposition must be inside the silo + in xy and above the lower Z-Fence of the silo. Setting the reference position + directly on the fence in x, y or z typically leads to errors. Try to keep a + safety margin. + API Status: internal + Args: + Index:int = 1 + X:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeSiloReference 1 1000 2000 3000 + """ + MessageServerInterface.sendSciCommand("SetScopeSiloReference",Index,X,Y,Z) + + +def AlignChuckTheta(XDistance="", YDistance="", PosRef=""): + """ + This command causes a chuck Theta axis rotation to align the wafer to the chuck + X,Y movements. It can be used to perform a two point alignment with + P1(X1,Y1) and P2(X2,Y2) as two points on a wafer street line. The units of + the distances are not important - but both distances should use the same unit. + If one or both distances are zero, the command does not return an error and + instead ignore this alignment + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignChuckTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignChuckTheta",XDistance,YDistance,PosRef) + + +def AlignScopeTheta(XDistance="", YDistance="", PosRef=""): + """ + This command causes a virtual rotation of the scope coordinate system to align + the scope to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of X and Y distances: + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignScopeTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignScopeTheta",XDistance,YDistance,PosRef) + + +def AlignProbeTheta(Probe="", XDistance="", YDistance="", PosRef=""): + """ + This command causes a rotation of the coordinate system of given probe to align + the probe to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of Y and Y distances: + API Status: published + Args: + Probe:int = 1 + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:AlignProbeTheta 1 10000 10 R + """ + rsp = MessageServerInterface.sendSciCommand("AlignProbeTheta",Probe,XDistance,YDistance,PosRef) + return int(rsp[0]) + +def AlignCardTheta(Angle="", Unit="", PosRef=""): + """ + This command causes a rotation of the chuck coordinate system to align the chuck + X, Y axis to the probecard. The polarity of the data determines a left or a + right rotation of the chuck coordinate system. + API Status: published + Args: + Angle:Decimal = 0 + Unit:str = "Degrees" + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignCardTheta 2.5 D R + """ + MessageServerInterface.sendSciCommand("AlignCardTheta",Angle,Unit,PosRef) + + +def ReadCardTheta(Unit=""): + """ + Returns the angle between the chuck-coordinate-system and the probecard- + coordinate-system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadCardTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadCardTheta",Unit) + return Decimal(rsp[0]) + +def ReadChuckTheta(Unit=""): + """ + Returns the current chuck alignment angle which is identical to the current + value of theta rotation. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadChuckTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTheta",Unit) + return Decimal(rsp[0]) + +def ReadScopeTheta(Unit=""): + """ + Returns the scope's alignment angle, which is the angle between the chuck + coordinate system and the scope coordinate system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadScopeTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTheta",Unit) + return Decimal(rsp[0]) + +def ReadProbeTheta(Probe="", Unit=""): + """ + Returns the actual positioner's alignment angle, which is the angle between the + chuck coordinate system and the positioner coordinate system. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Degrees" + Returns: + ProbeEcho:int + Angle:Decimal + Command Timeout: 5000 + Example:ReadProbeTheta 1 D + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTheta",Probe,Unit) + global ReadProbeTheta_Response + if not "ReadProbeTheta_Response" in globals(): ReadProbeTheta_Response = namedtuple("ReadProbeTheta_Response", "ProbeEcho,Angle") + return ReadProbeTheta_Response(int(rsp[0]),Decimal(rsp[1])) + +def ReadJoystickSpeeds(Stage="", Axis=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the preset speeds, which are used by the joystick controller for moving a + single stage. The speeds can be read for XY, for Z and for Theta axis + separately. Jog timing and index timing are the times, the joystick controller + waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "X" + Returns: + JogTime:Decimal + Speed2:Decimal + Speed3:Decimal + Speed4:Decimal + IndexTime:Decimal + Command Timeout: 5000 + Example:ReadJoystickSpeeds S Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeeds",Stage,Axis) + global ReadJoystickSpeeds_Response + if not "ReadJoystickSpeeds_Response" in globals(): ReadJoystickSpeeds_Response = namedtuple("ReadJoystickSpeeds_Response", "JogTime,Speed2,Speed3,Speed4,IndexTime") + return ReadJoystickSpeeds_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetJoystickSpeeds(Stage="", JogTime="", Speed2="", Speed3="", Speed4="", IndexTime="", Axis=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the preset speeds, which are used by the joystick controller for moving a + single stage. After setting, the speeds can be selected by pressing the Speed n + buttons at the controller. The speeds must be set separately for XY, for Z and + for Theta axis. Jog timing and index timing are the times, the joystick + controller waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + JogTime:Decimal = 0 + Speed2:Decimal = 0 + Speed3:Decimal = 0 + Speed4:Decimal = 0 + IndexTime:Decimal = 0 + Axis:str = "X" + Command Timeout: 5000 + Example:SetJoystickSpeeds S 10 20 30 40 50 Z + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeeds",Stage,JogTime,Speed2,Speed3,Speed4,IndexTime,Axis) + + +def SetLoaderGate(Open=""): + """ + Opens or closes the loader gate. Automatic handling systems can load wafers to + the chuck through the gate. + API Status: published + Args: + Open:int = 0 + Command Timeout: 5000 + Example:SetLoaderGate 0 + """ + MessageServerInterface.sendSciCommand("SetLoaderGate",Open) + + +def ReadWaferStatus(): + """ + Returns whether the system detected a wafer. This feature can be used if the + probe station is equipped with a vacuum sensor and while vacuum is activated. + API Status: published + Returns: + SensedByVac:str + Command Timeout: 5000 + Example:ReadWaferStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadWaferStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadContactCount(Stage=""): + """ + Returns the number of times this stage moved to contact since the last time the + counter was reset. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Count:int + Command Timeout: 5000 + Example:ReadContactCount C + """ + rsp = MessageServerInterface.sendSciCommand("ReadContactCount",Stage) + return int(rsp[0]) + +def ResetContactCount(Stage=""): + """ + Resets the contact counter for the specified stage to zero. Notifications: 23 + API Status: published + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:ResetContactCount C + """ + MessageServerInterface.sendSciCommand("ResetContactCount",Stage) + + +def SetManualMode(Enable=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command enables the manual mode on Elite/Summit/S300 systems. This mode + will allow to move the chuck using the knobs. + API Status: internal + Args: + Enable:int = 1 + Command Timeout: 10000 + Example:SetManualMode 1 + """ + MessageServerInterface.sendSciCommand("SetManualMode",Enable) + + +def GetManualMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of the manual mode on Elite/Summit/S300 stations. + API Status: internal + Returns: + Enable:int + Command Timeout: 10000 + Example:GetManualMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetManualMode") + return int(rsp[0]) + +def GetAxisReverse(Stage="", Axis=""): + """ + Allows reading if an axis is reverse. + API Status: published + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + IsReverse:int + Command Timeout: 5000 + Example:GetAxisReverse C X + """ + rsp = MessageServerInterface.sendSciCommand("GetAxisReverse",Stage,Axis) + return int(rsp[0]) + +def EnableEdgeSensor(EdgeSensor="", Enable=""): + """ + Enables/disables the use of an edge sensor. + API Status: published + Args: + EdgeSensor:int = 1 + Enable:int = 1 + Command Timeout: 5000 + Example:EnableEdgeSensor 1 1 + """ + MessageServerInterface.sendSciCommand("EnableEdgeSensor",EdgeSensor,Enable) + + +def SetTypedOutput(Channel="", WantOutputOn="", PulseTime=""): + """ + Controls the kernel valve driver signals and can be used to drive the outputs. + API Status: published + Args: + Channel:str = "NoSensor" + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetTypedOutput WaferVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetTypedOutput",Channel,WantOutputOn,PulseTime) + + +def ReadTypedSensor(Channel=""): + """ + Returns the status of the specified input channel, output channel, or edge + sensor. + API Status: published + Args: + Channel:str = "NoSensor" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadTypedSensor EmoIn I + """ + rsp = MessageServerInterface.sendSciCommand("ReadTypedSensor",Channel) + return int(rsp[0]) + +def MoveCoolDownPosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck to the cool down position that is defined in KernelSetup. The + cooldown position is used to move the chuck away in XY while the robot is in the + chamber and tries to get a hot wafer. + API Status: internal + Command Timeout: 30000 + Example:MoveCoolDownPosition + """ + MessageServerInterface.sendSciCommand("MoveCoolDownPosition") + + +def ReadJoystickSpeedsCycle(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the cycling speeds - these are the speeds that are used by + the USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CycleJog:int + CycleSpeed2:int + CycleSpeed3:int + CycleSpeed4:int + CycleIndex:int + Command Timeout: 5000 + Example:ReadJoystickSpeedsCycle S + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeedsCycle",Stage) + global ReadJoystickSpeedsCycle_Response + if not "ReadJoystickSpeedsCycle_Response" in globals(): ReadJoystickSpeedsCycle_Response = namedtuple("ReadJoystickSpeedsCycle_Response", "CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex") + return ReadJoystickSpeedsCycle_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetJoystickSpeedsCycle(Stage="", CycleJog="", CycleSpeed2="", CycleSpeed3="", CycleSpeed4="", CycleIndex=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets the cycling speeds - these are the speeds that are used by the + USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + CycleJog:int = 0 + CycleSpeed2:int = 0 + CycleSpeed3:int = 0 + CycleSpeed4:int = 0 + CycleIndex:int = 0 + Command Timeout: 5000 + Example:SetJoystickSpeedsCycle C 1 1 1 1 1 + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeedsCycle",Stage,CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex) + + +def SendAUCSCommand(Command=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows sending low level AUCS commands to the ECX box stage. Only + applies to Elite/Summit/S300 stations. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 60000 + Example:SendAUCSCommand "MM 1 0 INIT 0" + """ + rsp = MessageServerInterface.sendSciCommand("SendAUCSCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadCompensationStatus(Stage="", Compensation=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command allows reading if a specific type of compensation is enabled or + disabled. Returns an error if this type of compensation is not available for + this stage. + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Returns: + Enabled:int + Active:int + Command Timeout: 5000 + Example:ReadCompensationStatus C A + """ + rsp = MessageServerInterface.sendSciCommand("ReadCompensationStatus",Stage,Compensation) + global ReadCompensationStatus_Response + if not "ReadCompensationStatus_Response" in globals(): ReadCompensationStatus_Response = namedtuple("ReadCompensationStatus_Response", "Enabled,Active") + return ReadCompensationStatus_Response(int(rsp[0]),int(rsp[1])) + +def RegisterNotification(NotificationCode="", WantNotification=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deprecated. All Kernel notifications are now enabled by default. + API Status: internal + Args: + NotificationCode:int = 0 + WantNotification:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterNotification",NotificationCode,WantNotification) + + +def AlertNotification(NotificationId="", Value1="", Value2="", Value3=""): + """ + This is not a regular command. Asynchronous notifications will be sent from the + Kernel controller to the host system only. All notifications can be switched off + and on, except the Prober reset notification (ID01). /warning This is a stub + implementation without appropriate handling + API Status: published + Args: + NotificationId:int = 0 + Value1:Decimal = 0 + Value2:Decimal = 0 + Value3:Decimal = 0 + Command Timeout: 5000 + Example:AlertNotification 31 195000 160000 0 + """ + MessageServerInterface.sendSciCommand("AlertNotification",NotificationId,Value1,Value2,Value3) + + +def SetCompensationStatus(Stage="", Compensation="", Status=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables a compensation mode for the specified stage + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Status:int = -1 + Command Timeout: 5000 + Example:SetCompensationStatus C A 1 + """ + MessageServerInterface.sendSciCommand("SetCompensationStatus",Stage,Compensation,Status) + + +def GetControllerInfo(ControllerInfo=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command gets the value "Value" for the parameter "Parameter". The unit is + parameter specific. + API Status: internal + Args: + ControllerInfo:str = "Unknown" + Returns: + Value:Decimal + Command Timeout: 1000 + Example:GetControllerInfo HasScanChuckZ + """ + rsp = MessageServerInterface.sendSciCommand("GetControllerInfo",ControllerInfo) + return Decimal(rsp[0]) + +def SetOperationalMode(OperationalMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + In unprotected mode a number of security features like software fence and + initialization necessity are deactivated. Unprotected mode is + deactivated automatically after 5 minutes. Sending 'SetOperationalMode U' + anytime before resets the timer back to 5 minutes. It is not necessary to + deactivate it before. **WARNING**: If unprotected mode is enabled, even the + most basic safety- and sanity-checks are skipped. Any movement may cause + irreparable damage to the prober or attached hardware. + API Status: internal + Args: + OperationalMode:str = "ProtectedMode" + Command Timeout: 5000 + Example:SetOperationalMode P + """ + MessageServerInterface.sendSciCommand("SetOperationalMode",OperationalMode) + + +def GetNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured Nano-chamber-state. + API Status: internal + Returns: + NanoChamberState:str + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetNanoChamberState(NanoChamberState=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the NanoChamber-state. + API Status: internal + Args: + NanoChamberState:str = "Free" + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetNanoChamberState",NanoChamberState) + + +def SetCameraCool(State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows to force activate/deactivate the camera cool output or to let it be set + automatically by purge control. + API Status: internal + Args: + State:int = 2 + Command Timeout: 10000 + Example:SetCameraCool 0 + """ + MessageServerInterface.sendSciCommand("SetCameraCool",State) + + +def ActivateChuckVacuum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the chuck vacuum and forces it to be on. This command ignores the + vacuum sensor and timeout. + API Status: internal + Command Timeout: 10000 + Example:ActivateChuckVacuum + """ + MessageServerInterface.sendSciCommand("ActivateChuckVacuum") + + +def ReadMatrixValues(Stage="", MatrixIndexX="", MatrixIndexY=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns a point from the matrix compensation table for the + specified axis from the kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + Returns: + XVal:Decimal + YVal:Decimal + Command Timeout: 5000 + Example:ReadMatrixValues C 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMatrixValues",Stage,MatrixIndexX,MatrixIndexY) + global ReadMatrixValues_Response + if not "ReadMatrixValues_Response" in globals(): ReadMatrixValues_Response = namedtuple("ReadMatrixValues_Response", "XVal,YVal") + return ReadMatrixValues_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetMatrixValues(Stage="", MatrixIndexX="", MatrixIndexY="", XVal="", YVal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Downloads a point of the matrix compensation table for a specified stage to the + kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + XVal:Decimal = 0 + YVal:Decimal = 0 + Command Timeout: 5000 + Example:SetMatrixValues C 0 0 5000.0 5000.0 2500.0 + """ + MessageServerInterface.sendSciCommand("SetMatrixValues",Stage,MatrixIndexX,MatrixIndexY,XVal,YVal) + + +def ReadMEAStatus(Stage="", Type=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads if the MEA file for a stage is loaded/enabled (Nucleus legacy stations + only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Returns: + Enable:int + Command Timeout: 5000 + Example:ReadMEAStatus C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMEAStatus",Stage,Type) + return int(rsp[0]) + +def LoadMEAFile(Stage="", Type="", Load=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Load the MEA file for a stage (Nucleus legacy stations only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Load:int = 0 + Command Timeout: 5000 + Example:LoadMEAFile C 0 1 + """ + MessageServerInterface.sendSciCommand("LoadMEAFile",Stage,Type,Load) + + +def ReadSoftwareLimits(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The command returns the positions of the actual software limits (end of move + range) for each axis of the specified stage in microns. If the Theta stage is + selected Z1 and Z2 include the values for the Theta limits. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + ZLowValue:Decimal + ZHighValue:Decimal + X1Value:Decimal + Y1Value:Decimal + X2Value:Decimal + Y2Value:Decimal + X3Value:Decimal + Y3Value:Decimal + X4Value:Decimal + Y4Value:Decimal + Command Timeout: 5000 + Example:ReadSoftwareLimits C + """ + rsp = MessageServerInterface.sendSciCommand("ReadSoftwareLimits",Stage) + global ReadSoftwareLimits_Response + if not "ReadSoftwareLimits_Response" in globals(): ReadSoftwareLimits_Response = namedtuple("ReadSoftwareLimits_Response", "ZLowValue,ZHighValue,X1Value,Y1Value,X2Value,Y2Value,X3Value,Y3Value,X4Value,Y4Value") + return ReadSoftwareLimits_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def SetSoftwareFence(Stage="", AuxID="", FenceForm="", XBase="", YBase="", XDist="", YDist=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets types and dimensions of technological software fences. It can + also be used for enabling and disabling the software fence. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + FenceForm:str = "None" + XBase:Decimal = 0 + YBase:Decimal = 0 + XDist:Decimal = 0 + YDist:Decimal = 0 + Command Timeout: 10000 + Example:SetSoftwareFence C 0 R 5000 5000 25000 25000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareFence",Stage,AuxID,FenceForm,XBase,YBase,XDist,YDist) + + +def GetSoftwareFence(Stage="", AuxID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the type and the dimensions of an actual set technological + software fence. In case of a rectangular software fence, X and Y coordinates of + the four edge points of the fence are given back. In case of a circular software + fence, X and Y coordinates of the center point and the radius are given back. + All other return values are filled with zeros. All position values are in + microns from zero. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + Returns: + FenceForm:str + XValue1:Decimal + YValue1:Decimal + XValue2:Decimal + YValue2:Decimal + XValue3:Decimal + YValue3:Decimal + XValue4:Decimal + YValue4:Decimal + Command Timeout: 10000 + Example:GetSoftwareFence C + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareFence",Stage,AuxID) + global GetSoftwareFence_Response + if not "GetSoftwareFence_Response" in globals(): GetSoftwareFence_Response = namedtuple("GetSoftwareFence_Response", "FenceForm,XValue1,YValue1,XValue2,YValue2,XValue3,YValue3,XValue4,YValue4") + return GetSoftwareFence_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8])) + +def GetZFence(Stage="", CompLayer=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands reads if the Z-Fence is activated and the currently set Z-fence + values for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CompLayer:str = "Default" + Returns: + Enabled:int + ZLow:Decimal + ZHigh:Decimal + Command Timeout: 10000 + Example:GetZFence S + """ + rsp = MessageServerInterface.sendSciCommand("GetZFence",Stage,CompLayer) + global GetZFence_Response + if not "GetZFence_Response" in globals(): GetZFence_Response = namedtuple("GetZFence_Response", "Enabled,ZLow,ZHigh") + return GetZFence_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetZFence(Stage="", Enabled="", ZLow="", ZHigh="", CompLayer=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands sets Z-Fence and the Z-fence values for the specified stage. + Values are stored uncompensated internally and set default compensated as + default. + API Status: internal + Args: + Stage:str = "Chuck" + Enabled:int = 0 + ZLow:Decimal = 0 + ZHigh:Decimal = 0 + CompLayer:str = "Default" + Command Timeout: 10000 + Example:SetZFence S 1 5000 10000 + """ + MessageServerInterface.sendSciCommand("SetZFence",Stage,Enabled,ZLow,ZHigh,CompLayer) + + +def ResetProber(Mode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the Prober and replaces the current configuration with a formerly + written recovery file. If no recovery file was written, the configuration is + reset to the version of the last Prober restart. For ProberBench electronics, + 'H' will restart the Operating system, 'S' will only restart the Kernel + application. For Windows Kernel, 'H' and 'S' are identical. + API Status: internal + Args: + Mode:str = "S" + Command Timeout: 20000 + Example:ResetProber S + """ + MessageServerInterface.sendSciCommand("ResetProber",Mode) + + +def ResetCBox(ResetMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reboots the operation system inside the Joystick Controller and restarts the + functionality. The restart will need a time of around 20 seconds. + API Status: internal + Args: + ResetMode:str = "S" + Command Timeout: 20000 + Example:ResetCBox S + """ + MessageServerInterface.sendSciCommand("ResetCBox",ResetMode) + + +def ReadStageLocations(Stage="", LocationType="", AuxID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The Home Position on the Chuck or ProbeHead Z axis is also called contact + height. The Home Position on the Scope Z axis is also called focus height. + API Status: internal + Args: + Stage:str = "Chuck" + LocationType:str = "Center" + AuxID:int = 0 + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadStageLocations C C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadStageLocations",Stage,LocationType,AuxID) + global ReadStageLocations_Response + if not "ReadStageLocations_Response" in globals(): ReadStageLocations_Response = namedtuple("ReadStageLocations_Response", "X,Y,Z") + return ReadStageLocations_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetDataIterator(ShowAll=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters. + and requires the GetNextDatum command. + API Status: internal + Args: + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 10000 + Example:GetDataIterator 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetDataIterator",ShowAll) + global GetDataIterator_Response + if not "GetDataIterator_Response" in globals(): GetDataIterator_Response = namedtuple("GetDataIterator_Response", "IdentityToken,SizeNoAll") + return GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def GetNextDatum(IdentityToken=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + Attributes:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:GetNextDatum 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetNextDatum",IdentityToken) + global GetNextDatum_Response + if not "GetNextDatum_Response" in globals(): GetNextDatum_Response = namedtuple("GetNextDatum_Response", "IsLastDatum,DatumCode,Attributes,PathNameDescrValue") + return GetNextDatum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetDatum(PathNameAndValue=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:SetDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetDatum",PathNameAndValue) + + +def GetDatum(PathName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + PathName:str = "" + Returns: + Attributes:int + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:GetDatum Chuck:AlignGap + """ + rsp = MessageServerInterface.sendSciCommand("GetDatum",PathName) + global GetDatum_Response + if not "GetDatum_Response" in globals(): GetDatum_Response = namedtuple("GetDatum_Response", "Attributes,DatumCode,ValueDesc") + return GetDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetRecoveryDatum(PathNameAndValue=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 5000 + Example:SetRecoveryDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetRecoveryDatum",PathNameAndValue) + + +def TraceStart(Controller=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the motion recording. The recording parameters are set in dynamic + kernel setup. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStart C + """ + MessageServerInterface.sendSciCommand("TraceStart",Controller) + + +def TraceStatus(Controller=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Checks the motion recording status for one stage. + API Status: internal + Args: + Controller:str = "Chuck" + Returns: + IsReady:int + SizeCh0Raw:int + SizeCh0Comp:int + SizeCh1Raw:int + SizeCh1Comp:int + SizeCh2Raw:int + SizeCh2Comp:int + SizeCh3Raw:int + SizeCh3Comp:int + Command Timeout: 10000 + Example:TraceStatus C + """ + rsp = MessageServerInterface.sendSciCommand("TraceStatus",Controller) + global TraceStatus_Response + if not "TraceStatus_Response" in globals(): TraceStatus_Response = namedtuple("TraceStatus_Response", "IsReady,SizeCh0Raw,SizeCh0Comp,SizeCh1Raw,SizeCh1Comp,SizeCh2Raw,SizeCh2Comp,SizeCh3Raw,SizeCh3Comp") + return TraceStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def TraceGetData(Controller="", Channel="", PointOne="", IsCompress=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a collection of five data pairs. A pair is the index and the value of a + recording point. If the stream is empty or at the end the index is 1 and the + value 0. The index is relative to the start of the motion recording. The + recording is clocked by the motion controller cycle. The cycle time is contained + in the Kernel setup. In the raw stream all recorded trace points are contained. + But in the compressed stream only the non-linear depending trace points are + contained. To reload the recording points the stream must be reset to the first + recording point. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + PointOne:int = 1 + IsCompress:int = 1 + Returns: + Point1:int + Value1:int + Point2:int + Value2:int + Point3:int + Value3:int + Point4:int + Value4:int + Point5:int + Value5:int + Command Timeout: 10000 + Example:TraceGetData C 0 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("TraceGetData",Controller,Channel,PointOne,IsCompress) + global TraceGetData_Response + if not "TraceGetData_Response" in globals(): TraceGetData_Response = namedtuple("TraceGetData_Response", "Point1,Value1,Point2,Value2,Point3,Value3,Point4,Value4,Point5,Value5") + return TraceGetData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def TraceSetDataPosition(Controller="", Channel="", NewPos="", IsCompress=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the index position in the raw or compressed stream for the next call of the + command TraceGetData. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + NewPos:int = 0 + IsCompress:int = 1 + Command Timeout: 10000 + Example:TraceSetDataPosition C 0 1000 1 + """ + MessageServerInterface.sendSciCommand("TraceSetDataPosition",Controller,Channel,NewPos,IsCompress) + + +def TraceStop(Controller=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the motion recording. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStop C + """ + MessageServerInterface.sendSciCommand("TraceStop",Controller) + + +def SetZProfilePoint(Stage="", XValue="", YValue="", ZGap="", PosRef="", Unit="", ZProfileType=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set a point for the Z height profile. If this profile is enabled, the Z height + depends on a X and Y coordinate. The Z value is a gap to the current Z height. + Positive values are elevated spots, negative values are hollows. The height + profile is used to adjust the Z height. The adjusted Z height at a X and Y + position is derivated from the nearest profile point. The Z contact level will + be calculated from the contact height and the stored Z gap at this point. See + GetZProfilePoint for details. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + ZGap:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + ValueCount:int + Command Timeout: 5000 + Example:SetZProfilePoint C 5000 5000 -3 H Y + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfilePoint",Stage,XValue,YValue,ZGap,PosRef,Unit,ZProfileType) + return int(rsp[0]) + +def ReadZProfilePoint(Stage="", Index="", PosRef="", Unit="", ZProfileType=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a single point and the corresponding Z gap of the Z height profile. The + different z profiles are: - transient: meant to be used on a per-wafer-basis, + default - persistent: configured once, stays in memory - persistent-offset: same + as persistent, active when offset is enabled - scratch: not used internaly. Can + be used to translate KernelDatums <-> ZProfile-Points + API Status: internal + Args: + Stage:str = "Chuck" + Index:int = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + XValue:Decimal + YValue:Decimal + ZGap:Decimal + ValueCount:int + Command Timeout: 5000 + Example:ReadZProfilePoint C 1 H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfilePoint",Stage,Index,PosRef,Unit,ZProfileType) + global ReadZProfilePoint_Response + if not "ReadZProfilePoint_Response" in globals(): ReadZProfilePoint_Response = namedtuple("ReadZProfilePoint_Response", "XValue,YValue,ZGap,ValueCount") + return ReadZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3])) + +def ClearZProfile(Stage="", ZProfileType=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clears all profile points. See GetZProfile for type description. + API Status: internal + Args: + Stage:str = "Chuck" + ZProfileType:int = 0 + Command Timeout: 5000 + Example:ClearZProfile C + """ + MessageServerInterface.sendSciCommand("ClearZProfile",Stage,ZProfileType) + + +def ReadScopeSilo(Index=""): + """ + Returns the definition of a silo. If the type is rectangle, center means + _Point1_. If the type is circle, the meaning of Pos2X and Pos2Y is undefined. + API Status: published + Args: + Index:int = 1 + Returns: + Type:str + CenterX:Decimal + CenterY:Decimal + Radius:Decimal + Pos2X:Decimal + Pos2Y:Decimal + ZHigh:Decimal + RefX:Decimal + RefY:Decimal + RefZ:Decimal + Command Timeout: 5000 + Example:ReadScopeSilo 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSilo",Index) + global ReadScopeSilo_Response + if not "ReadScopeSilo_Response" in globals(): ReadScopeSilo_Response = namedtuple("ReadScopeSilo_Response", "Type,CenterX,CenterY,Radius,Pos2X,Pos2Y,ZHigh,RefX,RefY,RefZ") + return ReadScopeSilo_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def NewProjectFile(FileName=""): + """ + Alerts applications if the project file was changed. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("NewProjectFile",FileName) + + +def SaveProjectFile(FileName=""): + """ + Alerts applications to save the current project. This notification _MUST_ only + be invoked by CommonCommands. Sending this notification directly _WILL_ give + erroneous results. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectFile",FileName) + + +def NewAccessLevel(AccessLevel="", UserName="", VeloxLocked=""): + """ + Alerts applications of new access level. + API Status: published + Args: + AccessLevel:str = "Engineer" + UserName:str = "" + VeloxLocked:int = 0 + Command Timeout: 5000 + Example:NewAccessLevel 1 + """ + MessageServerInterface.sendSciCommand("NewAccessLevel",AccessLevel,UserName,VeloxLocked) + + +def LicenseInfo(AnnualEnabled="", AnnualDaysLeft="", VeloxProEnabled="", VueTrackEnabled="", VueTrack4PEnabled="", ReAlignEnabled="", AutomationEnabled="", IdToolsEnabled="", IVistaEnabled="", IVistaProEnabled="", LaserCutterEnabled="", SiPToolsEnabled="", AutoRfEnabled=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener about the licensed Velox features. Is sent cyclically by + CommonCommands. + API Status: internal + Args: + AnnualEnabled:int = 1 + AnnualDaysLeft:int = 460 + VeloxProEnabled:int = 0 + VueTrackEnabled:int = 0 + VueTrack4PEnabled:int = 0 + ReAlignEnabled:int = 0 + AutomationEnabled:int = 0 + IdToolsEnabled:int = 0 + IVistaEnabled:int = 0 + IVistaProEnabled:int = 0 + LaserCutterEnabled:int = 0 + SiPToolsEnabled:int = 0 + AutoRfEnabled:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicenseInfo",AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled) + + +def RegisterProberAppChange(AppName="", SecName="", NewRegistered=""): + """ + Alerts applications that an application is registered or unregistered on + MsgServer. + API Status: published + Args: + AppName:str = "SharedTest" + SecName:str = "SharedTest" + NewRegistered:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterProberAppChange",AppName,SecName,NewRegistered) + + +def AlignmentModeChange(AlignmentMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications of a change of the current alignment mode + API Status: internal + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + Example:AlignmentModeChange OnAxis + """ + MessageServerInterface.sendSciCommand("AlignmentModeChange",AlignmentMode) + + +def KernelConnectionStatus(ControllerNum="", Type="", Result="", Desc=""): + """ + An example of Kernel Connection Status is "Windows Socket Error Number and + Error Description." + API Status: published + Args: + ControllerNum:int = 1 + Type:str = "Socket" + Result:str = "Disconnected" + Desc:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelConnectionStatus",ControllerNum,Type,Result,Desc) + + +def KernelCompensationStatusChange(Stage="", Compensation="", Enabled="", Active=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Compensation:str = "None" + Enabled:int = 0 + Active:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationStatusChange",Stage,Compensation,Enabled,Active) + + +def KernelCompensationLevelChange(Stage="", Comp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation level has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Comp:str = "None" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationLevelChange",Stage,Comp) + + +def MoveZCombinedStatusChange(Status="", PlatenSafe="", Height="", HeightMax="", HeightRelative="", SafeHeight="", Message=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the combined-z-move-system + API Status: internal + Args: + Status:str = "Off" + PlatenSafe:int = 0 + Height:Decimal = 0 + HeightMax:Decimal = 0 + HeightRelative:Decimal = 0 + SafeHeight:Decimal = 0 + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedStatusChange",Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message) + + +def MachineStateChange(MachineState=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the machine state + API Status: internal + Args: + MachineState:str = "Off" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MachineStateChange",MachineState) + + +def ChuckVacuumChangeRequest(VacuumState=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if the user requests a chuck vacuum change + API Status: internal + Args: + VacuumState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ChuckVacuumChangeRequest",VacuumState) + + +def SoftwareStopChangedNotify(SoftwareStopState=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if software stop was activated or deactivated + API Status: internal + Args: + SoftwareStopState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SoftwareStopChangedNotify",SoftwareStopState) + + +def KernelQuietModeChange(IsQuiet="", Stage="", IsStageQuiet=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs if the overall quiet mode changes and about changes of single stages + API Status: internal + Args: + IsQuiet:int = 0 + Stage:str = "None" + IsStageQuiet:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelQuietModeChange",IsQuiet,Stage,IsStageQuiet) + + +def ConfigurationChanged(ParameterChanged=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies that a configuration item has changed by some application + API Status: internal + Args: + ParameterChanged:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ConfigurationChanged",ParameterChanged) + + +def ScopeWorkingStageChanged(ScopeWorkingStage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs that a new working stage is active + API Status: internal + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ScopeWorkingStageChanged",ScopeWorkingStage) + + +def BnR_AxisNotify(Stage="", Axis="", State="", AdditionalStateInfo=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the user Interface and Kernel if the state of the axis has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + State:str = "NotExisting" + AdditionalStateInfo:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisNotify",Stage,Axis,State,AdditionalStateInfo) + + +def BnR_StageNotify(Stage="", State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the stage status has changed. + API Status: internal + Args: + Stage:str = "Chuck" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_StageNotify",Stage,State) + + +def BnR_InputNotify(Channel="", State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an input channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InputNotify",Channel,State) + + +def BnR_OutputNotify(Channel="", State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an output channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_OutputNotify",Channel,State) + + +def BnR_AxisStatusNotify(Stage="", Axis="", Initialized="", PositiveLimit="", NegativeLimit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener that an axis status has changed. Currently used to notify + the Kernel about the init state of a BnR axis. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Initialized:int = 0 + PositiveLimit:int = 0 + NegativeLimit:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisStatusNotify",Stage,Axis,Initialized,PositiveLimit,NegativeLimit) + + +def AutoXYModeChange(AutoXYModeOn=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by Spectrum if Automation was enabled or disabled. This can be AutoXY, + AutoZ or VueTrack. Handled by WaferMap to ensure that automation is executed + when stepping. + API Status: internal + Args: + AutoXYModeOn:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("AutoXYModeChange",AutoXYModeOn) + + +def ZoomLevelChange(ZoomLevel=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by OpticalControl when the AZoom zoom level is changed. Spectrum should + handle this so it doesn't have to poll OpticalControl for the current zoom + level. + API Status: internal + Args: + ZoomLevel:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ZoomLevelChange",ZoomLevel) + + +def BnR_AnalogIONotify(AnalogIO="", ValuePercent="", UnderOverflow="", Error=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state or value of an analog input or output channel + has changed. + API Status: internal + Args: + AnalogIO:str = "AO_PurgeDewPoint" + ValuePercent:Decimal = 0 + UnderOverflow:int = 0 + Error:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AnalogIONotify",AnalogIO,ValuePercent,UnderOverflow,Error) + + +def BnR_ControllerInfoNotify(ControllerNum="", ControllerInfo="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies the listener about changed controller info. Currently used to inform + Toolbar about the battery state of the BnR controller. + API Status: internal + Args: + ControllerNum:int = 1 + ControllerInfo:str = "BatteryOK" + Value:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_ControllerInfoNotify",ControllerNum,ControllerInfo,Value) + + +def BnR_PositionNotify(Stage="", XorT="", Y="", Z="", CommandedXorT="", CommandedY="", CommandedZ=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by BnR controller if a axis position has changed. Currently + used to notify the Kernel about the new axis position. + API Status: internal + Args: + Stage:str = "Chuck" + XorT:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + CommandedXorT:Decimal = 0 + CommandedY:Decimal = 0 + CommandedZ:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_PositionNotify",Stage,XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ) + + +def BnR_InfoNotify(InfoType="", Info=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Generic Information Notification + API Status: internal + Args: + InfoType:str = "" + Info:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InfoNotify",InfoType,Info) + + +def WMNewCurrentDie(DieX="", DieY="", XFromHome="", YFromHome="", CurSite="", LastSiteIndex=""): + """ + Alerts applications that WaferMap has a new position. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + XFromHome:Decimal = 0 + YFromHome:Decimal = 0 + CurSite:int = 1 + LastSiteIndex:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMNewCurrentDie",DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex) + + +def WMSetupChange(): + """ + Alerts applications that a wafer's parameters have been changed. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMSetupChange") + + +def ButtonPress(TargetIdent=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when button instrumented for guided workflow is pressed. The TargetIdent is + the identifier for the button as defined for the guided workflow. + API Status: internal + Args: + TargetIdent:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("ButtonPress",TargetIdent) + + +def CryoCmdReady(State="", Error="", ErrorDescription=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when the cooling or heating process was terminated successfully or + incorrectly. Returns the status with which the process was finished (IDLE, COLD, + COOL DOWN, WARMUP) and sends the error code and error message. + API Status: internal + Args: + State:str = "IDLE" + Error:int = 0 + ErrorDescription:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CryoCmdReady",State,Error,ErrorDescription) + + +def VMProjectLoaded(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent when Spectrum VS project has finished loading. + API Status: internal + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProjectLoaded") + + +def VMProbeCardData(Access="", FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent when a probe card file is loaded. + API Status: internal + Args: + Access:str = "L" + FileName:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProbeCardData",Access,FileName) + + +def TTLTestDone(): + """ + Alerts applications that the TTL Test is ready. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("TTLTestDone") + + +def PSStateChanged(State="", SubState="", Message="", Error=""): + """ + Notification sent when VeloxPro changes its running state. + API Status: published + Args: + State:str = "Unknown" + SubState:str = "Unknown" + Message:str = "" + Error:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSStateChanged",State,SubState,Message,Error) + + +def PSProgressChanged(ProgressPercent=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent during wafer stepping process. It updates the progress + information. 'Progress' is the relationship of dies tested to dies to be tested. + API Status: internal + Args: + ProgressPercent:Decimal = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSProgressChanged",ProgressPercent) + + +def PSLoaderUsage(UseLoader="", UseAutoWafer="", WaferSizes=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent to notify the listener about usage of Loader, usage of + fully/semiautomatic mode and supported wafer sizes of process station. + API Status: internal + Args: + UseLoader:int = 0 + UseAutoWafer:int = 0 + WaferSizes:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSLoaderUsage",UseLoader,UseAutoWafer,WaferSizes) + + +def LoaderMessage(Message=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by loader to display a message on the process station. + API Status: internal + Args: + Message:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("LoaderMessage",Message) + + +def OpenProjectDialog(ProjectFilename="", Option=""): + """ + Asks if the current project should be saved and then brings up the Open Project + window which opens the selected project file if the user clicks ok. + API Status: published + Args: + ProjectFilename:str = "" + Option:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("OpenProjectDialog",ProjectFilename,Option) + + +def SaveProjectAsDialog(): + """ + Brings up the Save Project window which saves the project if the user clicks ok. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsDialog") + + +def LoginDialog(LevelToOffer=""): + """ + Brings up the Login window and sends a New Access Level alert if the user enters + a valid password. + API Status: published + Args: + LevelToOffer:str = "1" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoginDialog",LevelToOffer) + + +def GetStatus(): + """ + Returns the current software status. The server holds and maintains the software + status. Status can be changed by using any of the following commands: + BeginProbing, LoginDialog, AbortProbing, SetExternalMode, PauseProbing, + UnloadWafer, ResumeProbing + API Status: published + Returns: + DummyCommonMode:int + RunningMode:str + AccessLevel:str + ExternalMode:int + LicenseDaysLeft:int + MKH:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetStatus") + global GetStatus_Response + if not "GetStatus_Response" in globals(): GetStatus_Response = namedtuple("GetStatus_Response", "DummyCommonMode,RunningMode,AccessLevel,ExternalMode,LicenseDaysLeft,MKH") + return GetStatus_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def LicensingDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Licensing window. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicensingDialog") + + +def GetLicenseInfo(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current license information. + API Status: internal + Returns: + AnnualEnabled:int + AnnualDaysLeft:int + VeloxProEnabled:int + VueTrackEnabled:int + VueTrack4PEnabled:int + ReAlignEnabled:int + AutomationEnabled:int + IdToolsEnabled:int + IVistaEnabled:int + IVistaProEnabled:int + LaserCutterEnabled:int + SiPToolsEnabled:int + AutoRfEnabled:int + SecsGemEnabled:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLicenseInfo") + global GetLicenseInfo_Response + if not "GetLicenseInfo_Response" in globals(): GetLicenseInfo_Response = namedtuple("GetLicenseInfo_Response", "AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled,SecsGemEnabled") + return GetLicenseInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13])) + +def GetProjectFile(): + """ + Returns the current project file. + API Status: published + Returns: + ProjectFilename:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProjectFile") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportSoftwareVersion(): + """ + Returns the Velox software version as string. + API Status: published + Returns: + SoftwareVersion:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReportSoftwareVersion") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OpenProject(ProjectFilename=""): + """ + The OpenProject command opens the specified project. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("OpenProject",ProjectFilename) + + +def IsAppRegistered(Application=""): + """ + Checks the server to see if the application "AppName" is registered with the + server. + API Status: published + Args: + Application:str = "" + Returns: + IsAppRegistered:int + Command Timeout: 5000 + Example:IsAppRegistered WaferMap + """ + rsp = MessageServerInterface.sendSciCommand("IsAppRegistered",Application) + return int(rsp[0]) + +def SaveProject(ProjectFilename=""): + """ + Saves the current data to the project file. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("SaveProject",ProjectFilename) + + +def GetSoftwarePath(PathType=""): + """ + Returns the path for either the applications/data or project files. + API Status: published + Args: + PathType:str = "User" + Returns: + SoftwarePath:str + Command Timeout: 5000 + Example:GetSoftwarePath User + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwarePath",PathType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CCSelectLens(Lens=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. + API Status: internal + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:CCSelectLens 1 + """ + MessageServerInterface.sendSciCommand("CCSelectLens",Lens) + + +def CCReadCurrentLens(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. Probably no longer used. + API Status: internal + Returns: + Lens:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("CCReadCurrentLens") + return int(rsp[0]) + +def CCMoveAuxSite(AuxID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calls the Kernel command MoveAuxSite to move the chuck to the + position of a given AUX site. For the transfer move a safe height is used. If + AUX ID is set to 0, the target of the move is the wafer site. If the flag 'Auto + Align by Spectrum' in ControlCenter-SystemSetup-Aux Sites is True, the Spectrum + command AlignAux is executed after MoveAuxSite to align the site automatically. + The flag is only visible, if the aux site type is CalSubstrate and Spectrum is + installed. AUX ID in the response is the ID of the new active site. + API Status: internal + Args: + AuxID:int = 1 + Command Timeout: 200000 + """ + MessageServerInterface.sendSciCommand("CCMoveAuxSite",AuxID) + + +def ExecuteCleaningSequence(SequenceName="", AllowMediaReuse="", SkipAlignAux="", SkipReturnMove=""): + """ + This command moves to the single cleaning site, executes CleanProbeTip, moves to + the contact verify site, and then moves to contact. Returns an error if the + clean or verify sites aren't defined. + API Status: published + Args: + SequenceName:str = "" + AllowMediaReuse:int = 0 + SkipAlignAux:int = 0 + SkipReturnMove:int = 0 + Command Timeout: 1800000 + Example:ExecuteCleaningSequence "DeepClean" + """ + MessageServerInterface.sendSciCommand("ExecuteCleaningSequence",SequenceName,AllowMediaReuse,SkipAlignAux,SkipReturnMove) + + +def GetAlignmentMode(): + """ + Get the active alignment mode (either on axis or off axis). + API Status: published + Returns: + AlignmentMode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetAlignmentMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetAlignmentMode(AlignmentMode=""): + """ + Sets the active alignment mode (either on axis or off axis). + API Status: published + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetAlignmentMode",AlignmentMode) + + +def GetLoginData(CmdUserName=""): + """ + Gets the Velox user data: name, full name, group, access level. If the + commanded user name is empty, the data of the current user will be responded + API Status: published + Args: + CmdUserName:str = "" + Returns: + UserName:str + LongUserName:str + UserGroup:str + AccessLevel:str + VeloxLocked:int + Command Timeout: 5000 + Example:GetLoginData + """ + rsp = MessageServerInterface.sendSciCommand("GetLoginData",CmdUserName) + global GetLoginData_Response + if not "GetLoginData_Response" in globals(): GetLoginData_Response = namedtuple("GetLoginData_Response", "UserName,LongUserName,UserGroup,AccessLevel,VeloxLocked") + return GetLoginData_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4])) + +def NucleusInitChuck(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to warn user of chuck initialization for Nucleus stations. + Allows user to OK/Cancel. + API Status: internal + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("NucleusInitChuck") + + +def ShutdownVeloxWithSave(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to allow saving project before shutting down Velox. Allows + user to OK/Cancel. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ShutdownVeloxWithSave") + + +def WinCalAutoCal(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCal command to WinCal. + API Status: internal + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCal") + + +def WinCalCheckAutoRFStability(AllowMove=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCheckAutoRFStability command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Returns: + StabilityPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalCheckAutoRFStability",AllowMove) + return int(rsp[0]) + +def WinCalCloseRFStabilityReport(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCloseRFStabilityReport command to WinCal. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalCloseRFStabilityReport") + + +def WinCalMoveToIssRef(IssIdx=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalMoveToIssRef command to WinCal to move to the specified ISS + reference. The ISS index is the IssIdxMap index as returned from + WinCalGetIssListForAuxSite. + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("WinCalMoveToIssRef",IssIdx) + + +def WinCalVerifyIssRefLocAtHome(IssIdx=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalVerifyIssRefLocAtHome command to WinCal and returns AllRefAtHome + as 1 if stage and positioners at home. + API Status: internal + Args: + IssIdx:int = 0 + Returns: + AllRefAtHome:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalVerifyIssRefLocAtHome",IssIdx) + return int(rsp[0]) + +def WinCalGetIssForAuxSite(AuxID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetIssForAuxSite command to WinCal and returns the ISS + information for the given aux site ID. + API Status: internal + Args: + AuxID:int = 0 + Returns: + IssIdx:int + IssPN:str + IssDescription:str + IssEnabled:int + AuxSiteName:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetIssForAuxSite",AuxID) + global WinCalGetIssForAuxSite_Response + if not "WinCalGetIssForAuxSite_Response" in globals(): WinCalGetIssForAuxSite_Response = namedtuple("WinCalGetIssForAuxSite_Response", "IssIdx,IssPN,IssDescription,IssEnabled,AuxSiteName") + return WinCalGetIssForAuxSite_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def WinCalGetNameAndVersion(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetNameAndVersion command to WinCal. + API Status: internal + Returns: + ServerName:str + Version:str + MajorVersion:int + MinorVersion:int + Revision:int + Build:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNameAndVersion") + global WinCalGetNameAndVersion_Response + if not "WinCalGetNameAndVersion_Response" in globals(): WinCalGetNameAndVersion_Response = namedtuple("WinCalGetNameAndVersion_Response", "ServerName,Version,MajorVersion,MinorVersion,Revision,Build") + return WinCalGetNameAndVersion_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def WinCalMonitorNoMove(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMonitorNoMove command to WinCal. Triggers WinCal to measure the + monitor portion of the current calibration setup. + API Status: internal + Returns: + MonitorPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalMonitorNoMove") + return int(rsp[0]) + +def WinCalValidateAdvanced(ProbeSpacing="", ResetTrace="", AllowMove=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidateAdvanced command to WinCal. Performs the validation step of + the currently selected calibration setup. Resets the controller used in WinCal + for validataion. + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + ResetTrace:int = 1 + AllowMove:int = 1 + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidateAdvanced",ProbeSpacing,ResetTrace,AllowMove) + return int(rsp[0]) + +def WinCalMeasureMonitorReference(AllowMove=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMeasureMonitorReference command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalMeasureMonitorReference",AllowMove) + + +def WinCalGetNumValidationPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumValidationPorts command to WinCal. + API Status: internal + Returns: + NumValidationPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumValidationPorts") + return int(rsp[0]) + +def WinCalSetNumValidationPorts(NumValidationPorts=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumValidationPorts command to WinCal. + API Status: internal + Args: + NumValidationPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumValidationPorts",NumValidationPorts) + + +def WinCalGetNumMonitoringPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumMonitoringPorts command to WinCal. + API Status: internal + Returns: + NumMonitoringPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumMonitoringPorts") + return int(rsp[0]) + +def WinCalSetNumMonitoringPorts(NumMonitoringPorts=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumMonitoringPorts command to WinCal. + API Status: internal + Args: + NumMonitoringPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumMonitoringPorts",NumMonitoringPorts) + + +def WinCalGetNumRepeatabilityPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumRepeatabilityPorts command to WinCal. + API Status: internal + Returns: + NumRepeatabilityPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumRepeatabilityPorts") + return int(rsp[0]) + +def WinCalSetNumRepeatabilityPorts(NumRepeatabilityPorts=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumRepeatabilityPorts command to WinCal. + API Status: internal + Args: + NumRepeatabilityPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumRepeatabilityPorts",NumRepeatabilityPorts) + + +def WinCalValidate(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidate command to WinCal. Performs the validation step of the + currently selected calibration setup in WinCal. + API Status: internal + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidate") + return int(rsp[0]) + +def WinCalGetValidationSetup(Port=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends CalGetValidationSetup command to WinCal. Returns calibration setup + parameters. + API Status: internal + Args: + Port:int = 1 + Returns: + StandardType:str + StandardPorts:int + StandardCompareType:int + StructureType:str + PostCorrect:int + PostCorrectMatching:int + AutoConfigure:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetValidationSetup",Port) + global WinCalGetValidationSetup_Response + if not "WinCalGetValidationSetup_Response" in globals(): WinCalGetValidationSetup_Response = namedtuple("WinCalGetValidationSetup_Response", "StandardType,StandardPorts,StandardCompareType,StructureType,PostCorrect,PostCorrectMatching,AutoConfigure") + return WinCalGetValidationSetup_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def WinCalAutoCalNoValidation(ProbeSpacing=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCalNoValidation command to WinCal. Performs an AutoCal + without the validation step + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCalNoValidation",ProbeSpacing) + + +def WinCalHideAllWindows(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalHideAllWindows command to WinCal. This minimizes all the WinCal + windows + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalHideAllWindows") + + +def WinCalGetReferenceStructureInfo(IssIdx=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetReferenceStructureInfo command to WinCal. Given the WinCal ISS + index it will return a string with the reference information + API Status: internal + Args: + IssIdx:int = 0 + Returns: + ReferenceInfo:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetReferenceStructureInfo",IssIdx) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def WinCalSystemSetupHasUnappliedChanges(ShowErrors=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalSystemSetupHasUnappliedChanges command to WinCal. Returns true + if WinCal has unapplied changes + API Status: internal + Args: + ShowErrors:int = 0 + Returns: + HasUnappliedChanges:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalSystemSetupHasUnappliedChanges",ShowErrors) + return int(rsp[0]) + +def WinCalRecordIssRefAtCurrentLoc(IssIdx=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalRecordIssRefAtCurrentLoc command to WinCal. Record the ISS, + indicated by the index, reference as being the current location + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalRecordIssRefAtCurrentLoc",IssIdx) + + +def SaveProjectAsTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Save Project as Template window which saves the project template + if the user clicks ok. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsTemplateDialog") + + +def CreateProjectFromTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the New Project from Template dialog which allows the user to select a + template and create a new project. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CreateProjectFromTemplateDialog") + + +def WinCalGetNumPortsAndProbes(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns Max Ports and Number of probes connected to a port + API Status: internal + Returns: + MaxPorts:int + NumPortsConnectedtoProbes:int + Command Timeout: 1000 + Example:WinCalGetNumPortsAndProbes + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumPortsAndProbes") + global WinCalGetNumPortsAndProbes_Response + if not "WinCalGetNumPortsAndProbes_Response" in globals(): WinCalGetNumPortsAndProbes_Response = namedtuple("WinCalGetNumPortsAndProbes_Response", "MaxPorts,NumPortsConnectedtoProbes") + return WinCalGetNumPortsAndProbes_Response(int(rsp[0]),int(rsp[1])) + +def WinCalGetProbeInfoForPort(VnaPortNum=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the properties from one probe, based on the passed in index. Pass in a + physical VNA port number that is less than or equal to Max Probes from the call + to CalGetNumPortsAndProbes + API Status: internal + Args: + VnaPortNum:int = 1 + Returns: + IsSelected:int + BaseProbe:str + Options:str + PhysicalOrient:str + IsDual:int + IsSymmetric:int + SignalConfig:str + SelectedPitch:int + Command Timeout: 1000 + Example:WinCalGetProbeInfoForPort 1 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetProbeInfoForPort",VnaPortNum) + global WinCalGetProbeInfoForPort_Response + if not "WinCalGetProbeInfoForPort_Response" in globals(): WinCalGetProbeInfoForPort_Response = namedtuple("WinCalGetProbeInfoForPort_Response", "IsSelected,BaseProbe,Options,PhysicalOrient,IsDual,IsSymmetric,SignalConfig,SelectedPitch") + return WinCalGetProbeInfoForPort_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),str(rsp[6]),int(rsp[7])) + +def GetMachineState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current state of the machine. + API Status: internal + Returns: + MachineState:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMachineState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowAboutDialog(Pid=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the help about dialog for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowAboutDialog",Pid) + + +def ShowSplashScreen(Pid="", TimeoutMs=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + TimeoutMs:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowSplashScreen",Pid,TimeoutMs) + + +def CloseSplashScreen(Pid=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseSplashScreen",Pid) + + +def GetLastFourProjects(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the last four project files that were opened. + API Status: internal + Returns: + ProjectFile1:str + ProjectFile2:str + ProjectFile3:str + ProjectFile4:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLastFourProjects") + global GetLastFourProjects_Response + if not "GetLastFourProjects_Response" in globals(): GetLastFourProjects_Response = namedtuple("GetLastFourProjects_Response", "ProjectFile1,ProjectFile2,ProjectFile3,ProjectFile4") + return GetLastFourProjects_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def WinCalExecuteCommand(Command=""): + """ + Sends the WinCalExecuteCommand command to WinCal and returns the response + string. + API Status: published + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalExecuteCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDemoMode(TurnOnDemoMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will return an error if its called with any other parameter as 0. + API Status: internal + Args: + TurnOnDemoMode:int = 1 + Command Timeout: 5000 + Example:SetDemoMode 0 + """ + MessageServerInterface.sendSciCommand("SetDemoMode",TurnOnDemoMode) + + +def ChangeDemoRsp(Param=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Override a command with a demo response. The command will not reach its + destination but the supplied demo response will be returned. An active overide + for a command will be removed if the provided timeout is negative. Format: [ID] + [Time] [ErrorCode]:[Response] - Id: command id in hex withoud leding 0x - Time: + time in ms between command and response, negativ to reset demo mode for this + command - Errorcode: 0 for success, everything else indicates an error - + Response: response string + API Status: internal + Args: + Param:str = "" + Command Timeout: 5000 + Example:ChangeDemoRsp 31 200 0:5000.0 5000.0 8500 + """ + MessageServerInterface.sendSciCommand("ChangeDemoRsp",Param) + + +def GetDemoMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will always return 0. + API Status: internal + Returns: + DemoModeOn:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDemoMode") + return int(rsp[0]) + +def ResetNetworkPort(Param=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + (Re)sets the IP address and listen port of the socket to which the NetworkDriver + tries to connect to (IP address and listen port of Kernel socket). Dummy + implementation for Kernel to support backwards. + API Status: internal + Args: + Param:str = "" + Command Timeout: 10000 + Example:ResetNetworkPort 192.168.3.1 10000 + """ + MessageServerInterface.sendSciCommand("ResetNetworkPort",Param) + + +def GetNDriverClientStatus(ClientNum="", Param=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets status information about the connection NetworkDriver to Kernel. Socket + Error is the Windows socket error, Description the Windows socket error + description. If Socket Error is 0, the description 'Registered' informs that the + Kernel is ready to receive Remote Commands. + API Status: internal + Args: + ClientNum:int = 1 + Param:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:GetNDriverClientStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetNDriverClientStatus",ClientNum,Param) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OverrideCommandTimeout(CmdID="", TimeoutMilliSec=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows specifying a separate command timeout for a single instance + of a command. This is especially useful if the application that receives a + command knows how long a command will take. This command had been added for + SoakTime-handling of StepNextDie. A safe guess for the timeout of StepNextDie is + 5s. + API Status: internal + Args: + CmdID:int = 0 + TimeoutMilliSec:int = 1000 + Command Timeout: 5000 + Example:OverrideCommandTimeout 3234 20000 + """ + MessageServerInterface.sendSciCommand("OverrideCommandTimeout",CmdID,TimeoutMilliSec) + + +def ShutdownVelox(IgnorePID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shutdown all Velox applications in an ordered fashion. When this command returns + success, all non-mandatory apps are closed and the mandatory ones will follow + shortly + API Status: internal + Args: + IgnorePID:int = 0 + Command Timeout: 120000 + Example:ShutdownVelox + """ + MessageServerInterface.sendSciCommand("ShutdownVelox",IgnorePID) + + +def InitializationDone(CommandGroup=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Registration of an application can be delayed. To trigger this behavior, + RegisterProberApp has to be called with flag 3 set (0x04). From + RegisterProberApp to the time this command is sent, the application can send + commands but can't receive commands. This is necessary because some application + have to communicate with others during initialization and can not handle + commands properly during this time. The command group is necessary because of + architectural reasons (By design, the command receiver does not now the sender + of a command). + API Status: internal + Args: + CommandGroup:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("InitializationDone",CommandGroup) + + +def StepFirstZProfilePoint(XPos="", YPos="", NumberOfPoints="", NumberOfEPoints=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command goes to the first Z Profile Point, adjusts Z (in the automatic mode + only) and pauses after it (even in the automatic mode) + API Status: internal + Args: + XPos:Decimal = 0 + YPos:Decimal = 0 + NumberOfPoints:int = 0 + NumberOfEPoints:int = 0 + Command Timeout: 60000 + Example:StepFirstZProfilePoint 10000 20000 5 5 + """ + MessageServerInterface.sendSciCommand("StepFirstZProfilePoint",XPos,YPos,NumberOfPoints,NumberOfEPoints) + + +def StepNextZProfilePoint(Point=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calculates a delta value for the current point and then moves to + the specified point (if it's presented) or to the next one. Note, that in case + of the automatic Z detecting a return ZDelta parameter is a value for the + current point, but in case of the semiautomatic mode the command returns ZDelta + as a value for a previous tested point. If the profiling is finished this + command will return #807 error (End of the profile). Point indices are started + from 1 (1 is first, 2 is second, and so on). + API Status: internal + Args: + Point:int = 0 + Returns: + XPos:Decimal + YPos:Decimal + Delta:Decimal + CurPoint:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 60000 + Example:StepNextZProfilePoint 1 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextZProfilePoint",Point) + global StepNextZProfilePoint_Response + if not "StepNextZProfilePoint_Response" in globals(): StepNextZProfilePoint_Response = namedtuple("StepNextZProfilePoint_Response", "XPos,YPos,Delta,CurPoint,NumberOfPoints,NumberOfEPoints") + return StepNextZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def SetZProfileOptions(ProfileMode="", SepSpeed="", ProfileSensor="", Stage="", SearchSpeed="", Gap="", Units="", ClearElectronics="", ClearRefZ="", Inaccuracy=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets some Z Profile Program Options remotely. + API Status: internal + Args: + ProfileMode:str = "S" + SepSpeed:Decimal = 25 + ProfileSensor:str = "E" + Stage:str = "C" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + Units:str = "Y" + ClearElectronics:int = 1 + ClearRefZ:int = 1 + Inaccuracy:Decimal = 0 + Command Timeout: 10000 + Example:SetZProfileOptions S 25 E C 50 10 Y 1 1 0 + """ + MessageServerInterface.sendSciCommand("SetZProfileOptions",ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy) + + +def GetZProfileOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return predefined settings of the Z Profile Program. + API Status: internal + Returns: + ProfileMode:str + SepSpeed:Decimal + ProfileSensor:str + Stage:str + SearchSpeed:Decimal + Gap:Decimal + Units:str + ClearElectronics:int + ClearRefZ:int + Inaccuracy:Decimal + Command Timeout: 10000 + Example:GetZProfileOptions + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOptions") + global GetZProfileOptions_Response + if not "GetZProfileOptions_Response" in globals(): GetZProfileOptions_Response = namedtuple("GetZProfileOptions_Response", "ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy") + return GetZProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str(rsp[6]),int(rsp[7]),int(rsp[8]),Decimal(rsp[9])) + +def OpenZProfileFile(FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command opens the file inside of the Z Profiling. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 240000 + Example:OpenZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("OpenZProfileFile",FileName) + global OpenZProfileFile_Response + if not "OpenZProfileFile_Response" in globals(): OpenZProfileFile_Response = namedtuple("OpenZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return OpenZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def SaveZProfileFile(FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves the current profile in the specified file. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:SaveZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("SaveZProfileFile",FileName) + global SaveZProfileFile_Response + if not "SaveZProfileFile_Response" in globals(): SaveZProfileFile_Response = namedtuple("SaveZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return SaveZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def ReadZProfile(NewOrigin=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read a profile from the ProberBench Electronics II to the application. Return a + number of available points. + API Status: internal + Args: + NewOrigin:str = "Z" + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:ReadZProfile H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfile",NewOrigin) + return int(rsp[0]) + +def SetZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Uploads the current profile to the ProberBench Electronics II. Returns a number + of written points. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:SetZProfile + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfile") + return int(rsp[0]) + +def CloseZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Z-Profiling application. + API Status: internal + Command Timeout: 5000 + Example:CloseZProfiling + """ + MessageServerInterface.sendSciCommand("CloseZProfiling") + + +def SetZProfileStartPoint(X="", Y="", PosRef="", Units=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets new start point for the profile. All points of the profile will be shifted + accordingly. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + PosRef:str = "Z" + Units:str = "Y" + Command Timeout: 10000 + Example:SetZProfileStartPoint 0 0 H Y + """ + MessageServerInterface.sendSciCommand("SetZProfileStartPoint",X,Y,PosRef,Units) + + +def GetZProfilingStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the profiling process. If this status is true it means the + process is started. + API Status: internal + Returns: + Started:int + Command Timeout: 10000 + Example:GetZProfilingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilingStatus") + return int(rsp[0]) + +def StopZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the profiling process. + API Status: internal + Command Timeout: 10000 + Example:StopZProfiling + """ + MessageServerInterface.sendSciCommand("StopZProfiling") + + +def SetZProfileOrigin(Pos="", X="", Y="", Z=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an origin for the profile. If the origin position is H the command ignores + X and Y parameters. If Z is None the command clears Z value of the origin. + Otherwise it tries to extract a double value from the string and set it. + API Status: internal + Args: + Pos:str = "H" + X:Decimal = 0 + Y:Decimal = 0 + Z:str = "None" + Command Timeout: 10000 + Example:SetZProfileOrigin H 0 0 None + """ + MessageServerInterface.sendSciCommand("SetZProfileOrigin",Pos,X,Y,Z) + + +def GetZProfileOrigin(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current parameters of the profile origin. If the origin Z has no value + the return string for it will be None, otherwise it consists a double value of + the profile Z. + API Status: internal + Returns: + Pos:str + X:Decimal + Y:Decimal + Z:str + Command Timeout: 10000 + Example:GetZProfileOrigin + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOrigin") + global GetZProfileOrigin_Response + if not "GetZProfileOrigin_Response" in globals(): GetZProfileOrigin_Response = namedtuple("GetZProfileOrigin_Response", "Pos,X,Y,Z") + return GetZProfileOrigin_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def StartZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Command Timeout: 10000 + Example:StartZProfiling + """ + MessageServerInterface.sendSciCommand("StartZProfiling") + + +def ZProfileWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 36000000 + Example:ZProfileWafer + """ + rsp = MessageServerInterface.sendSciCommand("ZProfileWafer") + global ZProfileWafer_Response + if not "ZProfileWafer_Response" in globals(): ZProfileWafer_Response = namedtuple("ZProfileWafer_Response", "NumberOfPoints,NumberOfEPoints") + return ZProfileWafer_Response(int(rsp[0]),int(rsp[1])) + +def GetZProfileStartPoint(PosRef="", Units=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current start point of the profile by using given units and a + reference position. + API Status: internal + Args: + PosRef:str = "Z" + Units:str = "Y" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + Example:GetZProfileStartPoint H Y + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileStartPoint",PosRef,Units) + global GetZProfileStartPoint_Response + if not "GetZProfileStartPoint_Response" in globals(): GetZProfileStartPoint_Response = namedtuple("GetZProfileStartPoint_Response", "X,Y") + return GetZProfileStartPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AddZProfilePoint(X="", Y="", After=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Adds new point to the profile at the end (default) or after the given point. + Returns an index of new point and a number of all points in the profile. Point + indices are started from 1. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + After:int = 0 + Returns: + Index:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:AddZProfilePoint 50000 50000 + """ + rsp = MessageServerInterface.sendSciCommand("AddZProfilePoint",X,Y,After) + global AddZProfilePoint_Response + if not "AddZProfilePoint_Response" in globals(): AddZProfilePoint_Response = namedtuple("AddZProfilePoint_Response", "Index,NumberOfPoints,NumberOfEPoints") + return AddZProfilePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def DeleteZProfilePoint(Index=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deletes the point from the profile. Returns a number of all and enabled points + in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:DeleteZProfilePoint 11 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteZProfilePoint",Index) + global DeleteZProfilePoint_Response + if not "DeleteZProfilePoint_Response" in globals(): DeleteZProfilePoint_Response = namedtuple("DeleteZProfilePoint_Response", "NumberOfPoints,NumberOfEPoints") + return DeleteZProfilePoint_Response(int(rsp[0]),int(rsp[1])) + +def SetZProfilePointStatus(Index="", Status=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Status:str = "0" + Command Timeout: 10000 + Example:SetZProfilePointStatus 11 E + """ + MessageServerInterface.sendSciCommand("SetZProfilePointStatus",Index,Status) + + +def GetZProfilePointStatus(Index=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + Status:str + Command Timeout: 10000 + Example:GetZProfilePointStatus 11 + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilePointStatus",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def PreciseZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + All points are covered by triangles, each vertex of the triangle is a point of + the profile. The centers of the triangles are new points of the profile. If all + three vertexes of the triangle are tested points the new point will be marked as + tested also and has Z value equal to average Z of all three vertexes. Otherwise + the new point will be marked as untested. The command returns a number of points + in the profile after the update. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:PreciseZProfile + """ + rsp = MessageServerInterface.sendSciCommand("PreciseZProfile") + return int(rsp[0]) + +def CloseTableView(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the TableView application. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CloseTableView") + + +def StepChuckSite(Site=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Site no. of the chuck table view. + If no Site no is specified the chuck will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSite",Site) + return int(rsp[0]) + +def StepChuckSubsite(Site=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Subsite no. of the chuck subsite + table view. If no Subsite no. is specified the chuck will step automatically to + the next logical site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSubsite",Site) + return int(rsp[0]) + +def StepScopeSite(Site=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the microscope stage to the requested Site no. of the scope table view. If + no Site no is specified the scope will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepScopeSite",Site) + return int(rsp[0]) + +def StepProbeSite(Probe="", Site=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the specified probe to the requested Site no. of the Probe no table view. + If no Site no. is specified the Probe no. will step automatically to the next + logical site location. The first site in the table is site 1. + API Status: internal + Args: + Probe:int = -1 + Site:int = -1 + Returns: + ProbeRet:int + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepProbeSite",Probe,Site) + global StepProbeSite_Response + if not "StepProbeSite_Response" in globals(): StepProbeSite_Response = namedtuple("StepProbeSite_Response", "ProbeRet,SiteRet") + return StepProbeSite_Response(int(rsp[0]),int(rsp[1])) + +def ReadChuckSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual chuck site position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSitePosition") + global ReadChuckSitePosition_Response + if not "ReadChuckSitePosition_Response" in globals(): ReadChuckSitePosition_Response = namedtuple("ReadChuckSitePosition_Response", "Site,X,Y") + return ReadChuckSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSitePosition") + global ReadScopeSitePosition_Response + if not "ReadScopeSitePosition_Response" in globals(): ReadScopeSitePosition_Response = namedtuple("ReadScopeSitePosition_Response", "Site,X,Y") + return ReadScopeSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadProbeSitePosition(Probe=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Args: + Probe:int = -1 + Returns: + ProbeRet:int + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSitePosition",Probe) + global ReadProbeSitePosition_Response + if not "ReadProbeSitePosition_Response" in globals(): ReadProbeSitePosition_Response = namedtuple("ReadProbeSitePosition_Response", "ProbeRet,Site,X,Y") + return ReadProbeSitePosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadChuckSubsitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the chuck subsite position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSubsitePosition") + global ReadChuckSubsitePosition_Response + if not "ReadChuckSubsitePosition_Response" in globals(): ReadChuckSubsitePosition_Response = namedtuple("ReadChuckSubsitePosition_Response", "Site,X,Y") + return ReadChuckSubsitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def StepFirstDie(ClearBins="", RecalcRoute=""): + """ + Steps the chuck to the first die of the wafer map. Returns the row and column + number of the actual die location after the move is completed. If ClearBins is + 1, all binning data will be cleared from dies. If yes the route will be + recalculated. All dies marked to skip during the last test (marked to skip with + SetDieStatus) will be eliminated from the route. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + DieX:int + DieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstDie",ClearBins,RecalcRoute) + global StepFirstDie_Response + if not "StepFirstDie_Response" in globals(): StepFirstDie_Response = namedtuple("StepFirstDie_Response", "DieX,DieY,CurSite,LastSiteIndex") + return StepFirstDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def StepNextDie(CDieX="", CDieY="", Site=""): + """ + Steps the chuck to the specified x,y die location of the wafer map. If no + command data is passed, the chuck automatically steps to the next logical wafer + map die location. Returns the row and column number of the actual die location + after the move is completed. In addition, the SubDie location, and total number + of SubDies is also returned. If Site (i.e. SubDie) is -1, the chuck will move + to SubDie 0, on the next die; in this case, the first 2 parameters are ignored. + If sent without parameters, it will literally 'step to the next die'. When using + this command from shared code, use SendWithoutParameter(). + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDie",CDieX,CDieY,Site) + global StepNextDie_Response + if not "StepNextDie_Response" in globals(): StepNextDie_Response = namedtuple("StepNextDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepNextDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinMapDie(Bin="", CDieX="", CDieY=""): + """ + Assigns the bin information to the wafer map at the current die, unless a row + and column is specified. Inks the device if the real time inking option (of the + wafer map) is enabled. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 30000 + Example:BinMapDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinMapDie",Bin,CDieX,CDieY) + global BinMapDie_Response + if not "BinMapDie_Response" in globals(): BinMapDie_Response = namedtuple("BinMapDie_Response", "RDieX,RDieY") + return BinMapDie_Response(int(rsp[0]),int(rsp[1])) + +def AssignMapBins(Bins=""): + """ + Assigns the pass or fail information to the actual bin value. Redundant to + SetBinCode. + API Status: published + Args: + Bins:str = "" + Command Timeout: 10000 + Example:AssignMapBins PFFFFFF + """ + MessageServerInterface.sendSciCommand("AssignMapBins",Bins) + + +def StepFailedBack(): + """ + Steps the chuck back the number of consecutive failed dies (goes back to the + last known good die) and returns the number of consecutive failed dies. + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedBack") + return int(rsp[0]) + +def StepFailedForward(): + """ + Steps the chuck forward the number of consecutive failed dies (goes to next + untested die). + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedForward") + return int(rsp[0]) + +def ReadMapPosition(Pos="", FromPos=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 1-based, + the first value is 1, not 0. M_pnCurSite returns the currently selected + Subdie (1-based) or 0 if no Subdie is currently selected. This command (i.e. + ReadMapPosition) has been included for legacy support. ReadMapPosition2 is + the preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition",Pos,FromPos) + global ReadMapPosition_Response + if not "ReadMapPosition_Response" in globals(): ReadMapPosition_Response = namedtuple("ReadMapPosition_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadMapYield(): + """ + Returns the actual wafer map yield data information. + API Status: published + Returns: + TotalDies:int + TestedDies:int + Passed:int + Failed:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapYield") + global ReadMapYield_Response + if not "ReadMapYield_Response" in globals(): ReadMapYield_Response = namedtuple("ReadMapYield_Response", "TotalDies,TestedDies,Passed,Failed") + return ReadMapYield_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinStepDie(Bin="", CDieX="", CDieY="", Site=""): + """ + Bins the current die and steps the chuck to the next selected die location of + the wafer map (default) or steps to the specified Column and Row position, if + these values are passed. In contrast to StepNextDie, the BinStepDie command + will only step from die to die while staying on the current subdie. It will not + step through the subdies so it cannot be used for subdie stepping. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + Example:BinStepDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinStepDie",Bin,CDieX,CDieY,Site) + global BinStepDie_Response + if not "BinStepDie_Response" in globals(): BinStepDie_Response = namedtuple("BinStepDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinStepDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetMapHome(DieX="", DieY=""): + """ + If the command has no parameters it sets the current position as home position + both for the wafer map and for the chuck. Otherwise, it changes the wafer map + home position using the given die coordinates. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapHome",DieX,DieY) + + +def SaveMapFile(FileName="", FileType=""): + """ + Saves current map file with specified name. + API Status: published + Args: + FileName:str = "" + FileType:str = "m" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SaveMapFile",FileName,FileType) + + +def SetWaferMapMode(Mode=""): + """ + Enables or disables an external mode for the application. In the external mode, + all controls are disabled. The application handles all its remote commands in + both modes. Special interactive modes can also be turned on. + API Status: published + Args: + Mode:str = "" + Returns: + ModeType:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("SetWaferMapMode",Mode) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetWaferMapMode(ModeType=""): + """ + Returns whether the application is in external mode or not. + API Status: published + Args: + ModeType:str = "" + Returns: + Mode:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapMode",ModeType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferNum(Number=""): + """ + Specifies the wafer number. + API Status: published + Args: + Number:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferNum",Number) + + +def GetWaferNum(): + """ + Returns the wafer number for the current wafer. + API Status: published + Returns: + Number:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferNum") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferID(ID=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferID",ID) + + +def GetWaferID(): + """ + Returns the wafer ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetProductID(ID=""): + """ + Specifies the product ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetProductID",ID) + + +def GetProductID(): + """ + Displays the product ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProductID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DoInkerRun(): + """ + Instructs the WaferMap to perform an ink run on the current wafer. Returns the + number of dies which were inked during the inker run. + API Status: published + Returns: + InkedDies:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("DoInkerRun") + return int(rsp[0]) + +def CloseWaferMap(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Wafer Map application. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseWaferMap") + + +def GetNumSelectedDies(): + """ + Gets the number of dies in the map which are selected for probing. + API Status: published + Returns: + SelectedDies:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedDies") + return int(rsp[0]) + +def GetSelectedDieCoords(Die=""): + """ + Given the index of a selected die in the range [1..NumSelectedDies], returns the + column and row indices for the selected die. + API Status: published + Args: + Die:int = 0 + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedDieCoords",Die) + global GetSelectedDieCoords_Response + if not "GetSelectedDieCoords_Response" in globals(): GetSelectedDieCoords_Response = namedtuple("GetSelectedDieCoords_Response", "DieX,DieY") + return GetSelectedDieCoords_Response(int(rsp[0]),int(rsp[1])) + +def StepNextDieOffset(XOffset="", YOffset="", CDieX="", CDieY=""): + """ + Moves to a user-specified offset within a die. The optional col row params can + be used to specify the die. If they are omitted, WaferMap moves to the specified + offset within the next selected die. + API Status: published + Args: + XOffset:Decimal = 0 + YOffset:Decimal = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDieOffset",XOffset,YOffset,CDieX,CDieY) + global StepNextDieOffset_Response + if not "StepNextDieOffset_Response" in globals(): StepNextDieOffset_Response = namedtuple("StepNextDieOffset_Response", "RDieX,RDieY") + return StepNextDieOffset_Response(int(rsp[0]),int(rsp[1])) + +def ReadMapPosition2(Pos="", FromPos=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 0-based, + the first value is 0, not 1. M_pnCurSite returns the currently selected Subdie + (0-based) or -1 if no Subdie is currently selected. This command is the + preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition2",Pos,FromPos) + global ReadMapPosition2_Response + if not "ReadMapPosition2_Response" in globals(): ReadMapPosition2_Response = namedtuple("ReadMapPosition2_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition2_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def DeleteSubDie2(Site=""): + """ + Deletes selected subdie. The SubDie collection is 0-based, the first value is 0, + not 1. This command is the preferred method for deleting a selected + subdie. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie2",Site) + return int(rsp[0]) + +def DeleteAllSubDie(): + """ + Deletes all subdies for all dies. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("DeleteAllSubDie") + + +def GetDieLabel(DieX="", DieY=""): + """ + Returns a label from the wafer map at the current die, unless a row and column + are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabel",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabel(Label="", DieX="", DieY=""): + """ + Assigns a label to the wafer map at the current die, unless a row and column are + specified. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabel",Label,DieX,DieY) + + +def StepNextSubDie(Site=""): + """ + Steps the chuck to the specified SubDie number relative to the current die + origin of the wafer map. Returns the SubDie number of the actual die location + after the move is completed and the total number of subdies. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextSubDie",Site) + global StepNextSubDie_Response + if not "StepNextSubDie_Response" in globals(): StepNextSubDie_Response = namedtuple("StepNextSubDie_Response", "CurSite,LastSiteIndex") + return StepNextSubDie_Response(int(rsp[0]),int(rsp[1])) + +def OpenWaferMap(FileName=""): + """ + Opens a Wafer Map file. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenWaferMap",FileName) + + +def SetDieResult(Result="", DieX="", DieY=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResult",Result,DieX,DieY) + + +def GetDieResult(DieX="", DieY=""): + """ + Returns a measurement result from the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResult",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResult(Result="", DieX="", DieY="", Site=""): + """ + Assigns a measurement result to the wafer die map at the current die and the + current subdie, unless a subdie, row, and column are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResult",Result,DieX,DieY,Site) + + +def GetDieMapResult(DieX="", DieY="", Site=""): + """ + Returns a measurement result from the wafer map at the current die and current + subdie, unless a row, column, and subdie are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResult",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BinSubDie(Bin="", CDieX="", CDieY="", Site=""): + """ + Assigns the bin information for the current subdie in the current die, unless a + subdie, row, and column are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("BinSubDie",Bin,CDieX,CDieY,Site) + global BinSubDie_Response + if not "BinSubDie_Response" in globals(): BinSubDie_Response = namedtuple("BinSubDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinSubDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetSubDieData(Site="", X="", Y="", Label=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + Site:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieData",Site,X,Y,Label) + + +def GetSubDieData(Site=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + X:Decimal + Y:Decimal + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieData",Site) + global GetSubDieData_Response + if not "GetSubDieData_Response" in globals(): GetSubDieData_Response = namedtuple("GetSubDieData_Response", "CurSite,X,Y,Label") + return GetSubDieData_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def GetMapHome(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the home die location of the WaferMap. + API Status: internal + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapHome") + global GetMapHome_Response + if not "GetMapHome_Response" in globals(): GetMapHome_Response = namedtuple("GetMapHome_Response", "DieX,DieY") + return GetMapHome_Response(int(rsp[0]),int(rsp[1])) + +def GetMapDims(): + """ + Returns the parameters for the current wafer. + API Status: published + Returns: + MapType:str + XIndex:Decimal + YIndex:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapDims") + global GetMapDims_Response + if not "GetMapDims_Response" in globals(): GetMapDims_Response = namedtuple("GetMapDims_Response", "MapType,XIndex,YIndex,Columns,Rows") + return GetMapDims_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetWaferMapParams(Diameter="", DieWidth="", DieHeight="", FlatLength="", FlatAngle="", XOffset="", YOffset="", EdgeArea=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are percentages. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def SetRectMapParams(DieWidth="", DieHeight="", Columns="", Rows=""): + """ + Creates the rectangle wafer with specified parameters. + API Status: published + Args: + DieWidth:Decimal = 0 + DieHeight:Decimal = 0 + Columns:int = 0 + Rows:int = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetRectMapParams",DieWidth,DieHeight,Columns,Rows) + + +def StepToDie(DieNumber="", Site=""): + """ + Steps the chuck to the die location specified by the die number of the wafer + map. If no command data is passed, the chuck automatically steps to the next + logical wafer map die location. Returns the row and column number of the actual + die location after the move is completed. In addition, the SubDie location, and + total number of SubDies is also returned. + API Status: published + Args: + DieNumber:int = -1 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepToDie",DieNumber,Site) + global StepToDie_Response + if not "StepToDie_Response" in globals(): StepToDie_Response = namedtuple("StepToDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepToDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetMapOrientation(UseOrientationCornerForShift=""): + """ + Returns parameters of the map coordinate system. + API Status: published + Args: + UseOrientationCornerForShift:int = 0 + Returns: + Orientation:int + OriginShiftX:int + OriginShiftY:int + UseAlphas:int + UseIOs:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapOrientation",UseOrientationCornerForShift) + global GetMapOrientation_Response + if not "GetMapOrientation_Response" in globals(): GetMapOrientation_Response = namedtuple("GetMapOrientation_Response", "Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs") + return GetMapOrientation_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetMapOrientation(Orientation="", OriginShiftX="", OriginShiftY="", UseAlphas="", UseIOs="", UseOrientationCornerForShift=""): + """ + Sets up new map origin and new coordinate system after that. + API Status: published + Args: + Orientation:int = 0 + OriginShiftX:int = 0 + OriginShiftY:int = 0 + UseAlphas:int = 0 + UseIOs:int = 1 + UseOrientationCornerForShift:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapOrientation",Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs,UseOrientationCornerForShift) + + +def SetDieStatus(DieX="", DieY="", Status=""): + """ + Sets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieStatus",DieX,DieY,Status) + + +def GetDieStatus(DieX="", DieY=""): + """ + Gets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieStatus",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieStatus(Site="", Status=""): + """ + Sets the SubDie status. The SubDie collection is 0-based, the first value is 0, + not 1. + API Status: published + Args: + Site:int = 0 + Status:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieStatus",Site,Status) + + +def GetSubDieStatus(Site=""): + """ + Returns the SubDie status. The SubDie collection is 0-based, the first value is + 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieStatus",Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetBinCode(Bin=""): + """ + Returns the Die size from the current map. + API Status: published + Args: + Bin:int = 0 + Returns: + Chars:str + Color:int + Status:str + Inker1:int + Inker2:int + Inker3:int + Inker4:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinCode",Bin) + global GetBinCode_Response + if not "GetBinCode_Response" in globals(): GetBinCode_Response = namedtuple("GetBinCode_Response", "Chars,Color,Status,Inker1,Inker2,Inker3,Inker4") + return GetBinCode_Response(str(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetBinCode(Bin="", Chars="", Color="", Status="", Inker1="", Inker2="", Inker3="", Inker4=""): + """ + Appends the Bin information to a bin code. + API Status: published + Args: + Bin:int = 0 + Chars:str = "" + Color:int = 0 + Status:str = "" + Inker1:int = 0 + Inker2:int = 0 + Inker3:int = 0 + Inker4:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinCode",Bin,Chars,Color,Status,Inker1,Inker2,Inker3,Inker4) + + +def GetDieDataAsNum(CDieIndex=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Number is absent it uses the current die + on the wafer. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsNum",CDieIndex) + global GetDieDataAsNum_Response + if not "GetDieDataAsNum_Response" in globals(): GetDieDataAsNum_Response = namedtuple("GetDieDataAsNum_Response", "RDieIndex,DieX,DieY,Bin,Result") + return GetDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsNum(DieIndex="", Bin="", Result=""): + """ + Sets the Die Information. If the Die Number is invalid it returns an error. + API Status: published + Args: + DieIndex:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsNum",DieIndex,Bin,Result) + + +def GetSubDieDataAsNum(CDieIndex="", Site=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsNum",CDieIndex,Site) + global GetSubDieDataAsNum_Response + if not "GetSubDieDataAsNum_Response" in globals(): GetSubDieDataAsNum_Response = namedtuple("GetSubDieDataAsNum_Response", "RDieIndex,DieX,DieY,CurSite,Bin,Result") + return GetSubDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsNum(DieIndex="", Site="", Bin="", Result=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieIndex:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsNum",DieIndex,Site,Bin,Result) + + +def GetDieDataAsColRow(CDieX="", CDieY=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Column and Row are absent it uses the + current die on the wafer. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsColRow",CDieX,CDieY) + global GetDieDataAsColRow_Response + if not "GetDieDataAsColRow_Response" in globals(): GetDieDataAsColRow_Response = namedtuple("GetDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,Bin,Result") + return GetDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsColRow(DieX="", DieY="", Bin="", Result=""): + """ + Sets the Data in the Row Column format. If the Die is invalid it returns an + error. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsColRow",DieX,DieY,Bin,Result) + + +def GetSubDieDataAsColRow(CDieX="", CDieY="", Site=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsColRow",CDieX,CDieY,Site) + global GetSubDieDataAsColRow_Response + if not "GetSubDieDataAsColRow_Response" in globals(): GetSubDieDataAsColRow_Response = namedtuple("GetSubDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,CurSite,Bin,Result") + return GetSubDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsColRow(DieX="", DieY="", Site="", Bin="", Result=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsColRow",DieX,DieY,Site,Bin,Result) + + +def SelectAllDiesForProbing(DoSelectAll="", DoEdgeDies=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables all dies. + API Status: internal + Args: + DoSelectAll:int = 0 + DoEdgeDies:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SelectAllDiesForProbing",DoSelectAll,DoEdgeDies) + + +def GetMapName(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current WaferMap Filename. + API Status: internal + Returns: + Name:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapName") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetLotID(ID=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetLotID",ID) + + +def GetLotID(): + """ + Returns the Lot ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLotID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StepFirstCluster(ClearBins="", RecalcRoute=""): + """ + Steps the chuck to the first die cluster of the cluster map. If clusters are not + defined, the first Die is used. Returns the row and column information of the + actual cluster and die location after the move is completed. Switches to remote + control if the "Disable Velox" flag is set in the external options window. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstCluster",ClearBins,RecalcRoute) + global StepFirstCluster_Response + if not "StepFirstCluster_Response" in globals(): StepFirstCluster_Response = namedtuple("StepFirstCluster_Response", "ClusterX,ClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepFirstCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def StepNextCluster(CClusterX="", CClusterY=""): + """ + Steps the chuck to the specified x,y cluster die location of the cluster map. If + no command data is passed, the chuck automatically steps to the next logical + cluster map location. If clusters are not defined, the Die information is used. + Returns the row and column number of the actual die location after the move is + completed. + API Status: published + Args: + CClusterX:int = 0 + CClusterY:int = 0 + Returns: + RClusterX:int + RClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextCluster",CClusterX,CClusterY) + global StepNextCluster_Response + if not "StepNextCluster_Response" in globals(): StepNextCluster_Response = namedtuple("StepNextCluster_Response", "RClusterX,RClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepNextCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetMapRoute(MoveMode="", StartColumn="", StartRow="", MoveParam=""): + """ + Specifies the Move Path for the probe station inside the Wafer Map. Optimization + is done for the shortest move way for the station. + API Status: published + Args: + MoveMode:str = "B" + StartColumn:str = "L" + StartRow:str = "T" + MoveParam:str = "H" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapRoute",MoveMode,StartColumn,StartRow,MoveParam) + + +def GetMapRoute(): + """ + Returns the specified move path for the probe station inside the Wafer Map. + API Status: published + Returns: + MoveMode:str + StartColumn:str + StartRow:str + MoveParam:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapRoute") + global GetMapRoute_Response + if not "GetMapRoute_Response" in globals(): GetMapRoute_Response = namedtuple("GetMapRoute_Response", "MoveMode,StartColumn,StartRow,MoveParam") + return GetMapRoute_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetClusterParams(UseClusters="", ClusterWidth="", ClusterHeight="", TestIncomplete=""): + """ + Specifies the clusters parameters. + API Status: published + Args: + UseClusters:int = 0 + ClusterWidth:int = 1 + ClusterHeight:int = 1 + TestIncomplete:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterParams",UseClusters,ClusterWidth,ClusterHeight,TestIncomplete) + + +def GetClusterParams(): + """ + Returns current clusters parameters. + API Status: published + Returns: + UseClusters:int + ClusterWidth:int + ClusterHeight:int + TestIncomplete:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterParams") + global GetClusterParams_Response + if not "GetClusterParams_Response" in globals(): GetClusterParams_Response = namedtuple("GetClusterParams_Response", "UseClusters,ClusterWidth,ClusterHeight,TestIncomplete") + return GetClusterParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def NewWaferMap(): + """ + Deletes current wafer map, sub dies and binning information; then creates new + wafer map with defaults parameters. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("NewWaferMap") + + +def AddSubDie(X="", Y="", Label=""): + """ + Adds new subdie at the end of the table. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("AddSubDie",X,Y,Label) + return int(rsp[0]) + +def DeleteSubDie(Site=""): + """ + Deletes selected subdie. The SubDie collection is 1-based, the first value is 1, + not 0. If 0 is passed in as the subdie index, WaferMap will delete all subdies + for all dies.This command (i.e. DeleteSubDie) has been included for legacy + support. DeleteSubDie2 is the preferred method for deleting a selected + subdie. DeleteAllSubDie is the preferred method for deleting all subdies for all + dies. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie",Site) + return int(rsp[0]) + +def GetNumSelectedClusters(): + """ + Gets the number of clusters in the map which are selected for probing. + API Status: published + Returns: + SelectedClusters:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedClusters") + return int(rsp[0]) + +def GetSelectedClusterCoords(ClusterIndex=""): + """ + Given the index of a selected cluster in the range [1..NumSelectedClusters], + returns the column and row indices for the selected cluster. + API Status: published + Args: + ClusterIndex:int = 0 + Returns: + ClusterX:int + ClusterY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedClusterCoords",ClusterIndex) + global GetSelectedClusterCoords_Response + if not "GetSelectedClusterCoords_Response" in globals(): GetSelectedClusterCoords_Response = namedtuple("GetSelectedClusterCoords_Response", "ClusterX,ClusterY") + return GetSelectedClusterCoords_Response(int(rsp[0]),int(rsp[1])) + +def GetClusterDieStatus(ClusterX="", ClusterY="", DieX="", DieY=""): + """ + Gets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterDieStatus",ClusterX,ClusterY,DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetClusterDieStatus(ClusterX="", ClusterY="", DieX="", DieY="", Status=""): + """ + Sets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterDieStatus",ClusterX,ClusterY,DieX,DieY,Status) + + +def OpenBinCodeTable(FileName=""): + """ + Opens a Bin Code Table file (.bct) with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenBinCodeTable",FileName) + + +def SaveBinCodeTable(FileName=""): + """ + Saves bin code table to a file with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SaveBinCodeTable",FileName) + + +def SetBinTableSize(BinsSize=""): + """ + Sets size of the bin code table. This is the size of bins used in statistics and + binning. + API Status: published + Args: + BinsSize:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinTableSize",BinsSize) + + +def GetBinTableSize(): + """ + Gets size of the bin code table. + API Status: published + Returns: + BinsSize:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinTableSize") + return int(rsp[0]) + +def StepFailedClusterBack(): + """ + Steps the chuck the consecutive failed clusters back (goes back to the last + known good cluster) and returns the number of consecutive failed clusters. + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterBack") + return int(rsp[0]) + +def StepFailedClusterForward(): + """ + Steps the chuck the consecutive failed clusters forward and returns the number + of consecutive failed clusters (goes to next untested cluster). + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterForward") + return int(rsp[0]) + +def GoToWaferHome(): + """ + Moves the chuck to the wafer home position. + API Status: published + Command Timeout: 6000000 + """ + MessageServerInterface.sendSciCommand("GoToWaferHome") + + +def GetWaferInfo(): + """ + Returns a number of all units marked to test. Note that TestSites is a number of + all sites for all dies. + API Status: published + Returns: + ClustersCount:int + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferInfo") + global GetWaferInfo_Response + if not "GetWaferInfo_Response" in globals(): GetWaferInfo_Response = namedtuple("GetWaferInfo_Response", "ClustersCount,DiesCount,SitesCount") + return GetWaferInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetClusterInfo(Cluster=""): + """ + Returns a number of all dies and sites marked to test in the given cluster. + API Status: published + Args: + Cluster:int = 0 + Returns: + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterInfo",Cluster) + global GetClusterInfo_Response + if not "GetClusterInfo_Response" in globals(): GetClusterInfo_Response = namedtuple("GetClusterInfo_Response", "DiesCount,SitesCount") + return GetClusterInfo_Response(int(rsp[0]),int(rsp[1])) + +def GetDieInfo(Die=""): + """ + Returns a number of sites marked to test in the given die. + API Status: published + Args: + Die:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieInfo",Die) + return int(rsp[0]) + +def ConvertToAlphas(Start="", Finish=""): + """ + Returns a string of the alpha column coordinates for the given range divided by + spaces. + API Status: published + Args: + Start:int = 0 + Finish:int = 0 + Returns: + Alphas:str + Command Timeout: 240000 + """ + rsp = MessageServerInterface.sendSciCommand("ConvertToAlphas",Start,Finish) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetActiveLayer(Layer=""): + """ + Sets new active layer. + API Status: published + Args: + Layer:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetActiveLayer",Layer) + + +def GetActiveLayer(): + """ + Returns current active layer. + API Status: published + Returns: + Layer:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetActiveLayer") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieRefPoint(RefX="", RefY=""): + """ + Sets a new reference point for the die. This point is NOT used for die stepping, + nor for subdie stepping. When using the "Chuck Position from Reference" WaferMap + GUI setting, the Die Reference Point can be set to be more representative of the + actual reference location within the die. A setting of (0.0, 0.0) is defined as + the upper left corner of the die. All subdie coordinates are relative to upper + left corner of the die. + API Status: published + Args: + RefX:Decimal = 0 + RefY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieRefPoint",RefX,RefY) + + +def GetDieRefPoint(): + """ + Returns current reference point for the die. For details see SetDieRefPoint + command. + API Status: published + Returns: + RefX:Decimal + RefY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieRefPoint") + global GetDieRefPoint_Response + if not "GetDieRefPoint_Response" in globals(): GetDieRefPoint_Response = namedtuple("GetDieRefPoint_Response", "RefX,RefY") + return GetDieRefPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ClearAllBins(): + """ + Clears all binning data in the wafer map. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ClearAllBins") + + +def SetWindowState(State="", Window=""): + """ + Has sense in the application only (not for ActiveX controls). It shows or hides + a window. All parameters are case-insensitive. + API Status: published + Args: + State:str = "s" + Window:str = "setup" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWindowState",State,Window) + + +def SetCurrentBin(Bin="", ButtonStatus=""): + """ + Sets the current bin for the application. Second parameter allows to enable or + disable "Mark with Bin" mode in the application. + API Status: published + Args: + Bin:int = 0 + ButtonStatus:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetCurrentBin",Bin,ButtonStatus) + + +def GetCurrentBin(): + """ + Returns the current bin in the application. + API Status: published + Returns: + Bin:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetCurrentBin") + return int(rsp[0]) + +def ReadClusterPosition(Pos="", FromPos=""): + """ + Returns the actual wafer map cluster position. If the cluster probing is + disabled, the command will assume a cluster of size 1x1. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + DieX:int + DieY:int + DieIndex:int + ClusterWidth:int + ClusterHeight:int + EnabledDies:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadClusterPosition",Pos,FromPos) + global ReadClusterPosition_Response + if not "ReadClusterPosition_Response" in globals(): ReadClusterPosition_Response = namedtuple("ReadClusterPosition_Response", "ClusterX,ClusterY,ClusterIndex,DieX,DieY,DieIndex,ClusterWidth,ClusterHeight,EnabledDies") + return ReadClusterPosition_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str("" if len(rsp) < 9 else ' '.join(rsp[8:]))) + +def GetWaferMapParams(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are percentages. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams") + global GetWaferMapParams_Response + if not "GetWaferMapParams_Response" in globals(): GetWaferMapParams_Response = namedtuple("GetWaferMapParams_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def GetRectMapParams(): + """ + Creates a rectangular wafermap with specified parameters. + API Status: published + Returns: + DieWidth:Decimal + DieHeight:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetRectMapParams") + global GetRectMapParams_Response + if not "GetRectMapParams_Response" in globals(): GetRectMapParams_Response = namedtuple("GetRectMapParams_Response", "DieWidth,DieHeight,Columns,Rows") + return GetRectMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SyncMapHome(X="", Y=""): + """ + Tries to find an appropriate position in the wafer for the current chuck + position. X and Y describe the chuck position of the wafer center relatively to + the chuck zero position. If the wafer position is found the command sets it as + the wafer map home position and sets the current chuck position as the chuck + home position. If there is no corresponding wafer position the command returns + error 701. Command is used by AutoAlign for the BuildMap feature. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SyncMapHome",X,Y) + + +def SetWaferProfileOptions(ProfileSensor="", SearchSpeed="", Gap="", SuccessRatio="", ProfDistX="", ProfDistY=""): + """ + Sets some WaferMap profiling options remotely. + API Status: published + Args: + ProfileSensor:str = "e" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + SuccessRatio:Decimal = 75 + ProfDistX:Decimal = 0 + ProfDistY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferProfileOptions",ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY) + + +def GetWaferProfileOptions(): + """ + Returns predefined settings of the WaferMap profiling options. + API Status: published + Returns: + ProfileSensor:str + SearchSpeed:Decimal + Gap:Decimal + SuccessRatio:Decimal + ProfDistX:Decimal + ProfDistY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfileOptions") + global GetWaferProfileOptions_Response + if not "GetWaferProfileOptions_Response" in globals(): GetWaferProfileOptions_Response = namedtuple("GetWaferProfileOptions_Response", "ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY") + return GetWaferProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def StartWaferProfiling(DoContinue=""): + """ + Starts the profiling process. To determine the current profiling state, use + GetWaferProfilingStatus command. + API Status: published + Args: + DoContinue:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StartWaferProfiling",DoContinue) + + +def GetWaferProfilingStatus(): + """ + Returns status of the profiling process. If this status is true, the process is + started. + API Status: published + Returns: + Started:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfilingStatus") + return int(rsp[0]) + +def StopWaferProfiling(): + """ + Stops the profiling process. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StopWaferProfiling") + + +def DoWaferProfiling(): + """ + Profiles the wafer and returns a status of the profiling as an error code. + API Status: published + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfiling") + + +def DoWaferProfilingOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Profiles the wafer and returns a status of the profiling as an error code. + Executes profiling using the off axis camera + API Status: internal + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfilingOffAxis") + + +def GetSubDieLabel(DieX="", DieY="", Site=""): + """ + Returns a label from the wafer map at the current die and current subdie, unless + a row, column, and subdie are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabel",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabel(Label="", DieX="", DieY="", Site=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, row, and column are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabel",Label,DieX,DieY,Site) + + +def GetSubDieLabelAsNum(CDieIndex="", Site=""): + """ + Returns a label from the wafer map the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabelAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabelAsNum(Label="", CDieIndex="", Site=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabelAsNum",Label,CDieIndex,Site) + + +def GetDieLabelAsNum(CDieIndex=""): + """ + Returns a label from the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabelAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabelAsNum(Label="", CDieIndex=""): + """ + Assigns a label to the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabelAsNum",Label,CDieIndex) + + +def GetHomeDieOffset(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the XY offset from the reference position of the Home Die to wafer + center in chuck coordinates. + API Status: internal + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetHomeDieOffset") + global GetHomeDieOffset_Response + if not "GetHomeDieOffset_Response" in globals(): GetHomeDieOffset_Response = namedtuple("GetHomeDieOffset_Response", "X,Y") + return GetHomeDieOffset_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetWaferMapParams2(Diameter="", DieWidth="", DieHeight="", FlatLength="", FlatAngle="", XOffset="", YOffset="", EdgeArea=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are microns. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams2",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def GetWaferMapParams2(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are microns. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams2") + global GetWaferMapParams2_Response + if not "GetWaferMapParams2_Response" in globals(): GetWaferMapParams2_Response = namedtuple("GetWaferMapParams2_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams2_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def SetWaferTestAngle(Angle=""): + """ + This command sets the Wafer Test Angle. This is different from the notch angle + and allows rotating the WaferMap. + API Status: published + Args: + Angle:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferTestAngle",Angle) + + +def GetWaferTestAngle(): + """ + This returns the Wafer Test Angle. This is different from the notch angle and + allows rotating the WaferMap. + API Status: published + Returns: + Angle:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferTestAngle") + return int(rsp[0]) + +def LoadPreMappedDiesTable(FileName="", ClearMap=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads the Pre-Mapped Dies Table file with specified name. + API Status: internal + Args: + FileName:str = "" + ClearMap:int = 1 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("LoadPreMappedDiesTable",FileName,ClearMap) + + +def GetPreMappedDieInfo(DieX="", DieY=""): + """ + This command is valid when a PreMapped Dies Table has been loaded. Returns + values at the current die, unless a column (M_pnDieX) and row (M_pnDieY) are + specified. Returns actual (as measured during the Pre-Mapping) x, y, z, and + theta die positions. Also returns whether or not Z and Theta are being used. + This command is only valid when a Pre-Mapped Dies Table has been loaded. If a + PreMapped Dies Table has NOT been loaded, ERR_IllegalParameters (715) is + returned. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + UseZ:int + UseTheta:int + ActualX:Decimal + ActualY:Decimal + ActualZ:Decimal + Theta:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPreMappedDieInfo",DieX,DieY) + global GetPreMappedDieInfo_Response + if not "GetPreMappedDieInfo_Response" in globals(): GetPreMappedDieInfo_Response = namedtuple("GetPreMappedDieInfo_Response", "UseZ,UseTheta,ActualX,ActualY,ActualZ,Theta") + return GetPreMappedDieInfo_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def GetDieResultAsNum(CDieIndex=""): + """ + Returns a measurement result from the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResultAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieResultAsNum(Result="", CDieIndex=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResultAsNum",Result,CDieIndex) + + +def GetDieMapResultAsNum(CDieIndex="", Site=""): + """ + Returns a measurement result from the wafer map the current die and the current + subdie, unless a subdie, and die number are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResultAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResultAsNum(Result="", CDieIndex="", Site=""): + """ + Assigns a measurement result to the wafer die map at the current die at the + current subdie, unless a subdie, and die number are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResultAsNum",Result,CDieIndex,Site) + + +def MapEdgeDies(Enable=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables edge dies for test + API Status: internal + Args: + Enable:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("MapEdgeDies",Enable) + + +def GetSpectrumData(DataPath=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows access to read any data item in Spectrum explorer. GetSpectrumData + AlignWafer/ProjectData/Mark1/ChuckPosition/X GetSpectrumData Chuck + Camera/Camera Settings/Shutter + API Status: internal + Args: + DataPath:str = "" + Returns: + Value:str + Command Timeout: 6000 + Example:GetSpectrumData Chuck Camera/Camera Settings/Shutter + """ + rsp = MessageServerInterface.sendSciCommand("GetSpectrumData",DataPath) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumData(PathAndValue=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows changing any data item in Spectrum explorer. Works independent of access + level. SetSpectrumData AlignWafer/ProjectData/Mark1/ChuckPosition/X=1000 + SetSpectrumData Chuck Camera/Camera Settings/Shutter=17 + API Status: internal + Args: + PathAndValue:str = "" + Command Timeout: 6000 + Example:SetSpectrumData Scope Camera/Camera Settings/Shutter=17 + """ + MessageServerInterface.sendSciCommand("SetSpectrumData",PathAndValue) + + +def ReadVMPosition(ToolName="", XY="", Z="", Model=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the current chuck and microscope position and sets them as + new controller or chuck and microscope positions. The command was originally used + by ReAlignWizard but may be removed in the future because of direct access to + tooldata within Spectrum. + API Status: internal + Args: + ToolName:str = "" + XY:int = 1 + Z:int = 0 + Model:int = -1 + Command Timeout: 60000 + Example:ReadVMPosition AlignWafer 1 0 0 + """ + MessageServerInterface.sendSciCommand("ReadVMPosition",ToolName,XY,Z,Model) + + +def MoveToVMPosition(ToolName="", XYChuck="", ZChuck="", XYScope="", ZScope="", Model=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command moves to trained stages positions of a requested tool. Command is + used by ReAlignWizard to move to the trained positions for AutoAlign and + DetectWaferHeight. + API Status: internal + Args: + ToolName:str = "" + XYChuck:int = 1 + ZChuck:int = 1 + XYScope:int = 0 + ZScope:int = 0 + Model:int = -1 + Command Timeout: 120000 + Example:MoveToVMPosition AlignWafer 1 0 0 0 0 + """ + MessageServerInterface.sendSciCommand("MoveToVMPosition",ToolName,XYChuck,ZChuck,XYScope,ZScope,Model) + + +def ShapeTracker(SetHome="", AutoEdgeFind="", FileName=""): + """ + ShapeTracker automatically tracks the shape of a substrate (e.g. a broken wafer) + to determine the contour of it. The data will be memorized as xy coordinates of + contour points referenced to the home position. These Points are written to a + file after tracking the shape. + API Status: published + Args: + SetHome:int = 1 + AutoEdgeFind:int = 0 + FileName:str = "" + Command Timeout: 600000 + Example:ShapeTracker 1 + """ + MessageServerInterface.sendSciCommand("ShapeTracker",SetHome,AutoEdgeFind,FileName) + + +def DetectWaferHeight(SetStartPosition="", Synchronize="", ChuckX="", ChuckY=""): + """ + Synchronizes chuck and top camera in X, Y and Z. Then the wafer surface is + focused on the trained chuck position or the manual adjusted reference position. + This tool uses the FindFocus tool with its own Range. + API Status: published + Args: + SetStartPosition:int = 0 + Synchronize:int = 0 + ChuckX:Decimal = -1 + ChuckY:Decimal = -1 + Returns: + PositionX:Decimal + PositionY:Decimal + WaferHeight:Decimal + SynchGap:Decimal + ZOffset:Decimal + Stage:str + Command Timeout: 300000 + Example:DetectWaferHeight 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("DetectWaferHeight",SetStartPosition,Synchronize,ChuckX,ChuckY) + global DetectWaferHeight_Response + if not "DetectWaferHeight_Response" in globals(): DetectWaferHeight_Response = namedtuple("DetectWaferHeight_Response", "PositionX,PositionY,WaferHeight,SynchGap,ZOffset,Stage") + return DetectWaferHeight_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def CheckSpectrumPlugin(Plugin=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command checks if a plugin is trained and returns a string of error/warning + messages including information about what is not trained, setup for the tool to + run. + API Status: internal + Args: + Plugin:str = "" + Returns: + PluginAvailable:int + Message:str + Command Timeout: 1000 + Example:CheckSpectrumPlugin AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("CheckSpectrumPlugin",Plugin) + global CheckSpectrumPlugin_Response + if not "CheckSpectrumPlugin_Response" in globals(): CheckSpectrumPlugin_Response = namedtuple("CheckSpectrumPlugin_Response", "PluginAvailable,Message") + return CheckSpectrumPlugin_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AutoAlign(SetValue="", SkipSettingHome=""): + """ + Executes the AutoAlign tool to do a theta alignment of the wafer with optional + index calculation or thermal expansion measurement. The command will update home + if home was trained. It will only move to its trained chuck/scope position + before starting the alignment if the option "MoveToTrainedXYPosition" and/or + "MoveToTrainedZPosition" is true. + API Status: published + Args: + SetValue:int = 0 + SkipSettingHome:int = 0 + Command Timeout: 300000 + Example:AutoAlign 1 + """ + MessageServerInterface.sendSciCommand("AutoAlign",SetValue,SkipSettingHome) + + +def SetCameraQuiet(Active=""): + """ + Activates/deactivates the camera quiet mode. (Applies only to ATM300A and + SPS300/SUMMIT200 stations.) The camera quiet mode deactivates the chuck, + platen and contact view camera and triggers a digital output which + connects/disconnects these cameras firewire connection to the PC. + API Status: published + Args: + Active:int = 0 + Command Timeout: 30000 + Example:SetCameraQuiet 1 + """ + MessageServerInterface.sendSciCommand("SetCameraQuiet",Active) + + +def SetRefDieOffset(RefDieCol="", RefDieRow="", RefDieDistToCentreX="", RefDieDistToCentreY=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is based on the SetMapOrientation command. It allows shifting the + center of the reference die to the center of the wafer. + API Status: internal + Args: + RefDieCol:int = 0 + RefDieRow:int = 0 + RefDieDistToCentreX:Decimal = 0 + RefDieDistToCentreY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetRefDieOffset",RefDieCol,RefDieRow,RefDieDistToCentreX,RefDieDistToCentreY) + + +def AlignWafer(TrackPosition=""): + """ + Performs a two-point alignment and moves chuck to the trained align position. XY + correction is made afterwards to calculate the new home position. + API Status: published + Args: + TrackPosition:int = 0 + Returns: + ThetaOffset:Decimal + Command Timeout: 120000 + Example:AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("AlignWafer",TrackPosition) + return Decimal(rsp[0]) + +def AlignChip(): + """ + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). The + current chip is assumed to be in the region of interest when the command is + called. + API Status: published + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChip + """ + rsp = MessageServerInterface.sendSciCommand("AlignChip") + global AlignChip_Response + if not "AlignChip_Response" in globals(): AlignChip_Response = namedtuple("AlignChip_Response", "ThetaOffset,XOffset,YOffset") + return AlignChip_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def FindFocus(StepCount="", Range=""): + """ + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. + API Status: published + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocus 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocus",StepCount,Range) + global FindFocus_Response + if not "FindFocus_Response" in globals(): FindFocus_Response = namedtuple("FindFocus_Response", "ZPosition,Stage") + return FindFocus_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAux(AuxSiteID=""): + """ + Performs an automated aux site alignment in XYZ. Tool can correct reference + position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAux 1 + """ + MessageServerInterface.sendSciCommand("AlignAux",AuxSiteID) + + +def FindFeature(Model="", ReturnDistanceFromModelOrigin="", UseSingleImageAcquisition=""): + """ + Search user-defined models. Up to 40 different models can be trained. After + training, these models can be searched on screen either by direct user + interaction or from external applications with a remote command. The remote + command returns the X/Y-Positions, angle (degree) and score value (0 - 1.0) for + each instance of the controller found in the region of interest. + API Status: published + Args: + Model:int = 1 + ReturnDistanceFromModelOrigin:int = 0 + UseSingleImageAcquisition:int = 1 + Returns: + Data:str + Command Timeout: 10000 + Example:FindFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("FindFeature",Model,ReturnDistanceFromModelOrigin,UseSingleImageAcquisition) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CloseSpectrum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + CloseSpectrum closes the Spectrum application. Used internally by CommonCommands + during Project loading. Does save configuration data but does not save project + data. + API Status: internal + Command Timeout: 6000 + Example:CloseSpectrum + """ + MessageServerInterface.sendSciCommand("CloseSpectrum") + + +def SnapImage(MountPos="", FullPath="", SnapShotMode=""): + """ + Saves the currently displayed image to the specified file. The image is stored + in the requested file format (bmp, jpg or png). By default. it will save the raw + camera image and an image with the overlays that are currently visible on the + camera view. Using a parameter, one can decide to only save either raw image, + overlay image or both. By Specifying 'ALL' as the mount position, the captured + screenshot will consist of the currently selected camera layout without + providing the raw image. If MountPos and FullPath are empty then the current + camera view with overlays is copied to the clipboard. + API Status: published + Args: + MountPos:str = "Scope" + FullPath:str = "Image.bmp" + SnapShotMode:int = 2 + Command Timeout: 60000 + Example:SnapImage Scope C:/Temp/Image.bmp + """ + MessageServerInterface.sendSciCommand("SnapImage",MountPos,FullPath,SnapShotMode) + + +def SetCameraView(Name="", Zoom="", LiveVideo="", WindowState=""): + """ + Switches the desired video window of Spectrum as foreground and active view. The + camera view can be determined over a tool name or the camera mount position. The + second parameter defines the displays zoom factor to be used. Third parameter is + used to toogle the live video. Last parameter can be used to maximize a window. + API Status: published + Args: + Name:str = "" + Zoom:int = 0 + LiveVideo:int = 2 + WindowState:int = 1 + Command Timeout: 6000 + Example:SetCameraView AlignWafer 0 2 2 + """ + MessageServerInterface.sendSciCommand("SetCameraView",Name,Zoom,LiveVideo,WindowState) + + +def SetCameraLight(Name="", State="", Shutter="", Gain="", Brightness="", Contrast="", Sharpness="", Illumination=""): + """ + Switches the light of the choosen camera on or off. Light values of -1 will + cause that the parameter is not affected. + API Status: published + Args: + Name:str = "" + State:int = 0 + Shutter:Decimal = -1 + Gain:Decimal = -1 + Brightness:int = -1 + Contrast:int = -1 + Sharpness:int = -1 + Illumination:int = -1 + Command Timeout: 6000 + Example:SetCameraLight AlignWafer 1 20 5 + """ + MessageServerInterface.sendSciCommand("SetCameraLight",Name,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination) + + +def ShowWizard(ToolName="", MountPosition="", AskExecute=""): + """ + Starts the wizard of a given tool on the display defined in the tool settings. + Additionally it can start a wizard for training single models with the syntax + e.g. ShowWizard FindFeature/ProjectData/Features/Feature1/Model For the tools + MeasureOnScreen, Calibrate and CameraOrigin you can specify a mount position + e.g. ShowWizard Calibrate Platen + API Status: published + Args: + ToolName:str = "" + MountPosition:str = "" + AskExecute:int = 0 + Returns: + Cancelled:int + Command Timeout: 10000000 + Example:ShowWizard AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("ShowWizard",ToolName,MountPosition,AskExecute) + return int(rsp[0]) + +def ProbeToPadAlign(Position=""): + """ + Sets a new Home position. The command is used during ReAlign to search the + trained home reference controller and to calculate the new xy home position. + API Status: published + Args: + Position:str = "H" + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + Command Timeout: 120000 + Example:ProbeToPadAlign H + """ + rsp = MessageServerInterface.sendSciCommand("ProbeToPadAlign",Position) + global ProbeToPadAlign_Response + if not "ProbeToPadAlign_Response" in globals(): ProbeToPadAlign_Response = namedtuple("ProbeToPadAlign_Response", "XOffsetWafer,YOffsetWafer") + return ProbeToPadAlign_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ReadOcrString(): + """ + Reads the wafer ID string from the wafer's surface. Returns the read ID as + string. Requires IDTools license. + API Status: published + Returns: + OcrString:str + Command Timeout: 60000 + Example:ReadOcrString + """ + rsp = MessageServerInterface.sendSciCommand("ReadOcrString") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadBarCode(): + """ + Reads the wafers barcode and decodes it to a string. Requires IDTools license. + API Status: published + Returns: + BarCodeString:str + Command Timeout: 60000 + Example:ReadBarCode + """ + rsp = MessageServerInterface.sendSciCommand("ReadBarCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def Read2DMatrixCode(): + """ + Reads the wafers matrix code and decodes it to a string. Requires IDTools + license. + API Status: published + Returns: + MatrixCodeString:str + Command Timeout: 60000 + Example:Read2DMatrixCode + """ + rsp = MessageServerInterface.sendSciCommand("Read2DMatrixCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumRemote(Activate=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the Spectrum remote mode. In this mode all user interface elements are + hidden and disabled. This is used when Spectrum is hosted inside VeloxPro. + API Status: internal + Args: + Activate:int = 1 + Command Timeout: 10000 + Example:SetSpectrumRemote 1 + """ + MessageServerInterface.sendSciCommand("SetSpectrumRemote",Activate) + + +def GetCameraLight(Name=""): + """ + Returns light properties of choosen camera. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + State:int + Shutter:Decimal + Gain:Decimal + Brightness:int + Contrast:int + Sharpness:int + Illumination:int + Command Timeout: 6000 + Example:GetCameraLight Scope + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraLight",Name) + global GetCameraLight_Response + if not "GetCameraLight_Response" in globals(): GetCameraLight_Response = namedtuple("GetCameraLight_Response", "MountPosition,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination") + return GetCameraLight_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7])) + +def GetCameraView(Name=""): + """ + Returns the present camera view state of a desired tool or active view. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + Zoom:int + LiveVideo:int + WindowState:int + Command Timeout: 6000 + Example:GetCameraView AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraView",Name) + global GetCameraView_Response + if not "GetCameraView_Response" in globals(): GetCameraView_Response = namedtuple("GetCameraView_Response", "MountPosition,Zoom,LiveVideo,WindowState") + return GetCameraView_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetPattern(ToolName="", ModelName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Transforms the specific controller of a demanded tool into a bitmap. This bitmap will + be stored in the same folder as the project file. The command was originally + required by ReAlignWizard and is currently no longer in use. + API Status: internal + Args: + ToolName:str = "" + ModelName:str = "" + Returns: + BitmapPath:str + Command Timeout: 30000 + Example:GetPattern AlignWafer Model1 + """ + rsp = MessageServerInterface.sendSciCommand("GetPattern",ToolName,ModelName) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowPosition(MountPosition="", DistPositionX="", DistPositionY=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the ChuckCenter under a given camera. When no camera mount position is + given, Spectrum uses active view. If there is an Offset different from zero, + this position will be moved under the camera. + API Status: internal + Args: + MountPosition:str = "" + DistPositionX:Decimal = 0 + DistPositionY:Decimal = 0 + Command Timeout: 60000 + Example:ShowPosition Scope + """ + MessageServerInterface.sendSciCommand("ShowPosition",MountPosition,DistPositionX,DistPositionY) + + +def GetCameraHomePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the home die coordinates when the home die is under the alignment camera + (for instance, the top camera). Command was used during TrainReAlign to get + the start position for Z-Profiling. Command is no longer used. + API Status: internal + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 6000 + Example:GetCameraHomePosition + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraHomePosition") + global GetCameraHomePosition_Response + if not "GetCameraHomePosition_Response" in globals(): GetCameraHomePosition_Response = namedtuple("GetCameraHomePosition_Response", "XPosition,YPosition,ZPosition") + return GetCameraHomePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SynchronizeCamera(MountPos="", SynchronizeXY="", SynchronizeZ=""): + """ + Synchronizes the Platen camera with the calibration mark. The mark is mounted on + the chuck camera. The chuck must be moved to get the mark in view of the + specified camera. + API Status: published + Args: + MountPos:str = "Scope" + SynchronizeXY:int = 0 + SynchronizeZ:int = 0 + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 120000 + Example:SynchronizeCamera S 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SynchronizeCamera",MountPos,SynchronizeXY,SynchronizeZ) + global SynchronizeCamera_Response + if not "SynchronizeCamera_Response" in globals(): SynchronizeCamera_Response = namedtuple("SynchronizeCamera_Response", "XPosition,YPosition,ZPosition") + return SynchronizeCamera_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ProbeCardOCS(UpdateZ="", MeasureBothGroups=""): + """ + Determines the chuck XYZ axis position where the needles of the probe card are + in focus. The output parameter is the Z axis value in microns from zero of the + new focus height. + API Status: published + Args: + UpdateZ:int = 1 + MeasureBothGroups:int = 1 + Returns: + ZPosition:Decimal + Command Timeout: 360000 + Example:ProbeCardOCS 1 + """ + rsp = MessageServerInterface.sendSciCommand("ProbeCardOCS",UpdateZ,MeasureBothGroups) + return Decimal(rsp[0]) + +def MoveChuckAutoXY(XPosition="", YPosition="", XSubsiteOffset="", YSubsiteOffset=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is sent by WaferMap to trigger AutoXY, AutoZ or VueTrack for each die + move. Automation must be activated/trained before command can be used. Response + is X, Y relative distance of adjustment from requested position. + API Status: internal + Args: + XPosition:Decimal = 0 + YPosition:Decimal = 0 + XSubsiteOffset:Decimal = 0 + YSubsiteOffset:Decimal = 0 + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:MoveChuckAutoXY 5000 10000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveChuckAutoXY",XPosition,YPosition,XSubsiteOffset,YSubsiteOffset) + global MoveChuckAutoXY_Response + if not "MoveChuckAutoXY_Response" in globals(): MoveChuckAutoXY_Response = namedtuple("MoveChuckAutoXY_Response", "XOffset,YOffset") + return MoveChuckAutoXY_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def VueTrackAlign(FullVueTrackAlign=""): + """ + Alignment for the next wafer when using VueTrack. + API Status: published + Args: + FullVueTrackAlign:int = 1 + Command Timeout: 6000000 + Example:VueTrackAlign + """ + MessageServerInterface.sendSciCommand("VueTrackAlign",FullVueTrackAlign) + + +def AutoFocusEVue(DistBelow="", DistAbove="", XOffsetCenter="", YOffsetCenter=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is only used internally for software testing and for providing backwards + compatibility with SCPI legacy commands. It executes a focus search using the + eVue focus drive. + API Status: internal + Args: + DistBelow:Decimal = 0 + DistAbove:Decimal = 0 + XOffsetCenter:int = 0 + YOffsetCenter:int = 0 + Returns: + FocusScore:Decimal + ZPosition:Decimal + Command Timeout: 30000 + Example:AutoFocusEVue 200 200 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("AutoFocusEVue",DistBelow,DistAbove,XOffsetCenter,YOffsetCenter) + global AutoFocusEVue_Response + if not "AutoFocusEVue_Response" in globals(): AutoFocusEVue_Response = namedtuple("AutoFocusEVue_Response", "FocusScore,ZPosition") + return AutoFocusEVue_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AutoAlignOffAxis(SetValue=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes the ReAlign Wafer Alignment tool to do a theta alignment of the wafer + with optional index calculation or thermal expansion measurement. AutoAlign is + performed using the Platen camera. Only supported for systems with off-axis + camera. + API Status: internal + Args: + SetValue:int = 0 + Command Timeout: 300000 + Example:AutoAlignOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AutoAlignOffAxis",SetValue) + + +def FindFocusOffAxis(StepCount="", Range=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Focus search is performed using the Platen camera. Only supported for + systems with off-axis camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusOffAxis 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusOffAxis",StepCount,Range) + global FindFocusOffAxis_Response + if not "FindFocusOffAxis_Response" in globals(): FindFocusOffAxis_Response = namedtuple("FindFocusOffAxis_Response", "ZPosition,Stage") + return FindFocusOffAxis_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAuxOffAxis(AuxSiteID=""): + """ + Performs an automated aux site alignment in XYZ using the Off Axis camera. Tool + can correct reference position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAuxOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AlignAuxOffAxis",AuxSiteID) + + +def FindFocusPlaten(StepCount="", Range=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Uses the FindFocus tool settings but always the Platen camera - + independent of the FindFocus mount. This command is used on e.g. BlueRay systems + that have a platen camera but can't use ReAlign/DetectWaferHeight as they don't + have an upward looking camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusPlaten 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusPlaten",StepCount,Range) + global FindFocusPlaten_Response + if not "FindFocusPlaten_Response" in globals(): FindFocusPlaten_Response = namedtuple("FindFocusPlaten_Response", "ZPosition,Stage") + return FindFocusPlaten_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignChipOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). This + command is using the off axis platen camera with functionality of ReAlign. + API Status: internal + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChipOffAxis + """ + rsp = MessageServerInterface.sendSciCommand("AlignChipOffAxis") + global AlignChipOffAxis_Response + if not "AlignChipOffAxis_Response" in globals(): AlignChipOffAxis_Response = namedtuple("AlignChipOffAxis_Response", "ThetaOffset,XOffset,YOffset") + return AlignChipOffAxis_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SelectAZoomLens(Lens=""): + """ + Selects 1 of 4 symbolic lenses (4 classified coarse ranges). + API Status: published + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:SelectAZoomLens 1 + """ + MessageServerInterface.sendSciCommand("SelectAZoomLens",Lens) + + +def GetAZoomLens(): + """ + Returns 1 of 4 symbolic lenses, coarse ranges. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:GetAZoomLens + """ + rsp = MessageServerInterface.sendSciCommand("GetAZoomLens") + return int(rsp[0]) + +def AZoomSetupDialog(): + """ + Opens the operator panel. In this window you can change the settings for all + defined lenses. + API Status: published + Command Timeout: 5000 + Example:AZoomSetupDialog + """ + MessageServerInterface.sendSciCommand("AZoomSetupDialog") + + +def MoveAZoomFocus(Focus="", Ref=""): + """ + Changes the focus magnitude. + API Status: published + Args: + Focus:int = 100 + Ref:str = "R" + Returns: + RetFocus:int + Command Timeout: 10000 + Example:MoveAZoomFocus 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomFocus",Focus,Ref) + return int(rsp[0]) + +def ReadAZoomFocus(): + """ + Returns the focus magnitude. + API Status: published + Returns: + Focus:int + Command Timeout: 5000 + Example:ReadAZoomFocus + """ + rsp = MessageServerInterface.sendSciCommand("ReadAZoomFocus") + return int(rsp[0]) + +def MoveAZoomVelocity(Direction="", Velocity=""): + """ + Moves the A-Zoom using the set focus speed. + API Status: published + Args: + Direction:str = "" + Velocity:int = 100 + Returns: + RetVelocity:Decimal + Command Timeout: 240000 + Example:MoveAZoomVelocity + 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomVelocity",Direction,Velocity) + return Decimal(rsp[0]) + +def StopAZoom(): + """ + Stops the A-Zoom movements. + API Status: published + Command Timeout: 5000 + Example:StopAZoom + """ + MessageServerInterface.sendSciCommand("StopAZoom") + + +def SetAZoomLight(Light=""): + """ + Switches all lights ON or OFF. ON means the values defined by the current lens. + 1 switches the light on, 0 switches the light off. Without parameter toggles + between on an off. + API Status: published + Args: + Light:int = 0 + Command Timeout: 5000 + Example:SetAZoomLight 1 + """ + MessageServerInterface.sendSciCommand("SetAZoomLight",Light) + + +def CloseAZoom(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the OpticalControl application. Used during Project File handling. + API Status: internal + Command Timeout: 5000 + Example:CloseAZoom + """ + MessageServerInterface.sendSciCommand("CloseAZoom") + + +def OCLightVal(Value="", Channel="", Segment=""): + """ + Set the brightness of given channel and segment to the given value. + API Status: published + Args: + Value:int = 0 + Channel:int = 1 + Segment:int = 1 + Command Timeout: 5000 + Example:OCLightVal 128 1 4 + """ + MessageServerInterface.sendSciCommand("OCLightVal",Value,Channel,Segment) + + +def OCLightOn(On="", Channel=""): + """ + Switch the light (if it has segments then all) in a given channel ON or OFF. + Switch ON - that means: light to the before adjusted brightness. + API Status: published + Args: + On:int = 0 + Channel:int = 1 + Command Timeout: 5000 + Example:OCLightOn 1 1 + """ + MessageServerInterface.sendSciCommand("OCLightOn",On,Channel) + + +def OCSetZoomLevel(Zoom="", Motor=""): + """ + Set logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Zoom:int = 0 + Motor:int = 1 + Command Timeout: 5000 + Example:OCSetZoomLevel 50 1 + """ + MessageServerInterface.sendSciCommand("OCSetZoomLevel",Zoom,Motor) + + +def OCGetZoomLevel(Motor=""): + """ + Get logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Motor:int = 1 + Returns: + Zoom:int + Command Timeout: 5000 + Example:OCGetZoomLevel 1 + """ + rsp = MessageServerInterface.sendSciCommand("OCGetZoomLevel",Motor) + return int(rsp[0]) + +def StartReAlignTemperature(TargetTemperature="", ThetaAlignOnFinish="", ContactOnFinish=""): + """ + Starts temperature ramping using ReAlign. ReAlign will re-adjust the probes and + wafer during ramping to the new target temperature. Command returns immediately. + The status of temperature ramping must be checked using the + GetReAlignTemperatureStatus command. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + Command Timeout: 5000 + Example:StartReAlignTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartReAlignTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish) + + +def StopReAlignTemperature(): + """ + Stops temperature ramping using ReAlign. + API Status: published + Command Timeout: 10000 + Example:StopReAlignTemperature + """ + MessageServerInterface.sendSciCommand("StopReAlignTemperature") + + +def GetReAlignTemperatureStatus(): + """ + Returns the status of the current temperature ramping using ReAlign process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetReAlignTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignTemperatureStatus") + global GetReAlignTemperatureStatus_Response + if not "GetReAlignTemperatureStatus_Response" in globals(): GetReAlignTemperatureStatus_Response = namedtuple("GetReAlignTemperatureStatus_Response", "StatusId,StatusStr") + return GetReAlignTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReAlign(Repeats="", Mode="", AlignProbeCard="", CorrectZ=""): + """ + Performs an automatic realignment of the wafer. This includes measuring the + needle drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck + drift XYZ and optionally a Z-Profile. Alternatively the tool performs a + ProbeToDie Alignment to correct the needle position for the current die. Command + returns once ReAlign is finished or aborted because of an error. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + ZOffsetWafer:Decimal + XOffsetCard:Decimal + YOffsetCard:Decimal + ZOffsetCard:Decimal + Command Timeout: 1000000 + Example:ReAlign 2 H 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + global ReAlign_Response + if not "ReAlign_Response" in globals(): ReAlign_Response = namedtuple("ReAlign_Response", "XOffsetWafer,YOffsetWafer,ZOffsetWafer,XOffsetCard,YOffsetCard,ZOffsetCard") + return ReAlign_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def NextWafer(): + """ + Starts the NextWafer routine. + API Status: published + Returns: + Canceled:int + Command Timeout: 60000000 + Example:NextWafer + """ + rsp = MessageServerInterface.sendSciCommand("NextWafer") + return int(rsp[0]) + +def StartReAlign(Repeats="", Mode="", AlignProbeCard="", CorrectZ=""): + """ + Starts an automatic realignment of the wafer. This includes measuring the needle + drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck drift + XYZ and optionally a Z-Profile. Alternatively the tool performs a ProbeToPad + Alignment to correct the needle position for the current die. Command returns + immediately. The status of the asynchronous ReAlign execution must be checked + using the GetReAlignStatus command. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Command Timeout: 60000 + Example:StartReAlign 2 H 0 0 + """ + MessageServerInterface.sendSciCommand("StartReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + + +def StopReAlign(): + """ + Stops the ReAlign procedure. + API Status: published + Command Timeout: 120000 + Example:StopReAlign + """ + MessageServerInterface.sendSciCommand("StopReAlign") + + +def GetReAlignStatus(): + """ + Returns a status of the ReAlign procedure. If the return value is true, ReAlign + is running. + API Status: published + Returns: + Running:int + Command Timeout: 60000 + Example:GetReAlignStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignStatus") + return int(rsp[0]) + +def EnableOverlay(Overlay=""): + """ + Allows activating the overlay of the needles for the top camera. + API Status: published + Args: + Overlay:int = 0 + Command Timeout: 6000 + Example:EnableOverlay 0 + """ + MessageServerInterface.sendSciCommand("EnableOverlay",Overlay) + + +def SwitchOffset(Offset=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Switches the offset compensation. Applicable for MicroAlign stations only. + API Status: internal + Args: + Offset:int = 0 + Command Timeout: 60000 + Example:SwitchOffset 1 + """ + MessageServerInterface.sendSciCommand("SwitchOffset",Offset) + + +def TrainFeature(Model=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command was only implemented for supporting a SCPI legacy command. Does not make + sense in Velox, as there is no default training rectangle on the screen as in + Nucleus. + API Status: internal + Args: + Model:int = 1 + Returns: + Data:str + Command Timeout: 30000 + Example:TrainFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("TrainFeature",Model) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetEvueExposureLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Returns: + Exposure:Decimal + Command Timeout: 10000 + Example:GetEvueExposureLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueExposureLevel") + return Decimal(rsp[0]) + +def SetEvueExposureLevel(Exposure=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Args: + Exposure:Decimal = 0 + Command Timeout: 10000 + Example:SetEvueExposureLevel + """ + MessageServerInterface.sendSciCommand("SetEvueExposureLevel",Exposure) + + +def MoveEvueFocusStage(EvueZ="", EvueVelocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the eVue focus stage to a specified position. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + EvueZ:Decimal = 0 + EvueVelocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveEvueFocusStage 1000 + """ + MessageServerInterface.sendSciCommand("MoveEvueFocusStage",EvueZ,EvueVelocity) + + +def GetEvueFocusStagePos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the eVue focus stage. Implemented for supporting + SCPI legacy command. + API Status: internal + Returns: + EvueZ:Decimal + Command Timeout: 5000 + Example:GetEvueFocusStagePos + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueFocusStagePos") + return Decimal(rsp[0]) + +def RunEvueAutoExpose(UseCB=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command runs the AutoExpose function for the eVue. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + UseCB:int = 1 + Command Timeout: 20000 + Example:RunEvueAutoExpose 1 + """ + MessageServerInterface.sendSciCommand("RunEvueAutoExpose",UseCB) + + +def GetEvueZoomLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope that is connected to Velox. On eVue + systems, this command, returns values ranging from 0.5 to 5.0 for a 10x system + and 0.5 to 20.0 for a 40x system. + API Status: internal + Returns: + Zoom:Decimal + Command Timeout: 5000 + Example:GetEvueZoomLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueZoomLevel") + return Decimal(rsp[0]) + +def SetEvueZoomLevel(Zoom=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope or an A-Zoom microscope that is connected to + Velox. On eVue systems, this command sets the proper CCD zoom level to the + appropriate optical path. + API Status: internal + Args: + Zoom:Decimal = 0 + Command Timeout: 5000 + Example:SetEvueZoomLevel 2.0 + """ + MessageServerInterface.sendSciCommand("SetEvueZoomLevel",Zoom) + + +def StartAutomationTemperature(TargetTemperature="", ThetaAlignOnFinish="", ContactOnFinish="", AlignOnFinish=""): + """ + Starts temperature ramping using Automation. The Automation (mostly VueTrack) + will re-adjust the probes and wafer during ramping to the new target + temperature. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + AlignOnFinish:int = 1 + Command Timeout: 5000 + Example:StartAutomationTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartAutomationTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish,AlignOnFinish) + + +def StopAutomationTemperature(): + """ + Stops temperature ramping using Automation. + API Status: published + Command Timeout: 10000 + Example:StopAutomationTemperature + """ + MessageServerInterface.sendSciCommand("StopAutomationTemperature") + + +def GetAutomationTemperatureStatus(): + """ + Returns the status of the current temperature ramping using automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetAutomationTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationTemperatureStatus") + global GetAutomationTemperatureStatus_Response + if not "GetAutomationTemperatureStatus_Response" in globals(): GetAutomationTemperatureStatus_Response = namedtuple("GetAutomationTemperatureStatus_Response", "StatusId,StatusStr") + return GetAutomationTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationActive(): + """ + Command to read from Spectrum if Automation (AutoXY, AutoZ or VueTrack) is + active. Command is used by WaferMap to read if it must send MoveChuckAutoXY + instead of MoveChuck + API Status: published + Returns: + Active:int + Command Timeout: 1000 + Example:GetAutomationActive + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationActive") + return int(rsp[0]) + +def AutomationNeedleSearch(NeedleIndex="", MoveScope=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + VueTrack vision search of the given needle index. + API Status: internal + Args: + NeedleIndex:int = 1 + MoveScope:int = 1 + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + ZMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationNeedleSearch 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("AutomationNeedleSearch",NeedleIndex,MoveScope) + global AutomationNeedleSearch_Response + if not "AutomationNeedleSearch_Response" in globals(): AutomationNeedleSearch_Response = namedtuple("AutomationNeedleSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore,ZMatchScore") + return AutomationNeedleSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def AutomationReferenceSearch(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + AutomationReferenceSearch exposes the functionality of searching the Automation + reference target via remote command + API Status: internal + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationReferenceSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationReferenceSearch") + global AutomationReferenceSearch_Response + if not "AutomationReferenceSearch_Response" in globals(): AutomationReferenceSearch_Response = namedtuple("AutomationReferenceSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore") + return AutomationReferenceSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def MovePositionersSafe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the configured motorized positioners to a safe position + API Status: internal + Command Timeout: 60000 + Example:MovePositionersSafe + """ + MessageServerInterface.sendSciCommand("MovePositionersSafe") + + +def SetConstantContactMode(IsOn="", ForceLastCorrection=""): + """ + Starts Constant Contact mode using Automation. The Automation will re-adjust the + wafer during ramping to the new target temperature. + API Status: published + Args: + IsOn:int = 0 + ForceLastCorrection:int = 0 + Command Timeout: 5000 + Example:SetConstantContactMode 1 + """ + MessageServerInterface.sendSciCommand("SetConstantContactMode",IsOn,ForceLastCorrection) + + +def GetConstantContactModeStatus(): + """ + Returns the status of the current ConstantContact automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 5000 + Example:GetConstantContactModeStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetConstantContactModeStatus") + global GetConstantContactModeStatus_Response + if not "GetConstantContactModeStatus_Response" in globals(): GetConstantContactModeStatus_Response = namedtuple("GetConstantContactModeStatus_Response", "StatusId,StatusStr") + return GetConstantContactModeStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetAutomationActive(Activate=""): + """ + Command to set if Automation (AutoXY, AutoZ or VueTrack) is active. Command can + be used to e.g. deactivate automation programmatically in case it is no + longer used. When activating automation, the command will return an error in + case it is not possible (e.g. not trained) + API Status: published + Args: + Activate:int = 0 + Command Timeout: 1000 + Example:SetAutomationActive 1 + """ + MessageServerInterface.sendSciCommand("SetAutomationActive",Activate) + + +def AutomationSearchCurrentDie(): + """ + Performs an Automation search and position correction using the current chuck + position. Response is X, Y relative distance of adjustment. + API Status: published + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:AutomationSearchCurrentDie + """ + rsp = MessageServerInterface.sendSciCommand("AutomationSearchCurrentDie") + global AutomationSearchCurrentDie_Response + if not "AutomationSearchCurrentDie_Response" in globals(): AutomationSearchCurrentDie_Response = namedtuple("AutomationSearchCurrentDie_Response", "XOffset,YOffset") + return AutomationSearchCurrentDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def PreMapWafer(): + """ + PreMapWafer finds actual singulated die locations and updates positions used by + WaferMap. + API Status: published + Returns: + NumberOfDies:int + Command Timeout: 14400000 + Example:PreMapWafer + """ + rsp = MessageServerInterface.sendSciCommand("PreMapWafer") + return int(rsp[0]) + +def ISSProbeAlign(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs an probe to pad operation on the ISS with two RF positioners. + API Status: internal + Command Timeout: 6000000 + Example:ISSProbeAlign + """ + MessageServerInterface.sendSciCommand("ISSProbeAlign") + + +def FindWaferCenter(NoManualRecovery=""): + """ + FindWaferCenter finds the center of the wafer using edge detection. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:FindWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("FindWaferCenter",NoManualRecovery) + global FindWaferCenter_Response + if not "FindWaferCenter_Response" in globals(): FindWaferCenter_Response = namedtuple("FindWaferCenter_Response", "ChuckX,ChuckY") + return FindWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def LocateHomeDie(NoManualRecovery=""): + """ + LocateHomeDie finds the center of the wafer using edge detection and sets the + home position. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:LocateHomeDie + """ + rsp = MessageServerInterface.sendSciCommand("LocateHomeDie",NoManualRecovery) + global LocateHomeDie_Response + if not "LocateHomeDie_Response" in globals(): LocateHomeDie_Response = namedtuple("LocateHomeDie_Response", "ChuckX,ChuckY") + return LocateHomeDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetAutomationProbeLayout(LayoutName="", ProbeID="", XOffset="", YOffset=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stores the provided X or Y offset for the given probe for the specified layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Command Timeout: 10000 + Example:SetAutomationProbeLayout "layout1" 1 100.0 0 + """ + MessageServerInterface.sendSciCommand("SetAutomationProbeLayout",LayoutName,ProbeID,XOffset,YOffset) + + +def DeleteAutomationProbeLayout(LayoutName="", ProbeID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Delete the specfied layout. If LayoutName is empty then all layouts are deleted. + If optional ProbeID parmameter is set, it removes just that probe from the + layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 10000 + Example:DeleteAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("DeleteAutomationProbeLayout",LayoutName,ProbeID) + + +def CaptureAutomationProbeLayout(LayoutName="", ProbeID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Capture the specfied layout. If optional ProbeID parmameter is set, it captures + just that probe from the layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 30000 + Example:CaptureAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("CaptureAutomationProbeLayout",LayoutName,ProbeID) + + +def MoveToAutomationProbeLayout(LayoutName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move to the probes to specfied layout which are offsets from the trained + positions. + API Status: internal + Args: + LayoutName:str = "" + Command Timeout: 300000 + Example:MoveToAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("MoveToAutomationProbeLayout",LayoutName) + + +def ResetAutomation(): + """ + Reset automation data back to trained values. + API Status: published + Command Timeout: 10000 + Example:ResetAutomation + """ + MessageServerInterface.sendSciCommand("ResetAutomation") + + +def GetWaferCenter(): + """ + GetWaferCenter returns the chuck location (zero based) of the wafer center. It + returns 0 0 if FindWaferCenter has not been executed for the current wafer. + API Status: published + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 10000 + Example:GetWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferCenter") + global GetWaferCenter_Response + if not "GetWaferCenter_Response" in globals(): GetWaferCenter_Response = namedtuple("GetWaferCenter_Response", "ChuckX,ChuckY") + return GetWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def InitEvueFocusStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the eVue focus stage by finding the limit switches + API Status: internal + Command Timeout: 30000 + Example:InitEvueFocusStage + """ + MessageServerInterface.sendSciCommand("InitEvueFocusStage") + + +def EvueSetNumTraceEntriesPreTrigger(NumTraceEntriesPreTrigger=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Args: + NumTraceEntriesPreTrigger:int = 0 + Command Timeout: 30000 + Example:EvueSetNumTraceEntriesPreTrigger 14 + """ + MessageServerInterface.sendSciCommand("EvueSetNumTraceEntriesPreTrigger",NumTraceEntriesPreTrigger) + + +def EvueGetNumTraceEntriesPreTrigger(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Returns: + NumTraceEntriesPreTrigger:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntriesPreTrigger + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntriesPreTrigger") + return int(rsp[0]) + +def EvueStartCaptureServoTrace(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts capturing events in the eVue motion capture log. Capture continues until + the log is full. However, log entries will overwrite the oldest entry until the + trigger event is encountered. Then, {X} events are preserved prior to the + trigger event and the oldest events are only overwritten if they are not part of + that preserved set. + API Status: internal + Command Timeout: 30000 + Example:EvueStartCaptureServoTrace + """ + MessageServerInterface.sendSciCommand("EvueStartCaptureServoTrace") + + +def EvueGetTraceMachineStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current status of the trace machine. Bit fields - bit0 is 1 and bit4 is + 16, etc. bit0 - active and in pre-trigger state bit1 - active and in post- + trigger state bit2 - stopped by servo error, lens crash or lens removal bit3 - + stopped on requested server state entry bit4 - stopped by immediate command + bit5..31 - reserved + API Status: internal + Returns: + TraceMachineStatus:int + Command Timeout: 30000 + Example:EvueGetTraceMachineStatus + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceMachineStatus") + return int(rsp[0]) + +def EvueSetTraceCaptureStopBits(TraceCaptureStopBits=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets condition bits to trigger servo trace capture. Bit fields - bit0 is 1 and + bit4 is 16, etc. bit0 - immediate stop bit1 - stop on servo error, lens crash or + lens removal bit2 - stop on requested server state (defined by bits 4..7) bit3 - + stop on motor move finish bit4..7 - servo state that triggers a trace stop (not + an index but the 4-bit state that, if seen, is the trigger for trace capture) + bit8..31 - reserved + API Status: internal + Args: + TraceCaptureStopBits:int = 0 + Command Timeout: 30000 + Example:EvueSetTraceCaptureStopBits + """ + MessageServerInterface.sendSciCommand("EvueSetTraceCaptureStopBits",TraceCaptureStopBits) + + +def EvueGetNumTraceEntries(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current status of the trace machine. + API Status: internal + Returns: + TraceEntries:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntries + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntries") + return int(rsp[0]) + +def EvueGetTraceEntry(EntryIdx=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the N'th trace entry in the log. + API Status: internal + Args: + EntryIdx:int = 0 + Returns: + CommandedPositionMotorCounts:int + CommandedPositionMicrons:Decimal + MeasuredPositionMotorCounts:int + MeasuredPositionMicrons:Decimal + TimestampMicroseconds:int + ServoStatus:int + PwmVal:int + Command Timeout: 30000 + Example:EvueGetTraceEntry 32 + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceEntry",EntryIdx) + global EvueGetTraceEntry_Response + if not "EvueGetTraceEntry_Response" in globals(): EvueGetTraceEntry_Response = namedtuple("EvueGetTraceEntry_Response", "CommandedPositionMotorCounts,CommandedPositionMicrons,MeasuredPositionMotorCounts,MeasuredPositionMicrons,TimestampMicroseconds,ServoStatus,PwmVal") + return EvueGetTraceEntry_Response(int(rsp[0]),Decimal(rsp[1]),int(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def AutomationRFProbeSearch(ImageFilename=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the distance in X,Y between the center tips of the RF probes. + API Status: internal + Args: + ImageFilename:str = "" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 5000 + Example:AutomationRFProbeSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationRFProbeSearch",ImageFilename) + global AutomationRFProbeSearch_Response + if not "AutomationRFProbeSearch_Response" in globals(): AutomationRFProbeSearch_Response = namedtuple("AutomationRFProbeSearch_Response", "X,Y") + return AutomationRFProbeSearch_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def StartAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the AutoRF calibration sequence. + API Status: internal + Command Timeout: 3000 + Example:StartAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StartAutoRFCalibration") + + +def StopAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the currently running AutoRF calibraiton. + API Status: internal + Command Timeout: 10000 + Example:StopAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StopAutoRFCalibration") + + +def GetAutoRFCalibrationStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the status of the AutoRF calibration sequence. + API Status: internal + Returns: + StatusId:int + StatusStr:str + Command Timeout: 1000 + Example:GetAutoRFCalibrationStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutoRFCalibrationStatus") + global GetAutoRFCalibrationStatus_Response + if not "GetAutoRFCalibrationStatus_Response" in globals(): GetAutoRFCalibrationStatus_Response = namedtuple("GetAutoRFCalibrationStatus_Response", "StatusId,StatusStr") + return GetAutoRFCalibrationStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationLastStepDiagnostics(Index=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the diagnostic state information for the provided index. + API Status: internal + Args: + Index:int = 0 + Returns: + DiagnosticInfo:str + Command Timeout: 5000 + Example:GetAutomationLastStepDiagnostics + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationLastStepDiagnostics",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMNanoChamberState(State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the WLEM Nano Chamber State. + API Status: internal + Args: + State:str = "Free" + Command Timeout: 5000 + Example:SetWLEMNanoChamberState Free + """ + MessageServerInterface.sendSciCommand("SetWLEMNanoChamberState",State) + + +def GetWLEMNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the WLEM Nano Chamber State. + API Status: internal + Returns: + State:str + Command Timeout: 5000 + Example:GetWLEMNanoChamberState + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMState(State="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMState NCSeal 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMState",State,Value) + + +def GetWLEMState(State=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMState NCSeal + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMState",State) + return int(rsp[0]) + +def GetWLEMSensorValue(Sensor=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the value of a WLEM Sensor. + API Status: internal + Args: + Sensor:str = "O2Concentration" + Returns: + Value:Decimal + Command Timeout: 5000 + Example:GetWLEMSensorValue O2Concentration + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMSensorValue",Sensor) + return Decimal(rsp[0]) + +def SetWLEMOption(Option="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMOption MinimizeToTray 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMOption",Option,Value) + + +def GetWLEMOption(Option=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMOption MinimizeToTray + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMOption",Option) + return int(rsp[0]) + +def NewTesterProject(LotID="", TileID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a new Lot/Tile is to be tested. The tester + responds with the correct project name for the test. This is needed because the + prober needs to verify that the correct project is loaded. In case no valid + project is available, the command is returned with an error. + API Status: internal + Args: + LotID:str = "" + TileID:str = "" + Returns: + ProjectName:str + Command Timeout: 30000 + Example:NewTesterProject Lot01 Tile01 + """ + rsp = MessageServerInterface.sendSciCommand("NewTesterProject",LotID,TileID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StartMeasurement(DieColumn="", DieRow="", ActiveDies=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester to begin measuring (Needles are in correct + position and in contact). The command is responded when the measurement has + finished. The response string holds the binning information separated by comma. + For deactivated dies, a bin value of '0' should be responded. + API Status: internal + Args: + DieColumn:int = 0 + DieRow:int = 0 + ActiveDies:str = "" + Returns: + BinNumbers:str + Command Timeout: 100000 + Example:StartMeasurement 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("StartMeasurement",DieColumn,DieRow,ActiveDies) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def EndOfWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current substrate has + finished. It enables the tester application to save measurement data and/or + prepare for the next substrate. + API Status: internal + Command Timeout: 30000 + Example:EndOfWafer + """ + MessageServerInterface.sendSciCommand("EndOfWafer") + + +def EndOfLot(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current lot has finished. It + enables the tester application to save measurement data and/or prepare for the + next lot. + API Status: internal + Command Timeout: 30000 + Example:EndOfLot + """ + MessageServerInterface.sendSciCommand("EndOfLot") + + +def VerifyProductID(ProductID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProductID that is to be tested. The + tester can respond with an error in case the ProductID is not allowed for + testing. + API Status: internal + Args: + ProductID:str = "" + Command Timeout: 30000 + Example:VerifyProductID Product123 + """ + MessageServerInterface.sendSciCommand("VerifyProductID",ProductID) + + +def VerifyLotID(LotID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the LotID that is to be tested. The tester + can respond with an error in case the LotID is not allowed for testing. + API Status: internal + Args: + LotID:str = "" + Command Timeout: 30000 + Example:VerifyLotID Lot123 + """ + MessageServerInterface.sendSciCommand("VerifyLotID",LotID) + + +def VerifySubstrateID(SubstrateID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the SubstrateID that is to be tested. The + tester can respond with an error in case the SubstrateID is not allowed for + testing. + API Status: internal + Args: + SubstrateID:str = "" + Command Timeout: 30000 + Example:VerifySubstrateID Substrate123 + """ + MessageServerInterface.sendSciCommand("VerifySubstrateID",SubstrateID) + + +def VerifyProbecard(ProbeCard="", Touchdowns=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProbecardID and touchdowns that is + used for testing. The tester can respond with an error in case the Probecard is + not allowed for testing. + API Status: internal + Args: + ProbeCard:str = "" + Touchdowns:int = 0 + Command Timeout: 30000 + Example:VerifyProbecard Probecard123 10596 + """ + MessageServerInterface.sendSciCommand("VerifyProbecard",ProbeCard,Touchdowns) + + +def VerifyUserID(User=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the User ID. The tester can respond with + an error in case the User ID is not allowed for testing. + API Status: internal + Args: + User:str = "" + Command Timeout: 30000 + Example:VerifyUserID User123 + """ + MessageServerInterface.sendSciCommand("VerifyUserID",User) + + +def TesterAbort(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the job was aborted and no more test will + happen. + API Status: internal + Command Timeout: 30000 + Example:TesterAbort + """ + MessageServerInterface.sendSciCommand("TesterAbort") + + +def VerifySOTReady(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a wafer is ready for testing which will + immediately start. This command is sent in the recipe sequence "Verify + SOTReady". + API Status: internal + Command Timeout: 30000 + Example:VerifySOTReady + """ + MessageServerInterface.sendSciCommand("VerifySOTReady") + + +def VerifyWaferStart(SubstrateID="", CassettePlace="", LotID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent in the VeloxPro recipe sequence "Verify Wafer Start" and + informs the tester about the current wafer on the chuck. + API Status: internal + Args: + SubstrateID:str = "" + CassettePlace:str = "" + LotID:str = "" + Command Timeout: 30000 + Example:VerifyWaferStart Wafer01 1 Lot01 + """ + MessageServerInterface.sendSciCommand("VerifyWaferStart",SubstrateID,CassettePlace,LotID) + + +def TesterCassetteInfo(CassetteCmd=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command will be sent after the user selected which wafers are to be tested. + It contains a string which represents the state of each wafer: 0 = empty, 1 = + full (and selected), 2 = error (e.g. double slotted), 3 = unknown, 4 = + deselected + API Status: internal + Args: + CassetteCmd:str = "" + Returns: + CassetteRsp:str + Command Timeout: 30000 + Example:TesterCassetteInfo 0000001110000000010010111 + """ + rsp = MessageServerInterface.sendSciCommand("TesterCassetteInfo",CassetteCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def VerifyProject(ProjectName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent after selecting a project file in the VeloxPro product + setup page. The command sends the name of the project to tester for + verification. + API Status: internal + Args: + ProjectName:str = "" + Command Timeout: 30000 + Example:VerifyProject C:/Users/Public/Documents/Velox/Projects/Test.spp + """ + MessageServerInterface.sendSciCommand("VerifyProject",ProjectName) + + +def TesterAbortWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the test for the current wafer was aborted + and no more tests will happen with the current wafer. The job will continue + though. + API Status: internal + Command Timeout: 30000 + Example:TesterAbortWafer + """ + MessageServerInterface.sendSciCommand("TesterAbortWafer") + + +def DoTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts execution of one test. It returns a bin number or multple bin numbers + when clusters are enabled in the WaferMap (one number for each die in a + cluster). The command starts execution of one test. It returns a bin number or + multple bin numbers when clusters are enabled in the WaferMap (one number for + each die in a cluster). + API Status: internal + Returns: + BitNumber:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DoTTLTest") + return int(rsp[0]) + +def StartTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the test of a wafer. Depending on the cluster definitions queried from + the WaferMap, all clusters or all dies will be tested. The command starts the + test of a wafer. Depending on the cluster definitions queried from the WaferMap + all clusters or all dies will be tested. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("StartTTLTest") + + +def CancelTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the wafer test. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CancelTTLTest") + + +def SetTTLLine(Line="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the selected line of PA port. + API Status: internal + Args: + Line:int = 0 + Value:int = 0 + Command Timeout: 10000 + Example:SetTTLLine 2 0 + """ + MessageServerInterface.sendSciCommand("SetTTLLine",Line,Value) + + +def GetTTLLines(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the I/O lines as bit array. + API Status: internal + Returns: + LineA:int + LineB:int + LineC:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLLines") + global GetTTLLines_Response + if not "GetTTLLines_Response" in globals(): GetTTLLines_Response = namedtuple("GetTTLLines_Response", "LineA,LineB,LineC") + return GetTTLLines_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetTTLStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns returns the error 914 if the test is in progress. + API Status: internal + Returns: + ErrCode:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLStatus") + return int(rsp[0]) + +def StartScript(ScriptName=""): + """ + Starts the script and returns the response immediately. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000 + Example:StartScript myscript + """ + MessageServerInterface.sendSciCommand("StartScript",ScriptName) + + +def GetRunStatus(ScriptName=""): + """ + Command returns information about Communicator status. + API Status: published + Args: + ScriptName:str = "" + Returns: + Running:int + LastError:int + Title:str + Command Timeout: 5000 + Example:GetRunStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetRunStatus",ScriptName) + global GetRunStatus_Response + if not "GetRunStatus_Response" in globals(): GetRunStatus_Response = namedtuple("GetRunStatus_Response", "Running,LastError,Title") + return GetRunStatus_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def CloseCommunicator(): + """ + Command closes the program. Used during ProjectFile handling. + API Status: published + Command Timeout: 10000 + Example:CloseCommunicator + """ + MessageServerInterface.sendSciCommand("CloseCommunicator") + + +def DoScript(ScriptName=""): + """ + Executes the script and returns the response afterwards. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000000 + Example:DoScript myscript + """ + MessageServerInterface.sendSciCommand("DoScript",ScriptName) + + +def ReadKernelData(SilentMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads Kernel Data to KernelSetup (Left Program pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReadKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReadKernelData",SilentMode) + + +def SaveKernelDataAs(FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves Kernel Data (Left Program pane) to File. An existing File will be + overwritten. If the Folder does not exist, it will be created + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveKernelDataAs C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("SaveKernelDataAs",FileName) + + +def LoadConfigFile(FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads File Data to KernelSetup (Right Program pane). + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:LoadConfigFile C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("LoadConfigFile",FileName) + + +def ReplaceKernelDataByFileData(SilentMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces Kernel Data (Left pane) by File Data (Right pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceKernelDataByFileData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceKernelDataByFileData",SilentMode) + + +def ReplaceFileTreeByKernelData(SilentMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces File Tree (Right pane) by Kernel Data (Left pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceFileTreeByKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceFileTreeByKernelData",SilentMode) + + +def SaveFileTreeAs(FileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves File Tree (Right pane) to File. An existing File will be overwritten. If + the Folder does not exist, it will be created. + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveFileTreeAs C:/Temp/RCConfigSample2.xml + """ + MessageServerInterface.sendSciCommand("SaveFileTreeAs",FileName) + + +def HeatChuck(Temperature="", Unit="", ReduceContact=""): + """ + Sets a new target temperature and starts the heating or cooling of the chuck. An + answer to the command will be returned after reaching the given temperature and + waiting the soak time or an unexpected interrupt of the process. Given back is + the already reached temperature. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + ReduceContact:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 36000000 + Example:HeatChuck 61.3 C + """ + rsp = MessageServerInterface.sendSciCommand("HeatChuck",Temperature,Unit,ReduceContact) + global HeatChuck_Response + if not "HeatChuck_Response" in globals(): HeatChuck_Response = namedtuple("HeatChuck_Response", "RespTemperature,RespUnit") + return HeatChuck_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetHeaterTemp(Temperature="", Unit="", UseContactSafety=""): + """ + Sets a new target temperature and starts the heating or cooling of the + temperature chuck. The new target temperature is returned immediately as the + command does not wait until heating is complete. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + UseContactSafety:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:SetHeaterTemp 55.5 C + """ + rsp = MessageServerInterface.sendSciCommand("SetHeaterTemp",Temperature,Unit,UseContactSafety) + global SetHeaterTemp_Response + if not "SetHeaterTemp_Response" in globals(): SetHeaterTemp_Response = namedtuple("SetHeaterTemp_Response", "RespTemperature,RespUnit") + return SetHeaterTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetHeaterTemp(Unit="", ExternalHeaterID=""): + """ + Reads the current temperature of the chuck and determines the status of the + thermal system. + API Status: published + Args: + Unit:str = "Celsius" + ExternalHeaterID:int = 0 + Returns: + RespTemperature:Decimal + RespUnit:str + Status:str + Command Timeout: 60000 + Example:GetHeaterTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterTemp",Unit,ExternalHeaterID) + global GetHeaterTemp_Response + if not "GetHeaterTemp_Response" in globals(): GetHeaterTemp_Response = namedtuple("GetHeaterTemp_Response", "RespTemperature,RespUnit,Status") + return GetHeaterTemp_Response(Decimal(rsp[0]),str(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def EnableHeaterHoldMode(HoldMode=""): + """ + Switches the Temperature Chuck devices hold mode on or off. In hold mode the + chuck is heated with a constant current to avoid noise from the temperature + control. The hold mode can be enabled only in HoldReady state. + API Status: published + Args: + HoldMode:int = 1 + Returns: + RespHoldMode:int + Command Timeout: 60000 + Example:EnableHeaterHoldMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterHoldMode",HoldMode) + return int(rsp[0]) + +def StopHeatChuck(): + """ + Stops a pending heating or cooling process. If the device is not at temperature, + the actual temperature is set as target temperature. + API Status: published + Command Timeout: 60000 + Example:StopHeatChuck + """ + MessageServerInterface.sendSciCommand("StopHeatChuck") + + +def GetDewPointTemp(Unit=""): + """ + Returns the current dew point temperature, if a dew point sensor is connected. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetDewPointTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetDewPointTemp",Unit) + global GetDewPointTemp_Response + if not "GetDewPointTemp_Response" in globals(): GetDewPointTemp_Response = namedtuple("GetDewPointTemp_Response", "RespTemperature,RespUnit") + return GetDewPointTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetTemperatureChuckOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the currently set temperature chuck options. + API Status: internal + Returns: + UseSoakTime:int + SyncTemp:int + CurrConnection:int + MinTemperature:Decimal + MaxTemperature:Decimal + UsePurge:int + UseDynamicSoakTime:int + UseFixedDieSoakTime:int + UseDynamicDieSoakTime:int + UseEcoMode:int + PurgeOnChamberDoor:int + ForceBypassPurge:int + DoorClosedTime:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTemperatureChuckOptions") + global GetTemperatureChuckOptions_Response + if not "GetTemperatureChuckOptions_Response" in globals(): GetTemperatureChuckOptions_Response = namedtuple("GetTemperatureChuckOptions_Response", "UseSoakTime,SyncTemp,CurrConnection,MinTemperature,MaxTemperature,UsePurge,UseDynamicSoakTime,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime") + return GetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12])) + +def SetTemperatureChuckOptions(UseFixedWaferSoak="", SyncTemp="", CurrConnection="", UsePurge="", UseDynamicWaferSoak="", UseFixedDieSoakTime="", UseDynamicDieSoakTime="", UseEcoMode="", PurgeOnChamberDoor="", ForceBypassPurge="", DoorClosedTime=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is used to change the currently set temperature chuck options. + API Status: internal + Args: + UseFixedWaferSoak:int = -1 + SyncTemp:int = -1 + CurrConnection:int = -1 + UsePurge:int = -1 + UseDynamicWaferSoak:int = -1 + UseFixedDieSoakTime:int = -1 + UseDynamicDieSoakTime:int = -1 + UseEcoMode:int = -1 + PurgeOnChamberDoor:int = -1 + ForceBypassPurge:int = -1 + DoorClosedTime:int = -1 + Returns: + UseFixedWaferSoakRsp:int + SyncTempRsp:int + CurrConnectionRsp:int + UsePurgeRsp:int + UseDynamicWaferSoakRsp:int + UseFixedDieSoakTimeRsp:int + UseDynamicDieSoakTimeRsp:int + UseEcoModeRsp:int + PurgeOnChamberDoorRsp:int + ForceBypassPurgeRsp:int + DoorClosedTimeRsp:int + Command Timeout: 300000 + Example:SetTemperatureChuckOptions 1 0 1 1 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetTemperatureChuckOptions",UseFixedWaferSoak,SyncTemp,CurrConnection,UsePurge,UseDynamicWaferSoak,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime) + global SetTemperatureChuckOptions_Response + if not "SetTemperatureChuckOptions_Response" in globals(): SetTemperatureChuckOptions_Response = namedtuple("SetTemperatureChuckOptions_Response", "UseFixedWaferSoakRsp,SyncTempRsp,CurrConnectionRsp,UsePurgeRsp,UseDynamicWaferSoakRsp,UseFixedDieSoakTimeRsp,UseDynamicDieSoakTimeRsp,UseEcoModeRsp,PurgeOnChamberDoorRsp,ForceBypassPurgeRsp,DoorClosedTimeRsp") + return SetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10])) + +def GetHeaterSoak(): + """ + Returns the current soak time values in seconds and the soaking status. + API Status: published + Returns: + FixedWaferSoakTime:int + FixedWaferSoakStatus:int + DynamicWaferSoakTime:Decimal + DynamicWaferSoakStatus:int + FixedDieSoakTime:Decimal + DynamicDieSoakTime:Decimal + FixedDieSoakStatus:int + DynamicDieSoakStatus:int + Command Timeout: 60000 + Example:GetHeaterSoak + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterSoak") + global GetHeaterSoak_Response + if not "GetHeaterSoak_Response" in globals(): GetHeaterSoak_Response = namedtuple("GetHeaterSoak_Response", "FixedWaferSoakTime,FixedWaferSoakStatus,DynamicWaferSoakTime,DynamicWaferSoakStatus,FixedDieSoakTime,DynamicDieSoakTime,FixedDieSoakStatus,DynamicDieSoakStatus") + return GetHeaterSoak_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),int(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),int(rsp[6]),int(rsp[7])) + +def SetHeaterSoak(FixedWaferSoakTime="", DynamicWaferSoakTime="", FixedDieSoakTime="", DynamicDieSoakTime=""): + """ + Sets the new soak time values. The unit of the values is seconds. If soak time + is actually running, it may be affected by the change. + API Status: published + Args: + FixedWaferSoakTime:int = 60 + DynamicWaferSoakTime:Decimal = -1 + FixedDieSoakTime:Decimal = -1 + DynamicDieSoakTime:Decimal = -1 + Command Timeout: 60000 + Example:SetHeaterSoak 60 + """ + MessageServerInterface.sendSciCommand("SetHeaterSoak",FixedWaferSoakTime,DynamicWaferSoakTime,FixedDieSoakTime,DynamicDieSoakTime) + + +def EnableHeaterStandby(Standby=""): + """ + Switches the power save (standby) mode of the device on or off. If the device is + in power save mode, setting and reading temperatures switches off the power save + mode automatically. + API Status: published + Args: + Standby:int = 1 + Returns: + RespStandby:int + Command Timeout: 60000 + Example:EnableHeaterStandby 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterStandby",Standby) + return int(rsp[0]) + +def ReadTemperatureChuckStatus(): + """ + Returns values of the temperature chuck status. The status byte gives + information about the current controller's action. The dew point sensor status + encapsulates information, if such a sensor is connected, and if the actual dew + point difference temperature is readable (active). It can be used for purge + control. Soak time left (in seconds) is used when soak time is actually running. + API Status: published + Returns: + Status:str + DPSensor:int + SoakTimeLeft:int + HasEcoMode:int + Command Timeout: 60000 + Example:ReadTemperatureChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTemperatureChuckStatus") + global ReadTemperatureChuckStatus_Response + if not "ReadTemperatureChuckStatus_Response" in globals(): ReadTemperatureChuckStatus_Response = namedtuple("ReadTemperatureChuckStatus_Response", "Status,DPSensor,SoakTimeLeft,HasEcoMode") + return ReadTemperatureChuckStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetTargetTemp(Unit=""): + """ + Reads the target temperature of the chuck. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetTargetTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetTargetTemp",Unit) + global GetTargetTemp_Response + if not "GetTargetTemp_Response" in globals(): GetTargetTemp_Response = namedtuple("GetTargetTemp_Response", "RespTemperature,RespUnit") + return GetTargetTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetThermoWindow(Window=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command sets the window for the target temperture which is the window in which a + station is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Args: + Window:Decimal = 1 + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:SetThermoWindow 2.0 + """ + rsp = MessageServerInterface.sendSciCommand("SetThermoWindow",Window) + return Decimal(rsp[0]) + +def GetThermoWindow(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command returns the current thermo window which is the window in which a station + is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:GetThermoWindow + """ + rsp = MessageServerInterface.sendSciCommand("GetThermoWindow") + return Decimal(rsp[0]) + +def SendThermoCommand(Command=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends a command string to the thermal chuck using the thermal chuck protocol and + returns the thermal chucks response as command response. This command can be + used to access thermal chuck features that are not exposed as standalone SCI + commands. Command is currently implemented for ERS and ATT chucks. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:SendThermoCommand RH + """ + rsp = MessageServerInterface.sendSciCommand("SendThermoCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadAuxStatus(AuxID=""): + """ + Returns the status of a single AUX site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + FlagsMode:int + Comp:str + PresetHeight:str + AuxSiteType:str + Command Timeout: 10000 + Example:ReadAuxStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxStatus",AuxID) + global ReadAuxStatus_Response + if not "ReadAuxStatus_Response" in globals(): ReadAuxStatus_Response = namedtuple("ReadAuxStatus_Response", "AuxIDEcho,FlagsMode,Comp,PresetHeight,AuxSiteType") + return ReadAuxStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ReadAuxPosition(AuxID="", Unit="", PosRef="", Comp=""): + """ + Returns the actual AUX sites position in X, Y and Z. With AUX ID set to 0, the + position is read for the chuck stage. If no AUX ID is given, it tries to read + the position from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + AuxIDEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadAuxPosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxPosition",AuxID,Unit,PosRef,Comp) + global ReadAuxPosition_Response + if not "ReadAuxPosition_Response" in globals(): ReadAuxPosition_Response = namedtuple("ReadAuxPosition_Response", "AuxIDEcho,X,Y,Z") + return ReadAuxPosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadAuxHeights(AuxID="", Unit=""): + """ + Returns the actual technology heights from an AUX site. If AUX ID is set to 0, + all response values are read from chuck stage. If no AUX ID is given, it tries + to read the heights from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadAuxHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxHeights",AuxID,Unit) + global ReadAuxHeights_Response + if not "ReadAuxHeights_Response" in globals(): ReadAuxHeights_Response = namedtuple("ReadAuxHeights_Response", "AuxIDEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadAuxHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetAuxMode(AuxID="", Overtravel=""): + """ + Modes manage the way a stage behaves when it is in contact height. AUX site mode + holds only a single flag. Flags can be turned on by using the value 1 or turned + off by using the value 0. If you do not want to change the flag - use the value + of 2. If AUX ID is set to 0, all flags are set for chuck stage. AUX site will + move an additional overtravel on every contact move. + API Status: published + Args: + AuxID:int = -1 + Overtravel:int = 2 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxMode 1 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxMode",AuxID,Overtravel) + return int(rsp[0]) + +def SetAuxHome(AuxID="", Mode="", Unit="", XValue="", YValue=""): + """ + Sets the AUX sites Home position in X and Y. It defines the origin of the AUX + sites coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHome",AuxID,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetAuxIndex(AuxID="", XValue="", YValue="", Unit=""): + """ + Sets the AUX sites index size. If AUX ID is set to 0, index size is set for + chuck stage. + API Status: published + Args: + AuxID:int = -1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxIndex",AuxID,XValue,YValue,Unit) + return int(rsp[0]) + +def SetAuxHeight(AuxID="", PresetHeight="", Mode="", Unit="", Value=""): + """ + Sets the AUX sites contact height and corresponding gaps for overtravel, + alignment and separation height. A contact height search gap for contact search + with edge sensor can also be set. This search gap is always identical for all + AUX sites. Without any optional parameters the command sets contact height to + the current position. + API Status: published + Args: + AuxID:int = -1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHeight",AuxID,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadAuxIndex(AuxID="", Unit=""): + """ + Returns the actual AUX sites index values. If AUX ID is set to 0, the index size + is read from chuck stage. If no AUX ID is given, it tries to read the index from + the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 10000 + Example:ReadAuxIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxIndex",AuxID,Unit) + global ReadAuxIndex_Response + if not "ReadAuxIndex_Response" in globals(): ReadAuxIndex_Response = namedtuple("ReadAuxIndex_Response", "AuxIDEcho,IndexX,IndexY") + return ReadAuxIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetAuxThetaHome(AuxID="", Mode="", Unit="", Position=""): + """ + Sets the AUX sites theta home position. It defines the origin of the AUX sites + theta coordinate system for later movements. If AUX ID is set to 0, theta home + position is set for chuck stage. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + Position:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxThetaHome 1 0 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxThetaHome",AuxID,Mode,Unit,Position) + return int(rsp[0]) + +def EnableOffset(Stage="", Enable="", Move=""): + """ + Enables or disables the Offset XY compensation for the selected stage. If the + compensation holds an offset different from zero, the chuck is automatically + moved the distance of the offset. The chuck also moves automatically to a safe + height. The move can be disabled by the third parameter. This may put the stage + outside the software fence. + API Status: published + Args: + Stage:str = "Chuck" + Enable:int = 1 + Move:int = 1 + Command Timeout: 60000 + Example:EnableOffset C 1 + """ + MessageServerInterface.sendSciCommand("EnableOffset",Stage,Enable,Move) + + +def SetOffset(Stage="", OffsetX="", OffsetY=""): + """ + Sets the offset values for the Offset XY compensation for the selected stage. + The changes take effect immediately. Note that the Offset XY compensation must + be enabled for the values to take effect. The compensation is enabled or + disabled using EnableOffset command. + API Status: published + Args: + Stage:str = "Chuck" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Command Timeout: 5000 + Example:SetOffset C 100000.0 0.0 + """ + MessageServerInterface.sendSciCommand("SetOffset",Stage,OffsetX,OffsetY) + + +def GetOffsetInfo(Stage=""): + """ + Gets information about the Offset XY compensation of the selected stage, + including the stored offset values and whether the compensation is enabled or + disabled. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Enable:int + OffsetX:Decimal + OffsetY:Decimal + Command Timeout: 5000 + Example:GetOffsetInfo C + """ + rsp = MessageServerInterface.sendSciCommand("GetOffsetInfo",Stage) + global GetOffsetInfo_Response + if not "GetOffsetInfo_Response" in globals(): GetOffsetInfo_Response = namedtuple("GetOffsetInfo_Response", "Enable,OffsetX,OffsetY") + return GetOffsetInfo_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetSwitchPosition(Stage="", AuxSite="", X="", Y=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the switch position of a stage. This is the position to move to if an aux + site gets active. This is only supported for the chuck and it's aux sites. Aux + index 0 means wafer site, 1 means aux site 1 and so on. + API Status: internal + Args: + Stage:str = "Chuck" + AuxSite:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 5000 + Example:SetSwitchPosition C 0 5000 5000 + """ + MessageServerInterface.sendSciCommand("SetSwitchPosition",Stage,AuxSite,X,Y) + + +def MoveAuxSite(AuxID=""): + """ + Moves the chuck to the position of a given AUX site. A safe height is used for + the move. If AUX ID is set to 0, the target of the move is the wafer site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Command Timeout: 60000 + Example:MoveAuxSite 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAuxSite",AuxID) + return int(rsp[0]) + +def SetAuxSiteCount(AuxSiteCount=""): + """ + Sets the number of available AUX sites. For preparing for example two cal + chucks, the count must be set to 2. For the changes to take effect the system + needs to be restarted. + API Status: published + Args: + AuxSiteCount:int = 0 + Command Timeout: 10000 + Example:SetAuxSiteCount 2 + """ + MessageServerInterface.sendSciCommand("SetAuxSiteCount",AuxSiteCount) + + +def GetAuxSiteCount(): + """ + Reads the number of available AUX sites and the ID of the actual active AUX + site. If this is 0, the chuck stage is currently active. + API Status: published + Returns: + AuxSiteCount:int + ActualAuxSite:int + Command Timeout: 10000 + Example:GetAuxSiteCount + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteCount") + global GetAuxSiteCount_Response + if not "GetAuxSiteCount_Response" in globals(): GetAuxSiteCount_Response = namedtuple("GetAuxSiteCount_Response", "AuxSiteCount,ActualAuxSite") + return GetAuxSiteCount_Response(int(rsp[0]),int(rsp[1])) + +def SetAuxSiteName(AuxID="", AuxSiteName=""): + """ + Sets the description of an AUX site. With AUX ID zero, the description of the + wafer site can be set. + API Status: published + Args: + AuxID:int = -1 + AuxSiteName:str = "" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteName 1 Aux site 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteName",AuxID,AuxSiteName) + return int(rsp[0]) + +def GetAuxSiteName(AuxID=""): + """ + This command reads the description of an AUX site. If AUX ID is set to 0, the + description of the chuck stage is given back. If no AUX ID is given, it tries to + read from the active site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + AuxSiteName:str + Command Timeout: 10000 + Example:GetAuxSiteName 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteName",AuxID) + global GetAuxSiteName_Response + if not "GetAuxSiteName_Response" in globals(): GetAuxSiteName_Response = namedtuple("GetAuxSiteName_Response", "AuxIDEcho,AuxSiteName") + return GetAuxSiteName_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def CleanProbeTip(AuxID=""): + """ + Starts a probe tip cleaning on the given AUX site. The cleaning algorithm is + dependent from the type of the AUX site and from the duration and the cleaning + count that is set in configuration. The cleaning algorithm includes both a move + to the pad site and a move back to the source site. + API Status: published + Args: + AuxID:str = "-1" + Returns: + AuxIDEcho:int + Command Timeout: 300000 + Example:CleanProbeTip 1 + """ + rsp = MessageServerInterface.sendSciCommand("CleanProbeTip",AuxID) + return int(rsp[0]) + +def SetAuxSiteType(AuxID="", AuxSiteType=""): + """ + Sets the type for a given AUX site. It depends on the type of the AUX site, if + there is a cleaning algorithm available. It is not possible to set the type of + the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + AuxSiteType:str = "AuxUnknown" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteType 1 G + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteType",AuxID,AuxSiteType) + return int(rsp[0]) + +def SetCleaningParams(AuxID="", Count="", Time=""): + """ + Sets the cleaning parameters for a given AUX site. It is not possible to set the + cleaning parameters of the wafer site (AUX site 0). If no AUX ID is given, it + tries to set the parameters of the active site. The cleaning count defines, + how much times the cleaning is performed repeatedly. The cleaning time defines, + how much milliseconds the needles wait in cleaning position during each + cleaning cycle. + API Status: published + Args: + AuxID:int = -1 + Count:int = 1 + Time:int = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetCleaningParams 1 5 1000 + """ + rsp = MessageServerInterface.sendSciCommand("SetCleaningParams",AuxID,Count,Time) + return int(rsp[0]) + +def GetCleaningParams(AuxID=""): + """ + Reads the cleaning parameters of a given AUX site. It is not possible to read + cleaning parameters of the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Count:int + Time:int + Remaining:int + Command Timeout: 30000 + Example:GetCleaningParams + """ + rsp = MessageServerInterface.sendSciCommand("GetCleaningParams",AuxID) + global GetCleaningParams_Response + if not "GetCleaningParams_Response" in globals(): GetCleaningParams_Response = namedtuple("GetCleaningParams_Response", "AuxIDEcho,Count,Time,Remaining") + return GetCleaningParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def UpdateAuxSitePositions(AuxID="", XOffset="", YOffset=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Rotate the switch, home, and fence positions to match the current chuck theta + angle and adjust Home/Switch by XY offset. Should only be used for Aux sites + that don't move theta. + API Status: internal + Args: + AuxID:int = -1 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 5000 + Example:UpdateAuxSitePositions 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateAuxSitePositions",AuxID,XOffset,YOffset) + return int(rsp[0]) + +def ResetCleaningPosition(AuxID="", OffsetX="", OffsetY=""): + """ + Resets the cleaning position to the beginning of the cleaning aux site (home). + API Status: published + Args: + AuxID:str = "-1" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:ResetCleaningPosition 5 + """ + rsp = MessageServerInterface.sendSciCommand("ResetCleaningPosition",AuxID,OffsetX,OffsetY) + return int(rsp[0]) + +def BnR_EchoData(ControllerID="", TestCmd=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Test Command for the Kernel Communication. It is like a ping command. The given + text string is returned unchanged. + API Status: internal + Args: + ControllerID:int = 1 + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:BnR_EchoData 1 Hello World + """ + rsp = MessageServerInterface.sendSciCommand("BnR_EchoData",ControllerID,TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_ReportKernelVersion(ControllerID="", Module=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual version information of the controller software. + The 'Version' value contains version number and revision level of the actual + implementation. The text string contains a + code description, version number and the revision date. + The 'Module' byte is optional (default is K). + API Status: internal + Args: + ControllerID:int = 1 + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:BnR_ReportKernelVersion 1 K + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReportKernelVersion",ControllerID,Module) + global BnR_ReportKernelVersion_Response + if not "BnR_ReportKernelVersion_Response" in globals(): BnR_ReportKernelVersion_Response = namedtuple("BnR_ReportKernelVersion_Response", "Version,Description") + return BnR_ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetStationType(ControllerID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns information about the connected station. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StationType:str + Type:str + Command Timeout: 5000 + Example:BnR_GetStationType 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStationType",ControllerID) + global BnR_GetStationType_Response + if not "BnR_GetStationType_Response" in globals(): BnR_GetStationType_Response = namedtuple("BnR_GetStationType_Response", "StationType,Type") + return BnR_GetStationType_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_ResetController(ControllerID="", Mode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the BnR controller. + API Status: internal + Args: + ControllerID:int = 1 + Mode:str = "X" + Command Timeout: 10000 + Example:BnR_ResetController 1 + """ + MessageServerInterface.sendSciCommand("BnR_ResetController",ControllerID,Mode) + + +def BnR_SetOutput(ControllerID="", Channel="", State="", CycleTime=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + State:int = 0 + CycleTime:int = 0 + Command Timeout: 5000 + Example:BnR_SetOutput 1 1000 1 2000 + """ + MessageServerInterface.sendSciCommand("BnR_SetOutput",ControllerID,Channel,State,CycleTime) + + +def BnR_GetOutput(ControllerID="", Channel=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an output channel. By using the string identifier DO_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + Returns: + State:int + AllOutputs:str + Command Timeout: 5000 + Example:BnR_GetOutput 1 DO_WaferVacuum + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetOutput",ControllerID,Channel) + global BnR_GetOutput_Response + if not "BnR_GetOutput_Response" in globals(): BnR_GetOutput_Response = namedtuple("BnR_GetOutput_Response", "State,AllOutputs") + return BnR_GetOutput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetInput(ControllerID="", Channel=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an input channel. By using the string identifier DI_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DI_MotorPower" + Returns: + State:int + AllInputs:str + Command Timeout: 5000 + Example:BnR_GetInput 1 DI_MotorPower + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInput",ControllerID,Channel) + global BnR_GetInput_Response + if not "BnR_GetInput_Response" in globals(): BnR_GetInput_Response = namedtuple("BnR_GetInput_Response", "State,AllInputs") + return BnR_GetInput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_SetAnalogOutput(ControllerID="", Channel="", OutputPercent=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an analog output channel to a given value. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + OutputPercent:Decimal = 50 + Command Timeout: 5000 + Example:BnR_SetAnalogOutput 1 AO_PurgeDewPoint 50 + """ + MessageServerInterface.sendSciCommand("BnR_SetAnalogOutput",ControllerID,Channel,OutputPercent) + + +def BnR_GetAnalogIO(ControllerID="", Channel=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current value of an analog output or input. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + Returns: + Value:Decimal + UnderOverflow:int + Command Timeout: 5000 + Example:BnR_GetAnalogIO 1 AO_PurgeDewPoint + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAnalogIO",ControllerID,Channel) + global BnR_GetAnalogIO_Response + if not "BnR_GetAnalogIO_Response" in globals(): BnR_GetAnalogIO_Response = namedtuple("BnR_GetAnalogIO_Response", "Value,UnderOverflow") + return BnR_GetAnalogIO_Response(Decimal(rsp[0]),int(rsp[1])) + +def BnR_GetStartupStatus(ControllerID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the startup status of the BnR controller to determine if the controller + is properly booted or still starting. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StartupStatus:str + AdditionalStatusInfo:str + Command Timeout: 5000 + Example:BnR_GetStartupStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStartupStatus",ControllerID) + global BnR_GetStartupStatus_Response + if not "BnR_GetStartupStatus_Response" in globals(): BnR_GetStartupStatus_Response = namedtuple("BnR_GetStartupStatus_Response", "StartupStatus,AdditionalStatusInfo") + return BnR_GetStartupStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_CreateSdmSystemDump(ControllerID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Creates a Sdm System Dump file on the B&R flash + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 60000 + Example:BnR_CreateSdmSystemDump + """ + MessageServerInterface.sendSciCommand("BnR_CreateSdmSystemDump",ControllerID) + + +def BnR_GetControllerData(ControllerID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets controller data from the B&R controller. Currently used for init + information. + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 10000 + Example:BnR_GetControllerData 1 + """ + MessageServerInterface.sendSciCommand("BnR_GetControllerData",ControllerID) + + +def BnR_WriteMessage(ControllerID="", MessageType="", Message=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to write a (native) message to Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Message:str = "" + Command Timeout: 5000 + Example:BnR_WriteMessage 1 mtCryoLoader SampleMessage + """ + MessageServerInterface.sendSciCommand("BnR_WriteMessage",ControllerID,MessageType,Message) + + +def BnR_ReadMessage(ControllerID="", MessageType=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to read a (native) message from Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Returns: + Message:str + Command Timeout: 5000 + Example:BnR_ReadMessage 1 mtCryoLoader + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadMessage",ControllerID,MessageType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetDataIterator(ControllerID="", ShowAll=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters + and requires the BnR_GetNextDatum command. + API Status: internal + Args: + ControllerID:int = 1 + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 5000 + Example:BnR_GetDataIterator 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDataIterator",ControllerID,ShowAll) + global BnR_GetDataIterator_Response + if not "BnR_GetDataIterator_Response" in globals(): BnR_GetDataIterator_Response = namedtuple("BnR_GetDataIterator_Response", "IdentityToken,SizeNoAll") + return BnR_GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def BnR_GetNextDatum(ControllerID="", IdentityToken=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + ControllerID:int = 1 + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:BnR_GetNextDatum 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetNextDatum",ControllerID,IdentityToken) + global BnR_GetNextDatum_Response + if not "BnR_GetNextDatum_Response" in globals(): BnR_GetNextDatum_Response = namedtuple("BnR_GetNextDatum_Response", "IsLastDatum,DatumCode,PathNameDescrValue") + return BnR_GetNextDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def BnR_SetDatum(ControllerID="", PathNameAndValue=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + ControllerID:int = 1 + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:BnR_SetDatum 1 Chuck_XAxisData:CurrentMaximal:70 + """ + MessageServerInterface.sendSciCommand("BnR_SetDatum",ControllerID,PathNameAndValue) + + +def BnR_GetDatum(ControllerID="", PathName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + ControllerID:int = 1 + PathName:str = "" + Returns: + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:BnR_GetDatum 1 Chuck_XAxisData:CurrentMaximal + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDatum",ControllerID,PathName) + global BnR_GetDatum_Response + if not "BnR_GetDatum_Response" in globals(): BnR_GetDatum_Response = namedtuple("BnR_GetDatum_Response", "DatumCode,ValueDesc") + return BnR_GetDatum_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_DoInternalTask(ControllerID="", Task="", PCmdInt1="", PCmdInt2=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes an internal BnR Task + API Status: internal + Args: + ControllerID:int = 1 + Task:str = "" + PCmdInt1:int = 0 + PCmdInt2:int = 0 + Returns: + RspInt:int + RspString:str + Command Timeout: 10000 + Example:BnR_DoInternalTask 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_DoInternalTask",ControllerID,Task,PCmdInt1,PCmdInt2) + global BnR_DoInternalTask_Response + if not "BnR_DoInternalTask_Response" in globals(): BnR_DoInternalTask_Response = namedtuple("BnR_DoInternalTask_Response", "RspInt,RspString") + return BnR_DoInternalTask_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetPosition(Stage="", Unit=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current positions for the X,Y,Z (or T) axis for the specified stage + as well as the commanded positions. + API Status: internal + Args: + Stage:str = "Chuck" + Unit:str = "Microns" + Returns: + XorT:Decimal + Y:Decimal + Z:Decimal + CommandedXorT:Decimal + CommandedY:Decimal + CommandedZ:Decimal + Command Timeout: 5000 + Example:BnR_GetPosition 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetPosition",Stage,Unit) + global BnR_GetPosition_Response + if not "BnR_GetPosition_Response" in globals(): BnR_GetPosition_Response = namedtuple("BnR_GetPosition_Response", "XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ") + return BnR_GetPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def BnR_Move(Stage="", XValue="", YValue="", VelX="", VelY="", WaitFinished=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a XY movement for a specified stage. This can be either a + blocking or non blocking move. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + VelX:Decimal = 0 + VelY:Decimal = 0 + WaitFinished:int = 1 + Returns: + X:Decimal + Y:Decimal + Command Timeout: 60000 + Example:BnR_Move 1 C 5000 5000 Z 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_Move",Stage,XValue,YValue,VelX,VelY,WaitFinished) + global BnR_Move_Response + if not "BnR_Move_Response" in globals(): BnR_Move_Response = namedtuple("BnR_Move_Response", "X,Y") + return BnR_Move_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def BnR_MoveZ(Stage="", ZValue="", Vel="", Dec="", WaitFinished=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the stage Z axis to a new position. + API Status: internal + Args: + Stage:str = "Chuck" + ZValue:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + Z:Decimal + Command Timeout: 600000 + Example:BnR_MoveZ 1 C 12000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZ",Stage,ZValue,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_ScanMoveZ(ControllerID="", Stage="", ZDistance="", TriggerEveryNthCycle="", Vel=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a scan movement of the Z axis that sets a digital output + every couple microns to trigger e.g. a camera. After the move is finished, the + command returns a list of Z heights at which the digital output was set. + API Status: internal + Args: + ControllerID:int = 1 + Stage:str = "Chuck" + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 2 + Vel:Decimal = 10 + Command Timeout: 300000 + Example:BnR_ScanMoveZ 1 C 1000 6 10 + """ + MessageServerInterface.sendSciCommand("BnR_ScanMoveZ",ControllerID,Stage,ZDistance,TriggerEveryNthCycle,Vel) + + +def BnR_MoveT(TValue="", Vel="", WaitFinished=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes a movement of the theta axis, either blocking or non blocking + API Status: internal + Args: + TValue:Decimal = 0 + Vel:Decimal = 0 + WaitFinished:int = 1 + Returns: + T:Decimal + Command Timeout: 60000 + Example:BnR_MoveT 1 1.003 10 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveT",TValue,Vel,WaitFinished) + return Decimal(rsp[0]) + +def BnR_StopAxis(Stage="", FlagsStop=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops 1... all axes of a stage + API Status: internal + Args: + Stage:str = "Chuck" + FlagsStop:int = 15 + Command Timeout: 5000 + Example:BnR_StopAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_StopAxis",Stage,FlagsStop) + + +def BnR_InitAxis(Stage="", FlagsInit="", FlagsDirection="", FlagsInitInPlace="", LowLimitX="", LowLimitY="", LowLimitZ="", LowLimitTh="", InitInPlaceMoveRangeX="", InitInPlaceMoveRangeY="", InitInPlaceMoveRangeZ="", InitInPlaceMoveRangeTh=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Machine Coordinate System: X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - + _FlagsInitInPlace_: X, Y, Z, Theta All flags can be accessed by indirect + members. Initializes the stage and resets current coordinate system. Should be + used only in cases when the reported coordinates do not correspond to real + position of mechanics. Init in Place performs the initialization without any + movements. + API Status: internal + Args: + Stage:str = "Chuck" + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsInitInPlace:int = 0 + LowLimitX:Decimal = 0 + LowLimitY:Decimal = 0 + LowLimitZ:Decimal = 0 + LowLimitTh:Decimal = 0 + InitInPlaceMoveRangeX:Decimal = 0 + InitInPlaceMoveRangeY:Decimal = 0 + InitInPlaceMoveRangeZ:Decimal = 0 + InitInPlaceMoveRangeTh:Decimal = 0 + Command Timeout: 300000 + Example:BnR_InitAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_InitAxis",Stage,FlagsInit,FlagsDirection,FlagsInitInPlace,LowLimitX,LowLimitY,LowLimitZ,LowLimitTh,InitInPlaceMoveRangeX,InitInPlaceMoveRangeY,InitInPlaceMoveRangeZ,InitInPlaceMoveRangeTh) + + +def BnR_GetAxisState(Stage="", Axis=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of an axis (disabled/standstill/errorstop/stoppin + g/homing/continuousmotion/discretemotion/synchronizedmotion) + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + State:str + AdditionalStateInfo:str + Command Timeout: 5000 + Example:BnR_GetAxisState 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisState",Stage,Axis) + global BnR_GetAxisState_Response + if not "BnR_GetAxisState_Response" in globals(): BnR_GetAxisState_Response = namedtuple("BnR_GetAxisState_Response", "State,AdditionalStateInfo") + return BnR_GetAxisState_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetAxisStatus(Stage="", Axis=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns some axis status information + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + Initialized:int + PositiveEndlimit:int + NegativeEndlimit:int + Command Timeout: 5000 + Example:BnR_GetAxisStatus 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisStatus",Stage,Axis) + global BnR_GetAxisStatus_Response + if not "BnR_GetAxisStatus_Response" in globals(): BnR_GetAxisStatus_Response = namedtuple("BnR_GetAxisStatus_Response", "Initialized,PositiveEndlimit,NegativeEndlimit") + return BnR_GetAxisStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def BnR_SetQuietMode(Stage="", QuietMode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to enable the quiet mode for a stage (quiet turns motors powerless) + API Status: internal + Args: + Stage:str = "Chuck" + QuietMode:int = 0 + Command Timeout: 5000 + Example:BnR_SetQuietMode 1 C 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetQuietMode",Stage,QuietMode) + + +def BnR_GetQuietMode(Stage=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to query the quiet mode for a stage + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + QuietMode:int + Command Timeout: 5000 + Example:BnR_GetQuietMode 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetQuietMode",Stage) + return int(rsp[0]) + +def BnR_GetInternalAxisInfo(Stage="", Axis="", InfoType=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns various axis information, dependent on the InfoType + parameter + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + InfoType:str = "StallInfo" + Returns: + RspString:str + Command Timeout: 5000 + Example:BnR_GetInternalAxisInfo 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInternalAxisInfo",Stage,Axis,InfoType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetWiringTesterData(Stage="", Axis=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to get various information required for the BnR wiring tester tool. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + STIn_ModuleOK:int + STIn_LifeCnt:int + STIn_DrvOK:int + STIn_OvertemperatureError:int + STIn_CurrentError:int + STIn_OvercurrentError:int + STIn_RefPulsePos:int + STIn_RefPulseCnt:int + STIn_ModulePowerSupplyError:int + STOut_SetTime:int + STOut_MotorStep0:int + STOut_DriveEnable:int + STOut_BoostCurrent:int + STOut_StandStillCurrent:int + STOut_ClearError:int + CMIn_ModuleOK:int + CMIn_SDCLifeCount:int + CMIn_Encoder:int + CMIn_EncoderTimeValid:int + CMIn_DigitalInput1:int + CMIn_DigitalInput2:int + CMIn_BWChannelA:int + CMIn_BWChannelB:int + CMIn_PowerSupply2:int + CMOut_QuitChannelA:int + CMOut_QuitChannelB:int + SWAxisErrorID:int + SWAxisErrorDesc:str + Command Timeout: 5000 + Example:BnR_GetWiringTesterData 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetWiringTesterData",Stage,Axis) + global BnR_GetWiringTesterData_Response + if not "BnR_GetWiringTesterData_Response" in globals(): BnR_GetWiringTesterData_Response = namedtuple("BnR_GetWiringTesterData_Response", "STIn_ModuleOK,STIn_LifeCnt,STIn_DrvOK,STIn_OvertemperatureError,STIn_CurrentError,STIn_OvercurrentError,STIn_RefPulsePos,STIn_RefPulseCnt,STIn_ModulePowerSupplyError,STOut_SetTime,STOut_MotorStep0,STOut_DriveEnable,STOut_BoostCurrent,STOut_StandStillCurrent,STOut_ClearError,CMIn_ModuleOK,CMIn_SDCLifeCount,CMIn_Encoder,CMIn_EncoderTimeValid,CMIn_DigitalInput1,CMIn_DigitalInput2,CMIn_BWChannelA,CMIn_BWChannelB,CMIn_PowerSupply2,CMOut_QuitChannelA,CMOut_QuitChannelB,SWAxisErrorID,SWAxisErrorDesc") + return BnR_GetWiringTesterData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),int(rsp[14]),int(rsp[15]),int(rsp[16]),int(rsp[17]),int(rsp[18]),int(rsp[19]),int(rsp[20]),int(rsp[21]),int(rsp[22]),int(rsp[23]),int(rsp[24]),int(rsp[25]),int(rsp[26]),str("" if len(rsp) < 28 else ' '.join(rsp[27:]))) + +def BnR_MoveAxis(Stage="", Axis="", Value="", Vel="", Dec="", WaitFinished=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows moving a single axis to and e.g. in case of X does not + trigger a Y movement + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Value:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + PositionAfterMove:Decimal + Command Timeout: 60000 + Example:BnR_MoveAxis 1 C X 20000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveAxis",Stage,Axis,Value,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_MoveZCombined(ChuckTargetZ="", WaitFinished="", ForcedAbsVelocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move Chuck-Z and (by fixed factor) Scope X, Y and Z + API Status: internal + Args: + ChuckTargetZ:Decimal = 0 + WaitFinished:int = 1 + ForcedAbsVelocity:int = 0 + Returns: + ChuckZ:Decimal + ScopeX:Decimal + ScopeY:Decimal + ScopeZ:Decimal + Command Timeout: 600000 + Example:BnR_MoveZCombined 1 17592.5 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZCombined",ChuckTargetZ,WaitFinished,ForcedAbsVelocity) + global BnR_MoveZCombined_Response + if not "BnR_MoveZCombined_Response" in globals(): BnR_MoveZCombined_Response = namedtuple("BnR_MoveZCombined_Response", "ChuckZ,ScopeX,ScopeY,ScopeZ") + return BnR_MoveZCombined_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def BnR_StepMove(Stage="", ZDown="", XValue="", YValue="", ZUp=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command does a combined Z-XY-Z- move completely on the BnR-controller + without WinKernel interaction. This is a part of an ongoing optimization. + API Status: internal + Args: + Stage:str = "Chuck" + ZDown:Decimal = 0 + XValue:Decimal = 0 + YValue:Decimal = 0 + ZUp:Decimal = 0 + Command Timeout: 60000 + Example:BnR_StepMove 1 C 250 1000 1000 250 + """ + MessageServerInterface.sendSciCommand("BnR_StepMove",Stage,ZDown,XValue,YValue,ZUp) + + +def BnR_SearchEdgeSensor(SearchEndPos="", Velocity=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a search move until the search end position is reached or the edge + sensor triggers. If the edge sensor triggers during the move, the trigger + position is returned.Otherwise, an edge sensor not found error is returned. + API Status: internal + Args: + SearchEndPos:Decimal = 0 + Velocity:Decimal = 0 + Returns: + EdgeSensorTriggerPos:Decimal + Command Timeout: 300000 + Example:BnR_SearchEdgeSensor 3000 10 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_SearchEdgeSensor",SearchEndPos,Velocity) + return Decimal(rsp[0]) + +def BnR_GetTraceData(ControllerID=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a collection of trace data + API Status: internal + Args: + ControllerID:int = 1 + Returns: + Data:str + Command Timeout: 5000 + Example:BnR_GetTraceData 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetTraceData",ControllerID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_SetTraceMode(ControllerID="", Mode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Commands sets the trace mode + API Status: internal + Args: + ControllerID:int = 1 + Mode:int = 0 + Command Timeout: 5000 + Example:BnR_SetTraceMode 1 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetTraceMode",ControllerID,Mode) + + +def BnR_WriteAxisModuleRegister(Stage="", Axis="", MotorModule="", RegisterName="", Value=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to change a module register value without controller restart + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Value:int = 0 + Command Timeout: 5000 + Example:BnR_WriteAxisModuleRegister 1 C X 1 ConfigOutput03 70 + """ + MessageServerInterface.sendSciCommand("BnR_WriteAxisModuleRegister",Stage,Axis,MotorModule,RegisterName,Value) + + +def BnR_ReadAxisModuleRegister(Stage="", Axis="", MotorModule="", RegisterName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to get any desired module register value + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Returns: + Value:int + Command Timeout: 5000 + Example:BnR_ReadAxisModuleRegister 1 C X 1 ConfigOutput03 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadAxisModuleRegister",Stage,Axis,MotorModule,RegisterName) + return int(rsp[0]) + +def ProcessStationGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns process station status (UNKNOWN, IDLE, BUSY, ERROR, PAUSED, Not + Initialized) and error code with error message when error. + API Status: internal + Returns: + Status:str + SubstratePresent:int + LastError:int + UseLoaderModule:int + WaferSizes:str + StatusMessage:str + IsLoaderJobRunning:int + Command Timeout: 25000 + Example:ProcessStationGetStatus + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetStatus") + global ProcessStationGetStatus_Response + if not "ProcessStationGetStatus_Response" in globals(): ProcessStationGetStatus_Response = namedtuple("ProcessStationGetStatus_Response", "Status,SubstratePresent,LastError,UseLoaderModule,WaferSizes,StatusMessage,IsLoaderJobRunning") + return ProcessStationGetStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ProcessStationInit(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initialize process station machine. This is not the prober init it is a fast + program initialization. Only applies to fully auto systems. + API Status: internal + Command Timeout: 2400000 + Example:ProcessStationInit + """ + MessageServerInterface.sendSciCommand("ProcessStationInit") + + +def ProcessStationFinish(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Finishes a process station process. This resets some internal test information + for the probe station. Some data is only reset in case this command is sent + after the last wafer in the job was tested. Only applies to fully auto systems. + API Status: internal + Command Timeout: 7500000 + Example:ProcessStationFinish + """ + MessageServerInterface.sendSciCommand("ProcessStationFinish") + + +def ProcessStationPrepareForLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command moves the chuck of the probe station to the secondary load position and + if available also checks the table level sensor. Only applies to fully auto + systems. + API Status: internal + Command Timeout: 120000 + Example:ProcessStationPrepareForLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForLoad") + + +def ProcessStationLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck out of the load position and checks if a wafer is placed. Only + applies to fully auto systems. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadComplete") + + +def ProcessStationPrepareForUnLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should do whatever is necessary to prepare the current wafer for + unload. Typically this includes things such as moving lift pins and opening + doors. + API Status: internal + Command Timeout: 1000000 + Example:ProcessStationPrepareForUnLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForUnLoad") + + +def ProcessStationUnLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should so whatever is necessary after a wafer is unloaded. This may + for example include closing doors. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationUnLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationUnLoadComplete") + + +def ProcessStationLoadRecipe(ForceReOpenProject="", ProjectFileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The recipe is a zipped archive that includes all project data. This command + tells the device to load the recipe. + API Status: internal + Args: + ForceReOpenProject:int = 0 + ProjectFileName:str = "" + Command Timeout: 60000 + Example:ProcessStationLoadRecipe 1 SampleProject.spp + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadRecipe",ForceReOpenProject,ProjectFileName) + + +def ProcessStationVerifyRecipe(ProjectFileName=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Requests that the device verify that the recipe given can be executed on the + device. It should check that the recipe is correctly formed and conforms to the + hardware of the device. It should not check for transient things such as whether + there is sufficient media or facilities available. those kinds of checks should + be done in PrepareForProcess + API Status: internal + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 60000 + Example:ProcessStationVerifyRecipe SampleProject.spp + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationVerifyRecipe",ProjectFileName) + global ProcessStationVerifyRecipe_Response + if not "ProcessStationVerifyRecipe_Response" in globals(): ProcessStationVerifyRecipe_Response = namedtuple("ProcessStationVerifyRecipe_Response", "Verified,ErrorDescription") + return ProcessStationVerifyRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ProcessStationStartRecipe(CurrentWaferInJob="", TotalWafersInJob=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells VeloxPro to start the current recipe. The station will switch to error if + an error occurs. If VeloxPro recipe execution is currently paused, this command + tells the system to continue execution. + API Status: internal + Args: + CurrentWaferInJob:int = -1 + TotalWafersInJob:int = -1 + Command Timeout: 25000 + Example:ProcessStationStartRecipe 1 + """ + MessageServerInterface.sendSciCommand("ProcessStationStartRecipe",CurrentWaferInJob,TotalWafersInJob) + + +def ProcessStationStopRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the device to stop the current recipe. The station will switch to error if + an error occurs. + API Status: internal + Command Timeout: 25000 + Example:ProcessStationStopRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationStopRecipe") + + +def ProcessStationRecoverError(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the module to do whatever is necessary to recover from an error condition. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationRecoverError + """ + MessageServerInterface.sendSciCommand("ProcessStationRecoverError") + + +def ProcessStationGetWaferResult(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get substrate information from process station controller application. + API Status: internal + Returns: + Result:str + PercentDone:Decimal + AllowSkipWafer:int + TestInformation:str + Command Timeout: 25000 + Example:ProcessStationGetWaferResult + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetWaferResult") + global ProcessStationGetWaferResult_Response + if not "ProcessStationGetWaferResult_Response" in globals(): ProcessStationGetWaferResult_Response = namedtuple("ProcessStationGetWaferResult_Response", "Result,PercentDone,AllowSkipWafer,TestInformation") + return ProcessStationGetWaferResult_Response(str(rsp[0]),Decimal(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def QueryWaferInfo(): + """ + Returns information about the wafer that is currently on the probe station. It + will return an error when there is no wafer currently on the chuck. + API Status: published + Returns: + Size:int + Angle:Decimal + ID:str + LotID:str + ProductID:str + Command Timeout: 25000 + Example:QueryWaferInfo + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferInfo") + global QueryWaferInfo_Response + if not "QueryWaferInfo_Response" in globals(): QueryWaferInfo_Response = namedtuple("QueryWaferInfo_Response", "Size,Angle,ID,LotID,ProductID") + return QueryWaferInfo_Response(int(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ProcessStationPauseRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the process station to PAUSE mode + API Status: internal + Command Timeout: 25000 + Example:ProcessStationPauseRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationPauseRecipe") + + +def GetProbingStatus(): + """ + Retrieves the current status of the prober. If probing status is AtFirstDie the + tester can take control. + API Status: published + Returns: + Status:str + Command Timeout: 25000 + Example:GetProbingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetProbingStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedProbing(): + """ + Tells the prober to proceed the recipe when current status is AtFirstDie. + API Status: published + Command Timeout: 25000 + Example:ProceedProbing + """ + MessageServerInterface.sendSciCommand("ProceedProbing") + + +def GetCassetteStatus(Cassette=""): + """ + Provides all available wafer information. It returns a set of data for each + wafer in either cassette. The data contains the cassette and the slot number + where the wafer is located, the status of the wafer, and identification + information. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 25000 + Example:GetCassetteStatus 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def QueryWaferID(Module="", Slot=""): + """ + Queries the wafer ID of a given module and slot. + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryWaferID Cassette1 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferID",Module,Slot) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def UpdateWaferID(Module="", Slot="", ID=""): + """ + Overrides the wafer ID of the given module and slot. If the wafer id is empty + and the module is a Loadport, the id will be read by the idreader if possible. + This process behaves as follows: - the current wafer id is reset - if the read- + wafer-process would be delayed (e.g. there is already a wafer on the idreader) + the process will be aborted and an error will be returned - if the id- + reading fails, the process behaves like a normal inventory triggered by the UI: + skip (returns success), abort (returns error) or "ask user". It is + recomended to use either skip or abort for remote id reading. If the + module is a Loadport and the slot is set to -1, a regular inventory will be + triggered. This behaves similar to an inventory triggered by the UI: The ID + won't be reset and already scanned wafers won't be reset. Setting an ID + explicitly with slot -1 is an error: - Okay, read id of wafer in slot 3 even if + it is already set: UpdateWaferID Cassette1 3 - Okay, set id of wafer in slot 3 + to XYZ123: UpdateWaferID Cassette1 3 XYZ123 - Okay, start full inventory: + UpdateWaferID Cassette1 -1 - Error: UpdateWaferID Cassette1 -1 XYZ123 + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + ID:str = "" + Command Timeout: 1500000 + Example:UpdateWaferID Cassette1 1 Wafer01 + """ + MessageServerInterface.sendSciCommand("UpdateWaferID",Module,Slot,ID) + + +def ConfirmRecipe(ProjectFileName=""): + """ + Queries whether the given project/flow name is a valid project/flow at the probe + station. Using file and folder names without white spaces is recommended. For + folders and files whith white spaces use quotation marks for the path. Example + for using white spaces: ConfirmRecipe + "C:/Users/Public/Documents/Velox/Projects/White Spaces.spp" + API Status: published + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 25000 + Example:ConfirmRecipe C:/Temp/Test.spp + """ + rsp = MessageServerInterface.sendSciCommand("ConfirmRecipe",ProjectFileName) + global ConfirmRecipe_Response + if not "ConfirmRecipe_Response" in globals(): ConfirmRecipe_Response = namedtuple("ConfirmRecipe_Response", "Verified,ErrorDescription") + return ConfirmRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def StartWaferJob(RecipeName="", WaferIDs=""): + """ + Creates and starts a new job by specifying the flow/spp file and the wafers to + be included in the job. + API Status: published + Args: + RecipeName:str = "" + WaferIDs:str = "" + Returns: + JobID:str + Command Timeout: 25000 + Example:StartWaferJob C:/Users/Public/Documents/Velox/Test.flow 1;1 2;1 + """ + rsp = MessageServerInterface.sendSciCommand("StartWaferJob",RecipeName,WaferIDs) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetJobParams(JobID=""): + """ + Get job information for a specific job ID including the flow file and the list + of wafers. + API Status: published + Args: + JobID:str = "" + Returns: + RecipeName:str + WaferIDs:str + Command Timeout: 25000 + Example:GetJobParams 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetJobParams",JobID) + global GetJobParams_Response + if not "GetJobParams_Response" in globals(): GetJobParams_Response = namedtuple("GetJobParams_Response", "RecipeName,WaferIDs") + return GetJobParams_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def JobStatus(JobID=""): + """ + Retrieves the status of a specific job by its ID. If the status is ErrorWaiting, + an error string is returned. + API Status: published + Args: + JobID:str = "" + Returns: + Status:str + JobStatusInfo:str + Command Timeout: 25000 + Example:JobStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("JobStatus",JobID) + global JobStatus_Response + if not "JobStatus_Response" in globals(): JobStatus_Response = namedtuple("JobStatus_Response", "Status,JobStatusInfo") + return JobStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AbortJob(JobID="", Unload=""): + """ + Aborts the job given by the job ID. The status of the job will be set to + "Aborted". The "Unload" parameter defines whether the wafer remains on the chuck + or not. + API Status: published + Args: + JobID:str = "" + Unload:int = 0 + Command Timeout: 25000 + Example:AbortJob 2 1 + """ + MessageServerInterface.sendSciCommand("AbortJob",JobID,Unload) + + +def ProcessStationCloseApplication(NoUserPrompt=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the VeloxPro application. + API Status: internal + Args: + NoUserPrompt:int = 0 + Command Timeout: 25000 + Example:ProcessStationCloseApplication + """ + MessageServerInterface.sendSciCommand("ProcessStationCloseApplication",NoUserPrompt) + + +def UnloadWafer(): + """ + Unolads a Wafer from the chuck to its origin. If no origin is known, the first + free Slot of a loadport will be chosen. A Wafer should be on the chuck. + API Status: published + Command Timeout: 600000 + Example:UnloadWafer + """ + MessageServerInterface.sendSciCommand("UnloadWafer") + + +def GetJobList(JobType=""): + """ + Returns a string for the relevant JobIDs. + API Status: published + Args: + JobType:str = "Probing" + Returns: + GetJobList:str + Command Timeout: 25000 + Example:GetJobList + """ + rsp = MessageServerInterface.sendSciCommand("GetJobList",JobType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedJob(ProceedJob=""): + """ + Continues a job that is waiting on an error (Job Status ErrorWaiting). The mode + determines how the job continues. + API Status: published + Args: + ProceedJob:str = "AbortJob" + Command Timeout: 25000 + Example:ProceedJob AbortJob + """ + MessageServerInterface.sendSciCommand("ProceedJob",ProceedJob) + + +def QueryCassetteID(Cassette=""): + """ + Returns the ID of a cassette that is placed on the load port. The loadport and + the cassette must support RFID reading (additional hardware needed). + API Status: published + Args: + Cassette:int = 1 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryCassetteID 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryCassetteID",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DockCassette(LoadPortId="", DockUndock=""): + """ + Docks or undocks a cassette which is placed on a LoadPort (CM300 only). It will + return an error if no cassette is placed: the LoadPort is not ready/available or + the docking failed. The command will do the docking/undocking and return when + this is done. + API Status: published + Args: + LoadPortId:int = 0 + DockUndock:int = 0 + Command Timeout: 60000 + Example:DockCassette 1 1 + """ + MessageServerInterface.sendSciCommand("DockCassette",LoadPortId,DockUndock) + + +def LoadWafer(LoadportID="", SlotID="", AlignmentAngle=""): + """ + Load a wafer from a given loadport onto the prober. If no slot id is defined, + the first available wafer with the lowest slot id will be loaded. If no loadport + is defined, it will try to use the first loadport. If there is no suitable + wafer, it will try the second. Returns an error if the loading process fails or + no suitable wafer is found. To define an alignment angle and still use the + "autoselect" behaviour, use -1 for loadport and slot. + API Status: published + Args: + LoadportID:int = -1 + SlotID:int = -1 + AlignmentAngle:Decimal = 0 + Command Timeout: 600000 + Example:LoadWafer 1 1 + """ + MessageServerInterface.sendSciCommand("LoadWafer",LoadportID,SlotID,AlignmentAngle) + + +def UpdateCassetteStatus(Cassette=""): + """ + Updates the cassette status with a simple scan. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 1200000 + Example:UpdateCassetteStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def TransportWafer(SourceLocation="", SourceSlot="", DestinationLocation="", DestinationSlot=""): + """ + Transport a wafer from one location to another. This command behaves like the + wafer-transport inside the LoaderModule. The Slot must always be set. + API Status: published + Args: + SourceLocation:str = "Cassette1" + SourceSlot:int = 1 + DestinationLocation:str = "Cassette1" + DestinationSlot:int = 1 + Command Timeout: 600000 + Example:TransportWafer Cassette1 1 PreAligner 1 + """ + MessageServerInterface.sendSciCommand("TransportWafer",SourceLocation,SourceSlot,DestinationLocation,DestinationSlot) + + +def ProcessWafer(Module="", ProcessParam=""): + """ + "Process" a wafer on a given location. What is done depends on the current + station: - IDReader: read ID - PreAligner: align wafer (alignment angle + mandatory) - Prober: Perform current recipe + API Status: published + Args: + Module:str = "Cassette1" + ProcessParam:str = "" + Command Timeout: 100000 + Example:ProcessWafer PreAligner 90.0 + """ + MessageServerInterface.sendSciCommand("ProcessWafer",Module,ProcessParam) + + +def GetIDReaderPos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the IDReader + API Status: internal + Returns: + IDReaderPos:str + Command Timeout: 2000 + """ + rsp = MessageServerInterface.sendSciCommand("GetIDReaderPos") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetIDReaderPos(IDReaderPos=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the current position of the IDReader + API Status: internal + Args: + IDReaderPos:str = "Bottom" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetIDReaderPos",IDReaderPos) + + +def CryoCommand(Process=""): + """ + CryoCommand controls automatic cooling and warm up. + API Status: published + Args: + Process:str = "CD" + Command Timeout: 60000 + Example:CryoCommand CD + """ + MessageServerInterface.sendSciCommand("CryoCommand",Process) + + +def CryoReadTemperature(Stage=""): + """ + Reads the current temperature from sensor chuck or shield. + API Status: published + Args: + Stage:str = "C" + Returns: + Temp:Decimal + Command Timeout: 10000 + Example:CryoReadTemperature C + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadTemperature",Stage) + return Decimal(rsp[0]) + +def CryoSetTemperature(Stage="", Temp=""): + """ + Sets temperature value for TIC chuck or shield. (Only available in process state + 'Idle' or 'Cold'.) + API Status: published + Args: + Stage:str = "C" + Temp:Decimal = 320 + Command Timeout: 10000 + Example:CryoSetTemperature C 70.5 + """ + MessageServerInterface.sendSciCommand("CryoSetTemperature",Stage,Temp) + + +def CryoStartRefill(Stage=""): + """ + Enables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStartRefill C + """ + MessageServerInterface.sendSciCommand("CryoStartRefill",Stage) + + +def CryoStopRefill(Stage=""): + """ + Disables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStopRefill C + """ + MessageServerInterface.sendSciCommand("CryoStopRefill",Stage) + + +def CryoReadState(): + """ + Reads current state. + API Status: published + Returns: + State:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CryoMoveBBPark(): + """ + Moves the black body to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBPark") + + +def CryoMoveBBWork(NbrPosition=""): + """ + Moves the black body to working position. + API Status: published + Args: + NbrPosition:int = 1 + Command Timeout: 60000 + Example:CryoMoveBBWork 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBWork",NbrPosition) + + +def CryoMoveShutter(Position="", Shutter=""): + """ + Moves one of the two shutters. + API Status: published + Args: + Position:str = "C" + Shutter:int = 1 + Command Timeout: 60000 + Example:CryoMoveShutter F 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveShutter",Position,Shutter) + + +def CryoMoveScopeWork(): + """ + Moves the microscope to working position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopeWork") + + +def CryoMoveScopePark(): + """ + Moves the microscope to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopePark") + + +def CryoReadPressure(): + """ + Reads the current pressure of the vacuum chamber. + API Status: published + Returns: + Pressure:Decimal + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadPressure") + return Decimal(rsp[0]) + +def MoveZCombined(Height="", Percent="", Async=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move both Chuck and Scope to a new absolute z-Height. The position must be + within 0 and a predefined maximum height (e.g. 3000um). Moves are performed with + maximum velocity for now + API Status: internal + Args: + Height:Decimal = 0 + Percent:Decimal = 0 + Async:int = 0 + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("MoveZCombined",Height,Percent,Async) + + +def GetSoftwareStop(): + """ + Get the state of the software stop. + API Status: published + Returns: + StopState:int + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareStop") + return int(rsp[0]) + +def MoveZCombinedSetStatus(Status="", Message=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Used to set the system either in off, on, error or locked state. For lock, a + key is required. To unlock this key, doe a 'SetStatus' with the same key. So, + SetStatus without message means enable/ recover from error, with message it + means unlock. If the system wasn't enabled or in error state before an unlock, + it will remain in this state after the unlock. + API Status: internal + Args: + Status:str = "Off" + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedSetStatus",Status,Message) + + +def GetScopeWorkingStage(): + """ + Get the currently active ScopeWorkingStage or -1 if unknown. Normally, this + should be the same as the currently active ScopeSilo + API Status: published + Returns: + ScopeWorkingStage:int + Command Timeout: 5000 + Example:GetScopeWorkingStage + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeWorkingStage") + return int(rsp[0]) + +def SetPerformanceMode(Mode=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the performance mode in use by remote command. If this feature is not + supported and the mode is anything but Standard, an error is returned. + API Status: internal + Args: + Mode:str = "Standard" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetPerformanceMode",Mode) + + +def SetScopeWorkingStage(ScopeWorkingStage=""): + """ + Move to the target working stage + API Status: published + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 30000 + Example:SetScopeWorkingStage 1 + """ + MessageServerInterface.sendSciCommand("SetScopeWorkingStage",ScopeWorkingStage) + + +def GetPerformanceMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured performance mode. If this feature is not supported + on a station, Standard will be returned + API Status: internal + Returns: + Mode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPerformanceMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def MoveZCombinedGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the current status of the combined-z-move-system + API Status: internal + Returns: + Status:str + PlatenSafe:int + Height:Decimal + HeightMax:Decimal + HeightRelative:Decimal + SafeHeight:Decimal + Message:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveZCombinedGetStatus") + global MoveZCombinedGetStatus_Response + if not "MoveZCombinedGetStatus_Response" in globals(): MoveZCombinedGetStatus_Response = namedtuple("MoveZCombinedGetStatus_Response", "Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message") + return MoveZCombinedGetStatus_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str("" if len(rsp) < 7 else ' '.join(rsp[6:]))) + +def LoadScopeFenceConfiguration(Enable="", Path=""): + """ + Load a previously saved Scope-Fence-configuration or remove the current + configuration + API Status: published + Args: + Enable:int = 0 + Path:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoadScopeFenceConfiguration",Enable,Path) + + +def SetSoftwareStop(StopState=""): + """ + Set the state of the software stop. + API Status: published + Args: + StopState:int = 0 + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareStop",StopState) + + +#End of module diff --git a/src/FlexSensor/Prober/velox_api/velox/sci35.py b/src/FlexSensor/Prober/velox_api/velox/sci35.py new file mode 100644 index 0000000000000000000000000000000000000000..655db8fb75f1ddee407da4bee0f5d95a0fe8a6aa --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/sci35.py @@ -0,0 +1,11999 @@ +from Prober.velox_api.velox.vxmessageserver import * +from decimal import Decimal +from collections import namedtuple + +""" +Velox SCI Commands +This module provides a function interface to the Cascade Microtech Velox software suite. +The module was auto-generated from the commands.info.xml file on 2019-11-09. +737 SCI commands were found and included. + +To use this module, your code must import the veloxsci.py module. +Create a connection to the Velox Message Server using the 'with MessageServerInterface():' +command as shown in the sample below. + +The Velox Message Server must be running prior to establishing a connection. +To start the Message Server, run Velox. + +The sample code to use this module is: + +import velox +with velox.MessageServerInterface() as msgServer: + + # Your Code: try some SCI Commands - such as: + response = velox.ReportKernelVersion() + print ('The kernel version is', response.Version, 'and', response.Description) + +""" +def EchoData(TestCmd:str=""): + """ + Test Command for the Kernel Communication. Like a ping command, the given text + string is returned unchanged. + API Status: published + Args: + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:EchoData Test + """ + rsp = MessageServerInterface.sendSciCommand("EchoData",TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportKernelVersion(Module:str=""): + + """ + Returns the version information of the kernel or the control box code. The + "Version" value contains version number and revision level of the actual Kernel + implementation. The text string contains a code description, version number and + the revision date. + API Status: published + Args: + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:ReportKernelVersion K + """ + rsp = MessageServerInterface.sendSciCommand("ReportKernelVersion",Module) + global ReportKernelVersion_Response + if not "ReportKernelVersion_Response" in globals(): ReportKernelVersion_Response = namedtuple("ReportKernelVersion_Response", "Version,Description") + return ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReadProberStatus(): + """ + Returns an actual status information of the prober. + API Status: published + Returns: + FlagsBusy:int + FlagsContact:int + Mode:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadProberStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadProberStatus") + global ReadProberStatus_Response + if not "ReadProberStatus_Response" in globals(): ReadProberStatus_Response = namedtuple("ReadProberStatus_Response", "FlagsBusy,FlagsContact,Mode,IsQuiet") + return ReadProberStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3])) + +def EnableMotorQuiet(WantQuietModeOn:int="", Stage:str=""): + """ + Toggles the motor power for quiet probing. In most applications this feature is + not required. However, for special measurements it may be necessary to reduce + the noise of the system. Quiet on turns off the motor power for all stages (or + the one specified with the optional parameter). Quiet off will turn on the motor + power of all stages (or the one specified with the optional parameter) for + subsequent movements. A move command will also turn on the motor power of the + moved stage automatically. For automatical switching of the quiet mode refer to + Auto Quiet functionality. Sending 'EnableMotorQuiet 1' will enable the quiet + mode for all stages. Sending 'EnableMotorQuiet 1 C' will only enable the quiet + mode for the chuck stage. Sending 'EnableMotorQuiet 1 1' will only enable the + quiet mode for the Positioner1 stage. Sending 'EnableMotorQuiet 0 S' will only + disable the quiet mode for the scope stage. + API Status: published + Args: + WantQuietModeOn:int = 0 + Stage:str = "None" + Command Timeout: 10000 + Example:EnableMotorQuiet 1 + """ + MessageServerInterface.sendSciCommand("EnableMotorQuiet",WantQuietModeOn,Stage) + + +def SetChuckVacuum(WantChuckVacuumOn:int=""): + """ + Toggles the chuck vacuum on (1) or off (0). Can return vacuum timeout error for + stations with wafer vacuum sensors in case no wafer was detected. + API Status: published + Args: + WantChuckVacuumOn:int = 0 + Command Timeout: 10000 + Example:SetChuckVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetChuckVacuum",WantChuckVacuumOn) + + +def SetMicroLight(WantIlluminatorOn:int=""): + """ + Toggles the microscope light channel of the peripheral output board and all + cameras. Notifications: 7 + API Status: published + Args: + WantIlluminatorOn:int = 2 + Command Timeout: 5000 + Example:SetMicroLight 1 + """ + MessageServerInterface.sendSciCommand("SetMicroLight",WantIlluminatorOn) + + +def SetBeaconStatus(FlagsMode:int="", PulseWidthRed:int="", PulseWidthGreen:int="", PulseWidthYellow:int="", PulseWidthBlue:int="", PulseWidthWhite:int=""): + """ + This command controls the beacon channel of the peripheral output board. All + lights can be switched on, off, or blinking. Setting an interval to zero means, + that the corresponding light will be statically on or off. The minimum blinking + interval is 50ms. + API Status: published + Args: + FlagsMode:int = 0 + PulseWidthRed:int = 1000 + PulseWidthGreen:int = 0 + PulseWidthYellow:int = 0 + PulseWidthBlue:int = 0 + PulseWidthWhite:int = 0 + Command Timeout: 5000 + Example:SetBeaconStatus 1 1000 + """ + MessageServerInterface.sendSciCommand("SetBeaconStatus",FlagsMode,PulseWidthRed,PulseWidthGreen,PulseWidthYellow,PulseWidthBlue,PulseWidthWhite) + + +def SetOutput(Channel:int="", WantOutputOn:int="", PulseTime:int=""): + """ + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: published + Args: + Channel:int = 1 + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetOutput 4 0 + """ + MessageServerInterface.sendSciCommand("SetOutput",Channel,WantOutputOn,PulseTime) + + +def StopAllMovements(): + """ + Stops all Prober movements immediately. The response status value of any pending + movement will signify that the stop command was executed. + API Status: published + Command Timeout: 5000 + Example:StopAllMovements + """ + MessageServerInterface.sendSciCommand("StopAllMovements") + + +def InkDevice(FlagsInker:int="", PulseWidth:int=""): + """ + Inks the current device under test. The range of PulseWidth is 20ms to 2000ms. + For correct function, the inkers have to be linked to default outputs. + API Status: published + Args: + FlagsInker:int = 0 + PulseWidth:int = 50 + Command Timeout: 10000 + Example:InkDevice 1 40 + """ + MessageServerInterface.sendSciCommand("InkDevice",FlagsInker,PulseWidth) + + +def ReadProbeSetup(): + """ + Returns the current positioner configuration. The output pattern is: 1. Type + Positioner 1 2. Type Positioner 2 3. Type Positioner 3 4. Type Positioner 4 5. + Type Positioner 5 6. Axis Positioner 1 (Bit 0: XY, Bit 1: Z) 7. Axis Positioner + 2 (Bit 0: XY, Bit 1: Z) 8. Axis Positioner 3 (Bit 0: XY, Bit 1: Z) 9. Axis + Positioner 4 (Bit 0: XY, Bit 1: Z) 10. Axis Positioner 5 (Bit 0: XY, Bit 1: Z) + 11. Type Positioner 6 12. Axis Positioner 6 (Bit 0: XY, Bit 1: Z) + API Status: published + Returns: + TypePositioner1:int + TypePositioner2:int + TypePositioner3:int + TypePositioner4:int + TypePositioner5:int + AxisPositioner1:int + AxisPositioner2:int + AxisPositioner3:int + AxisPositioner4:int + AxisPositioner5:int + TypePositioner6:int + AxisPositioner6:int + Command Timeout: 5000 + Example:ReadProbeSetup + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSetup") + global ReadProbeSetup_Response + if not "ReadProbeSetup_Response" in globals(): ReadProbeSetup_Response = namedtuple("ReadProbeSetup_Response", "TypePositioner1,TypePositioner2,TypePositioner3,TypePositioner4,TypePositioner5,AxisPositioner1,AxisPositioner2,AxisPositioner3,AxisPositioner4,AxisPositioner5,TypePositioner6,AxisPositioner6") + return ReadProbeSetup_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11])) + +def ReadSystemStatus(): + """ + Returns the system options which are currently enabled at the prober. + API Status: published + Returns: + Name:str + System:str + ChuckXY:int + ChuckZ:int + ChuckTheta:int + ScopeXY:int + ScopeZ:int + EdgeSensor:int + OperationalMode:str + Turret:int + TemperatureChuck:int + AuxSiteCount:int + PlatenXY:int + PlatenZ:int + LoaderGateState:str + NucleusType:str + Command Timeout: 10000 + Example:ReadSystemStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadSystemStatus") + global ReadSystemStatus_Response + if not "ReadSystemStatus_Response" in globals(): ReadSystemStatus_Response = namedtuple("ReadSystemStatus_Response", "Name,System,ChuckXY,ChuckZ,ChuckTheta,ScopeXY,ScopeZ,EdgeSensor,OperationalMode,Turret,TemperatureChuck,AuxSiteCount,PlatenXY,PlatenZ,LoaderGateState,NucleusType") + return ReadSystemStatus_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),str(rsp[14]),str("" if len(rsp) < 16 else ' '.join(rsp[15:]))) + +def SetExternalMode(Mode:str=""): + """ + If 'R' is sent, it sets the external mode of the kernel. This disables most of + the control box functions (except the LOCAL function key). Otherwise, this + command re-enables all functions of the control box. + API Status: published + Args: + Mode:str = "L" + Command Timeout: 5000 + Example:SetExternalMode L + """ + MessageServerInterface.sendSciCommand("SetExternalMode",Mode) + + +def SetStageLock(Stage:str="", WantStageLock:int="", Application:str=""): + """ + Enables or disables the stage lock functionality. Stages which are locked can't + be moved in any way. If the joystick controller is locked, the display and the + keys are deactivated. The name of the application can be stored by using the + Application Name parameter and is shown in lock-caused error messages. + API Status: published + Args: + Stage:str = "0" + WantStageLock:int = 1 + Application:str = "" + Command Timeout: 10000 + Example:SetStageLock C 0 WaferMap + """ + MessageServerInterface.sendSciCommand("SetStageLock",Stage,WantStageLock,Application) + + +def ReadSensor(Channel:int="", Type:str=""): + """ + Returns the actual status of the specified input channel, output channel or edge + sensor. The signal table is described in the Hardware Manual. Each used IO-board + has 16 channels (max. 4 IO-boards are supported), what results in a domain of 64 + channel numbers. Beyond this range there are pseudo channels, which are used for + special purposes. Pseudo channels: + API Status: published + Args: + Channel:int = 1 + Type:str = "Input" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadSensor 11 I + """ + rsp = MessageServerInterface.sendSciCommand("ReadSensor",Channel,Type) + return int(rsp[0]) + +def GetStageLock(Stage:str=""): + """ + Reads whether stages or joystick controller are locked. + API Status: published + Args: + Stage:str = "0" + Returns: + Locks:int + Application:str + Command Timeout: 10000 + Example:GetStageLock C + """ + rsp = MessageServerInterface.sendSciCommand("GetStageLock",Stage) + global GetStageLock_Response + if not "GetStageLock_Response" in globals(): GetStageLock_Response = namedtuple("GetStageLock_Response", "Locks,Application") + return GetStageLock_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetBackSideMode(WantBackSideMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets bottomside mode. In this mode the Z axis is reverse and the + command MoveChuckLoad is not allowed. + API Status: internal + Args: + WantBackSideMode:int = 0 + Command Timeout: 5000 + Example:SetBackSideMode 1 + """ + MessageServerInterface.sendSciCommand("SetBackSideMode",WantBackSideMode) + + +def GetBackSideMode(): + """ + Returns the current side mode. + API Status: published + Returns: + IsBackSideModeOn:int + Command Timeout: 5000 + Example:GetBackSideMode + """ + rsp = MessageServerInterface.sendSciCommand("GetBackSideMode") + return int(rsp[0]) + +def SetDarkMode(WantSetDarkMode:int=""): + """ + Switches off all LEDs on the Control Box, on the positioners, and on the screen + of the Control Box and also the light of the cameras. + API Status: published + Args: + WantSetDarkMode:int = 0 + Command Timeout: 5000 + Example:SetDarkMode 1 + """ + MessageServerInterface.sendSciCommand("SetDarkMode",WantSetDarkMode) + + +def GetDarkMode(): + """ + Returns the current mode of the light sources. + API Status: published + Returns: + IsDarkMode:int + Command Timeout: 5000 + Example:GetDarkMode + """ + rsp = MessageServerInterface.sendSciCommand("GetDarkMode") + return int(rsp[0]) + +def DockChuckCamera(ConnectCamera:str="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Connect or disconnect the chuck camera to the chuck stage. The command is only + available for the Prober type PA300BEP. + API Status: internal + Args: + ConnectCamera:str = "ParkPos" + Velocity:Decimal = 100 + Command Timeout: 300000 + Example:DockChuckCamera P 75 + """ + MessageServerInterface.sendSciCommand("DockChuckCamera",ConnectCamera,Velocity) + + +def ReadCBoxStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current selected stage of the joystick controller. + API Status: internal + Returns: + Stage:str + Command Timeout: 5000 + Example:ReadCBoxStage + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxStage") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxStage(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current stage of the joystick controller. + API Status: internal + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:SetCBoxStage C + """ + MessageServerInterface.sendSciCommand("SetCBoxStage",Stage) + + +def ReadCBoxPosMonConf(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current setting of the joystick controllers position monitor for the + secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + PosRef:str + Unit:str + Command Timeout: 5000 + Example:ReadCBoxPosMonConf C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxPosMonConf",Stage) + global ReadCBoxPosMonConf_Response + if not "ReadCBoxPosMonConf_Response" in globals(): ReadCBoxPosMonConf_Response = namedtuple("ReadCBoxPosMonConf_Response", "PosRef,Unit") + return ReadCBoxPosMonConf_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetCBoxPosMonConf(Stage:str="", PosRef:str="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Configures the joystick controller position monitor for the secified stage. + API Status: internal + Args: + Stage:str = "Chuck" + PosRef:str = "Zero" + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetCBoxPosMonConf C Z Y + """ + MessageServerInterface.sendSciCommand("SetCBoxPosMonConf",Stage,PosRef,Unit) + + +def ReadCBoxCurrSpeed(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CBoxSpeed:str + Command Timeout: 5000 + Example:ReadCBoxCurrSpeed C + """ + rsp = MessageServerInterface.sendSciCommand("ReadCBoxCurrSpeed",Stage) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetCBoxCurrSpeed(Stage:str="", CBoxSpeed:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current speed of the joystick controller for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CBoxSpeed:str = "Speed4" + Command Timeout: 5000 + Example:SetCBoxCurrSpeed C 3 + """ + MessageServerInterface.sendSciCommand("SetCBoxCurrSpeed",Stage,CBoxSpeed) + + +def MoveChuckAsync(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck stage to the specified X,Y position without waiting for the move + to be finished If chuck Z is in contact height or higher, the chuck will drop to + separation. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveChuckAsync 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeAsync(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the scope stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 5000 + Example:MoveScopeAsync 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAsync",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveProbeAsync(Probe:int="", XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the probe stage to the specified X,Y position without waiting for the move + to be finished. + API Status: internal + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAsync",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def ReadChuckStatus(): + """ + Returns the current chuck status. Every bit in the bit fields works like a + boolean value: One <1> means true/on and zero <0> means false/off. + Its counted from LSB to MSB. - _FlagsInit_: X, Y, Z, Theta - _FlagsMode_: + HasOvertravel, HasAutoZ, HasInterlock, ContactSearch, IsContactSet, + EdgeInterlock, QuietContact, IsLocked - _FlagsLimit_: XHigh, XLow, YHigh, YLow, + ZHigh, ZLow, ThetaHigh, ThetaLow - _FlagsMoving_: X, Y, Z, Theta All parameters + are provided as indirect access (e.g. first bit of M_pvecFlagsInit can be + accessed by M_pbIsInitX). + API Status: published + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsVacuumOn:int + PresetHeight:str + LoadPos:str + IsLiftDown:int + CameraConnection:str + IsQuiet:int + Command Timeout: 5000 + Example:ReadChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckStatus") + global ReadChuckStatus_Response + if not "ReadChuckStatus_Response" in globals(): ReadChuckStatus_Response = namedtuple("ReadChuckStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,IsVacuumOn,PresetHeight,LoadPos,IsLiftDown,CameraConnection,IsQuiet") + return ReadChuckStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),int(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),str(rsp[9]),int(rsp[10])) + +def ReadChuckPosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the current chuck stage position in X, Y and Z. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadChuckPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckPosition",Unit,PosRef,Comp) + global ReadChuckPosition_Response + if not "ReadChuckPosition_Response" in globals(): ReadChuckPosition_Response = namedtuple("ReadChuckPosition_Response", "X,Y,Z") + return ReadChuckPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadChuckHeights(Unit:str=""): + """ + Returns the current settings used for the chuck Z movement. `Contact` is the + contact-height from zero in default compensation. The other heights are relative + to this. If no contact is set, the value will be -1. + API Status: published + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + SearchGap:Decimal + Command Timeout: 5000 + Example:ReadChuckHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckHeights",Unit) + global ReadChuckHeights_Response + if not "ReadChuckHeights_Response" in globals(): ReadChuckHeights_Response = namedtuple("ReadChuckHeights_Response", "Contact,Overtravel,AlignDist,SepDist,SearchGap") + return ReadChuckHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def InitChuck(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + Machine Coordinate System: Chuck X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - _FlagsMoveRange_: + X, Y, Z, Theta All flags can be accessed by indirect members. Initializes the + chuck stage and resets current coordinate system. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 150000 + Example:InitChuck 7 0 0 + """ + MessageServerInterface.sendSciCommand("InitChuck",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveChuck(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck stage to the specified X,Y position. If chuck Z is in contact + height or higher, Interlock and Auto Z flags will be analyzed and stage will + behave correspondingly - can move to separation first or return an error: + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MoveChuck 5000. 5000. R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuck",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveChuckIndex(XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves the chuck stage in index steps. This command modifies Die Home Position. + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveChuckSubsite(XValue:Decimal="", YValue:Decimal="", Unit:str="", Velocity:Decimal=""): + """ + Moves the chuck stage to the specified X, Y sub-site position. Die home position + is defined by destination position of last successful MoveChuck or + MoveChuckIndex commands. MoveChuckVelocity does not touch die home position. If + you have moved chuck with MoveChuckVelocity, "MoveChuckSubsite 0 0" will move it + back to die home position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckSubsite 200 200 Y 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSubsite",XValue,YValue,Unit,Velocity) + + +def MoveChuckContact(Velocity:Decimal=""): + """ + Performs a movement of chuck Z axis to preset contact height or will return + error if no contact height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckContact 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckContact",Velocity) + + +def MoveChuckAlign(Velocity:Decimal=""): + """ + Moves the chuck Z axis to the align height. If no Contact height is set will + return an error. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckAlign",Velocity) + + +def MoveChuckSeparation(Velocity:Decimal=""): + """ + Moves the chuck Z axis to the separation height. Returns error if no Contact + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveChuckSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveChuckSeparation",Velocity) + + +def MoveChuckLoad(LoadPosition:str=""): + """ + Moves the Chuck stage in X, Y, Z and Theta to the load position. + API Status: published + Args: + LoadPosition:str = "First" + Command Timeout: 60000 + Example:MoveChuckLoad 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckLoad",LoadPosition) + + +def MoveChuckZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck Z axis to the specified height. If contact is set, only moves up + to contact height will be allowed. If overtravel is enabled - up to overtravel + height. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 60000 + Example:MoveChuckZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckZ",Height,PosRef,Unit,Velocity,Comp) + + +def SearchChuckContact(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the chuck Z axis to the specified height and sets contact. The move stops + immediately if the Contact Sensor ( Edge Sensor) is triggered. If no contact has + been found and an old one was set before the old contact will not get lost, it + will be reset. + API Status: published + Args: + Height:Decimal = 100 + PosRef:str = "Relative" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 60000 + Example:SearchChuckContact 1000 R Y 10 + """ + rsp = MessageServerInterface.sendSciCommand("SearchChuckContact",Height,PosRef,Unit,Velocity,Comp) + return Decimal(rsp[0]) + +def MoveChuckVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + Moves the chuck stage in velocity mode. The motion continues until the + StopChuckMovement command is received, or the end limit is reached. + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveChuckVelocity + + 0 100 30 0 + """ + MessageServerInterface.sendSciCommand("MoveChuckVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopChuckMovement(FlagsStop:int=""): + """ + Stops chuck movement for the given axis. Notifications: 31 / 32 / 5 + API Status: published + Args: + FlagsStop:int = 15 + Command Timeout: 5000 + Example:StopChuckMovement 7 + """ + MessageServerInterface.sendSciCommand("StopChuckMovement",FlagsStop) + + +def SetChuckMode(Overtravel:int="", AutoZ:int="", Interlock:int="", ContactSearch:int="", EdgeInterlock:int="", QuietContact:int=""): + """ + Mode manages the way the chuck behaves when it is in contact height. Chuck mode + is made from 6 flags and you can control all of them using this command. Every + flag can be turned on by using value 1 or turned off by using value 0. If you do + not want to change a flag - use value of 2. + API Status: published + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + ContactSearch:int = 2 + EdgeInterlock:int = 2 + QuietContact:int = 2 + Command Timeout: 5000 + Example:SetChuckMode 2 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetChuckMode",Overtravel,AutoZ,Interlock,ContactSearch,EdgeInterlock,QuietContact) + + +def SetChuckHome(Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets wafer and die home position, which can be used later as coordinate system + for movements. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetChuckHome",Mode,Unit,XValue,YValue) + + +def SetChuckIndex(XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the wafer index size. Normally the size of one die. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetChuckIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetChuckIndex",XValue,YValue,Unit) + + +def SetChuckHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation. A predefined contact search gap is able to write. No data + in the optional parameters sets contact height at current position. If Mode is + '0', contact height can be set at current position. The levels O, A, S and T + support no Mode '0'. If Mode is 'V' and no value for height is specified - + default 0 will be used, what potentially can be not what you expect. If Mode is + 'R', contact height can be invalidated. The levels O, A, S and T support no Mode + 'R'. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckHeight C V Y 5000. + """ + MessageServerInterface.sendSciCommand("SetChuckHeight",PresetHeight,Mode,Unit,Value) + + +def ReadChuckIndex(Unit:str=""): + """ + The command gets the current die size which is stored in the kernel. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadChuckIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckIndex",Unit) + global ReadChuckIndex_Response + if not "ReadChuckIndex_Response" in globals(): ReadChuckIndex_Response = namedtuple("ReadChuckIndex_Response", "IndexX,IndexY") + return ReadChuckIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveChuckTransfer(): + """ + Moves the Chuck to the Transfer Position. If the movement starts in Load + Position (where it's possible to pull out the chuck) the handling of the Add On + Platen or the Pin Chuck is integrated. + API Status: published + Command Timeout: 90000 + Example:MoveChuckTransfer + """ + MessageServerInterface.sendSciCommand("MoveChuckTransfer") + + +def MoveChuckLift(SetLift:int=""): + """ + Moves the chuck to the upper (0) or lower = lifted (1) position. This initiates + motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveChuckLift 1 + """ + MessageServerInterface.sendSciCommand("MoveChuckLift",SetLift) + + +def SetChuckThermoScale(ScaleX:Decimal="", ScaleY:Decimal=""): + """ + Thermo drifts of the wafer will be compensated. The compensation is not + persistent, (power off - this compensation is deleted). The algorithm works as + an additional one. This is for an iterative usage, so: 1. `ResetProber H` 2. + `SetChuckThermoScale 1.5 1.5` 3. `SetChuckThermoScale 1.5 1.5` will result in a + scale of 2.25 in both directions. The thermal scale can also be reset using the + command 'SetChcukThermoValue 20 C' + API Status: published + Args: + ScaleX:Decimal = 1 + ScaleY:Decimal = 1 + Command Timeout: 5000 + Example:SetChuckThermoScale 1.000005 1.0000045 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoScale",ScaleX,ScaleY) + + +def ReadChuckThermoScale(): + """ + Read the linear scaling value of the chuck. + API Status: published + Returns: + ScaleX:Decimal + ScaleY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoScale + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoScale") + global ReadChuckThermoScale_Response + if not "ReadChuckThermoScale_Response" in globals(): ReadChuckThermoScale_Response = namedtuple("ReadChuckThermoScale_Response", "ScaleX,ScaleY") + return ReadChuckThermoScale_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetChuckThermoValue(Temperature:Decimal="", Unit:str="", ExpCoeffX:Decimal="", ExpCoeffY:Decimal=""): + """ + Set a temperature and optional the expansion coefficient. The temperature for + normal level is 20 degree. The scaling factor at this temperature is 1.0. If you + set the temperature directly the controller calculates the stage difference in + the coordinate system. For the calculation use the set coefficient of expansion + from the controller. The default coefficient of expansion is based on silicon: + 2.33E-06 1/K. + API Status: published + Args: + Temperature:Decimal = 0 + Unit:str = "Celsius" + ExpCoeffX:Decimal = 0 + ExpCoeffY:Decimal = 0 + Command Timeout: 5000 + Example:SetChuckThermoValue 250 C 2.43 2.32 + """ + MessageServerInterface.sendSciCommand("SetChuckThermoValue",Temperature,Unit,ExpCoeffX,ExpCoeffY) + + +def ReadChuckThermoValue(Unit:str=""): + """ + Read the current temperature (either set or calculated) for the thermal scaling. + With SetChuckThermoScale in use, the value will be calculated by the current + scale and the expansion factor of silicium. The temperature that is read with + this command is not identical to the current chuck temperature. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + Temperature:Decimal + ExpCoeffX:Decimal + ExpCoeffY:Decimal + Command Timeout: 5000 + Example:ReadChuckThermoValue C + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckThermoValue",Unit) + global ReadChuckThermoValue_Response + if not "ReadChuckThermoValue_Response" in globals(): ReadChuckThermoValue_Response = namedtuple("ReadChuckThermoValue_Response", "Temperature,ExpCoeffX,ExpCoeffY") + return ReadChuckThermoValue_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetChuckTableID(TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ChuckTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetChuckTableID ChuckTable + """ + rsp = MessageServerInterface.sendSciCommand("GetChuckTableID",TableName) + return int(rsp[0]) + +def MoveChuckTablePoint(TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move the chuck to the next stored table site. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveChuckTablePoint 3 10 67 + """ + MessageServerInterface.sendSciCommand("MoveChuckTablePoint",TableID,PointID,Velocity) + + +def ReadChuckTablePoint(TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the table site information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadChuckTablePoint 10 250 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTablePoint",TableID,PointID,Unit) + global ReadChuckTablePoint_Response + if not "ReadChuckTablePoint_Response" in globals(): ReadChuckTablePoint_Response = namedtuple("ReadChuckTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadChuckTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetChuckTablePoint(TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the chuck table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetChuckTablePoint 10 12000.0 2344.0 Y F + """ + rsp = MessageServerInterface.sendSciCommand("SetChuckTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearChuckTablePoint(TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of chuck table site points in the in the Kernel. If Start + Point is -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearChuckTablePoint 5 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearChuckTablePoint",TableID,StartPoint,EndPoint) + global ClearChuckTablePoint_Response + if not "ClearChuckTablePoint_Response" in globals(): ClearChuckTablePoint_Response = namedtuple("ClearChuckTablePoint_Response", "ClearNumber,ValidNumber") + return ClearChuckTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def AttachAmbientWafer(MoveTimeMs:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is moved to slowly attach a wafer that is at ambient temperature while + the chuck is hot. The command acts similar to MoveChuckTransfer when moving + out of Load 2 but will use a much slower Z velocity. This is only supported + for BnR-machines (CM300 and Summit200) at the moment. + API Status: internal + Args: + MoveTimeMs:Decimal = 30000 + Command Timeout: 300000 + Example:AttachAmbientWafer + """ + MessageServerInterface.sendSciCommand("AttachAmbientWafer",MoveTimeMs) + + +def ReadThetaStatus(): + """ + Returns the actual status of the chuck Theta axis. + API Status: published + Returns: + IsInit:int + FlagsLimit:int + IsMoving:int + Command Timeout: 5000 + Example:ReadThetaStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaStatus") + global ReadThetaStatus_Response + if not "ReadThetaStatus_Response" in globals(): ReadThetaStatus_Response = namedtuple("ReadThetaStatus_Response", "IsInit,FlagsLimit,IsMoving") + return ReadThetaStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadThetaPosition(Unit:str="", PosRef:str=""): + """ + Returns the actual Theta position. + API Status: published + Args: + Unit:str = "Degrees" + PosRef:str = "Home" + Returns: + Position:Decimal + Command Timeout: 5000 + Example:ReadThetaPosition D Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadThetaPosition",Unit,PosRef) + return Decimal(rsp[0]) + +def InitTheta(FlagsDoPlus:int="", FlagsMoveRange:int=""): + """ + Performs an initialization move and resets the coordinate system of the Theta + axis. + API Status: published + Args: + FlagsDoPlus:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitTheta 0 0 + """ + MessageServerInterface.sendSciCommand("InitTheta",FlagsDoPlus,FlagsMoveRange) + + +def MoveTheta(Position:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal=""): + """ + Moves the chuck Theta axis to the specified position. The positive direction is + counter-clockwise. + API Status: published + Args: + Position:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Degrees" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveTheta 1000. R E + """ + MessageServerInterface.sendSciCommand("MoveTheta",Position,PosRef,Unit,Velocity) + + +def MoveThetaVelocity(Polarity:str="", Velocity:Decimal=""): + """ + Moves the chuck Theta axis in velocity mode. The positive direction is counter- + clockwise. The motion continues until the StopThetaMovement command is received, + or the end limit (error condition) is reached. This command is mostly used for + joystick movements that do not have a target destination. + API Status: published + Args: + Polarity:str = "Fixed" + Velocity:Decimal = 0 + Command Timeout: 240000 + Example:MoveThetaVelocity + 67 + """ + MessageServerInterface.sendSciCommand("MoveThetaVelocity",Polarity,Velocity) + + +def StopThetaMovement(): + """ + Stops any type (velocity, position etc.) of chuck Theta axis movement. This is + treated as a smooth stop rather than an emergency stop. + API Status: published + Command Timeout: 5000 + Example:StopThetaMovement + """ + MessageServerInterface.sendSciCommand("StopThetaMovement") + + +def SetThetaHome(Mode:str="", Unit:str="", Position:Decimal=""): + """ + Sets the chuck Theta position to home. This position is usable as reference + position for other commands. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Degrees" + Position:Decimal = 0 + Command Timeout: 5000 + Example:SetThetaHome 0 + """ + MessageServerInterface.sendSciCommand("SetThetaHome",Mode,Unit,Position) + + +def ScanChuckZ(ZDistance:Decimal="", TriggerEveryNthCycle:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts moving the chuck from the current position with Velocity [%] over + ZDistance (sign is important, as a negative sign will move chuck down during + scan) - Predefined camera trigger pulses (TTL active high for at least 5us) will + be sent during the scan every passed number of BnR cyclics (800us per cyclic) + until the ZDistance has been reached. Command returns number of positions and + all compensated Z Positions from Zero, where the trigger was sent. + API Status: internal + Args: + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 3 + Velocity:Decimal = 10 + Returns: + NumberOfPositions:int + TriggerPositions:str + Command Timeout: 60000 + Example:ScanChuckZ 300 3 1.5 + """ + rsp = MessageServerInterface.sendSciCommand("ScanChuckZ",ZDistance,TriggerEveryNthCycle,Velocity) + global ScanChuckZ_Response + if not "ScanChuckZ_Response" in globals(): ScanChuckZ_Response = namedtuple("ScanChuckZ_Response", "NumberOfPositions,TriggerPositions") + return ScanChuckZ_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def MoveChuckZSafe(): + """ + Moves the chuck Z axis to a z height considered safe. This is either the lower + Z-Fence or the kernel setup item Chuck:SafeTransferHeight (which ever is larger) + API Status: published + Command Timeout: 60000 + Example:MoveChuckZSafe + """ + MessageServerInterface.sendSciCommand("MoveChuckZSafe") + + +def SetPlatenMode(Overtravel:int="", AutoZ:int="", Interlock:int="", AutoZFollow:int="", AutoQuiet:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The mode manages the way the platen behaves when it is in contact height. Platen + mode is made up from 5 flags and the user can control all of them by using this + command. Every flag can be turned on by setting value 1 or turned off by setting + value 0. If no change for a flag is wanted, use the value of 2. + API Status: internal + Args: + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Command Timeout: 5000 + Example:SetPlatenMode 2 2 2 2 2 + """ + MessageServerInterface.sendSciCommand("SetPlatenMode",Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + + +def MovePlatenLift(SetLift:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen to the high (0) or low = lifted (1) position. This initiates + motion; the actual movement may take some seconds. + API Status: internal + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MovePlatenLift 1 + """ + MessageServerInterface.sendSciCommand("MovePlatenLift",SetLift) + + +def SearchPlatenContact(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Searches contact height using the edge sensor using a z movement of the platen + stage + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + CompLayer:str = "Default" + Returns: + ContactHeight:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("SearchPlatenContact",Height,PosRef,Unit,Velocity,CompLayer) + return Decimal(rsp[0]) + +def ReadPlatenStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current platen status. + API Status: internal + Returns: + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + PresetHeight:str + IsLiftDown:int + Command Timeout: 10000 + Example:ReadPlatenStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenStatus") + global ReadPlatenStatus_Response + if not "ReadPlatenStatus_Response" in globals(): ReadPlatenStatus_Response = namedtuple("ReadPlatenStatus_Response", "FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,PresetHeight,IsLiftDown") + return ReadPlatenStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ReadPlatenPosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the platens X, Y and Z axes. The default + compensation is the currently selected compensation for the stage. + API Status: internal + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadPlatenPosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenPosition",Unit,PosRef,Comp) + global ReadPlatenPosition_Response + if not "ReadPlatenPosition_Response" in globals(): ReadPlatenPosition_Response = namedtuple("ReadPlatenPosition_Response", "X,Y,Z") + return ReadPlatenPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadPlatenHeights(Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual settings for the probe Z movement. + API Status: internal + Args: + Unit:str = "Microns" + Returns: + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadPlatenHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadPlatenHeights",Unit) + global ReadPlatenHeights_Response + if not "ReadPlatenHeights_Response" in globals(): ReadPlatenHeights_Response = namedtuple("ReadPlatenHeights_Response", "Contact,Overtravel,AlignDist,SepDist") + return ReadPlatenHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def InitPlaten(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the platens X, Y and Z axes. Currently the initialization in + negative direction and the move range scan are not supported. + API Status: internal + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 120000 + Example:InitPlaten 4 + """ + MessageServerInterface.sendSciCommand("InitPlaten",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MovePlatenZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the specified height. If contact is set, only moves + up to contact height will be allowed. If overtravel is enabled - up to + overtravel height. + API Status: internal + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 30000 + Example:MovePlatenZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MovePlatenZ",Height,PosRef,Unit,Velocity,Comp) + + +def MovePlatenContact(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a movement of platen Z axis to preset contact height or returns an + error, if no contact height is set. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenContact 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenContact",Velocity) + + +def MovePlatenAlign(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the align height. If no contact height is set, the + command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenAlign 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenAlign",Velocity) + + +def MovePlatenSeparation(Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen Z axis to the separation height. If no contact height is set, + the command will return an error. + API Status: internal + Args: + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MovePlatenSeparation 100 + """ + MessageServerInterface.sendSciCommand("MovePlatenSeparation",Velocity) + + +def MovePlatenVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the platen stage in velocity mode. The motion continues until the + StopPlatenMovement command is received, or the software fence is reached. + API Status: internal + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 240000 + Example:MovePlatenVelocity + + 0 67 50 0 + """ + MessageServerInterface.sendSciCommand("MovePlatenVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopPlatenMovement(FlagsStop:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the movement of a set of platen axes immediately. + API Status: internal + Args: + FlagsStop:int = 7 + Command Timeout: 10000 + Example:StopPlatenMovement 4 + """ + MessageServerInterface.sendSciCommand("StopPlatenMovement",FlagsStop) + + +def SetPlatenHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Defines the predefined contact height and corresponding gaps for overtravel, + align and separation height. A command without data sets contact height at + current position. + API Status: internal + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 10000 + Example:SetPlatenHeight C V Y 5000 + """ + MessageServerInterface.sendSciCommand("SetPlatenHeight",PresetHeight,Mode,Unit,Value) + + +def ReadManualPlatenState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the current status of the manual platen. THis is only supported for + Nucleus and Summit200. + API Status: internal + Returns: + IsUp:int + IsDown:int + IsSafe:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadManualPlatenState") + global ReadManualPlatenState_Response + if not "ReadManualPlatenState_Response" in globals(): ReadManualPlatenState_Response = namedtuple("ReadManualPlatenState_Response", "IsUp,IsDown,IsSafe") + return ReadManualPlatenState_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def ReadScopeStatus(): + """ + Returns the current scope status. + API Status: published + Returns: + FlagsInit:int + FlagsLimit:int + FlagsMoving:int + Comp:str + IsScopeLiftUp:int + PresetHeight:str + IsScopeLight:int + FlagsMode:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadScopeStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeStatus") + global ReadScopeStatus_Response + if not "ReadScopeStatus_Response" in globals(): ReadScopeStatus_Response = namedtuple("ReadScopeStatus_Response", "FlagsInit,FlagsLimit,FlagsMoving,Comp,IsScopeLiftUp,PresetHeight,IsScopeLight,FlagsMode,IsQuiet") + return ReadScopeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),str(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def ReadScopePosition(Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual scope stage position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadScopePosition Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopePosition",Unit,PosRef,Comp) + global ReadScopePosition_Response + if not "ReadScopePosition_Response" in globals(): ReadScopePosition_Response = namedtuple("ReadScopePosition_Response", "X,Y,Z") + return ReadScopePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeHeights(Unit:str=""): + """ + Returns the actual settings of the focus height, align gap, and separation gap + for the scope Z axis. + API Status: published + Args: + Unit:str = "Microns" + Returns: + FocusHeight:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadScopeHeights Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeHeights",Unit) + global ReadScopeHeights_Response + if not "ReadScopeHeights_Response" in globals(): ReadScopeHeights_Response = namedtuple("ReadScopeHeights_Response", "FocusHeight,AlignDist,SepDist") + return ReadScopeHeights_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def InitScope(FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int=""): + """ + Initializes the microscope stage in X, Y and Z. The Axis default is all axes and + the Direction default is XY in minus and Z in plus. Should be used only in cases + when the reported coordinates do not correspond to real position of mechanics. + Find Move Range starts the initialization in the defined direction and then + moves to the other limit and finds the whole range of the axes. + API Status: published + Args: + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + Command Timeout: 240000 + Example:InitScope 3 0 0 + """ + MessageServerInterface.sendSciCommand("InitScope",FlagsInit,FlagsDirection,FlagsMoveRange) + + +def MoveScope(XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 70000 + Example:MoveScope 5000 5000 R Y 100 + """ + MessageServerInterface.sendSciCommand("MoveScope",XValue,YValue,PosRef,Unit,Velocity,Comp) + + +def MoveScopeIndex(XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves the microscope stage in index steps. If no PositionReference byte is + passed the scope will step relative to the wafer home position. ('R' means the + step relative to current position). + API Status: published + Args: + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeIndex 1 1 R 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeIndex",XSteps,YSteps,PosRef,Velocity) + + +def MoveScopeZ(Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves the microscope Z axis to the specified height. Default velocity is 100%. + API Status: published + Args: + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Command Timeout: 120000 + Example:MoveScopeZ 1000. R Y 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeZ",Height,PosRef,Unit,Velocity,Comp) + + +def SetScopeMode(QuietMode:int="", FollowMode:int=""): + """ + Scope mode is made up of two flags which can be controlled using this command. + Each flag can be turned on by using value 1 or turned off by using value 0. If + you do not want to change a flag, use value of 2. + API Status: published + Args: + QuietMode:int = 2 + FollowMode:int = 2 + Command Timeout: 5000 + Example:SetScopeMode 2 2 + """ + MessageServerInterface.sendSciCommand("SetScopeMode",QuietMode,FollowMode) + + +def MoveScopeVelocity(PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + Moves the microscope stage in velocity mode. The motion continues until the + StopScopeMovement command is received, or the end limit (error condition) is + reached. Axes parameter: '+' move this axis in plus direction '-' move this axis + in minus direction '0' Do not change this axis + API Status: published + Args: + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Command Timeout: 30000 + Example:MoveScopeVelocity + + 0 67 100 0 + """ + MessageServerInterface.sendSciCommand("MoveScopeVelocity",PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + + +def StopScopeMovement(FlagsStop:int=""): + """ + Stops scope movement for the given axis. A smooth stop is executed, no emergency + stop. + API Status: published + Args: + FlagsStop:int = 7 + Command Timeout: 5000 + Example:StopScopeMovement 7 + """ + MessageServerInterface.sendSciCommand("StopScopeMovement",FlagsStop) + + +def SetScopeHome(Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the scope Home position in X and Y. It identifies the scope coordinate + system for later movements. Usually this position is identical to the die home + location. + API Status: published + Args: + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHome 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHome",Mode,Unit,XValue,YValue) + + +def SetScopeIndex(XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the microscope index size. Normally set in relation to the wafer index + size. + API Status: published + Args: + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Command Timeout: 5000 + Example:SetScopeIndex 5000. 5000. Y + """ + MessageServerInterface.sendSciCommand("SetScopeIndex",XValue,YValue,Unit) + + +def SetScopeHeight(PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + This command defines scope focus height and the corresponding gaps for alignment + or separation. No data sets focus height at current position. + API Status: published + Args: + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeHeight F 0 Y + """ + MessageServerInterface.sendSciCommand("SetScopeHeight",PresetHeight,Mode,Unit,Value) + + +def ReadScopeIndex(Unit:str=""): + """ + Returns the actual scope stage index values in X and Y. + API Status: published + Args: + Unit:str = "Microns" + Returns: + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadScopeIndex Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeIndex",Unit) + global ReadScopeIndex_Response + if not "ReadScopeIndex_Response" in globals(): ReadScopeIndex_Response = namedtuple("ReadScopeIndex_Response", "IndexX,IndexY") + return ReadScopeIndex_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def MoveScopeFocus(Velocity:Decimal=""): + """ + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 25000 + Example:MoveScopeFocus 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeFocus",Velocity) + + +def MoveScopeAlign(Velocity:Decimal=""): + """ + Moves the Scope Z axis to the alignment height. If no focus height is set an + error will bereturned. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 10000 + Example:MoveScopeAlign 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeAlign",Velocity) + + +def MoveScopeSeparation(Velocity:Decimal=""): + """ + Moves the scope Z axis to the separation height. Returns an error if no focus + height is set. + API Status: published + Args: + Velocity:Decimal = 100 + Command Timeout: 60000 + Example:MoveScopeSeparation 100 + """ + MessageServerInterface.sendSciCommand("MoveScopeSeparation",Velocity) + + +def MoveScopeLift(SetLift:int=""): + """ + Moves the microscope lift to the lower (0) or upper = lifted (1) position. This + initiates the motion only, the actual movement may take some seconds. + API Status: published + Args: + SetLift:int = 1 + Command Timeout: 10000 + Example:MoveScopeLift 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeLift",SetLift) + + +def ReadTurretStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current status of the motorized turret. + API Status: internal + Returns: + IsMoving:int + Command Timeout: 5000 + Example:ReadTurretStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTurretStatus") + return int(rsp[0]) + +def SelectLens(Lens:int=""): + """ + Parfocality and para-centricity are adjusted according to the stored values. + This can be used with manual turrets to compensate for XYZ differences between + lenses. + API Status: published + Args: + Lens:int = 1 + Command Timeout: 30000 + Example:SelectLens 1 + """ + MessageServerInterface.sendSciCommand("SelectLens",Lens) + + +def GetScopeTable(TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return the TableID Number of the stored chuck table or create a new table. The + ID Number is unique for the name and the chuck. The table itself has a string + name, this name is not case sensitive. This command has to be used before all + other table commands can be used. Accesses to the table is possible only with an + ID Number (name dependet). + API Status: internal + Args: + TableName:str = "ScopeTable" + Returns: + TableID:int + Command Timeout: 5000 + Example:GetScopeTable ScopeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeTable",TableName) + return int(rsp[0]) + +def MoveScopeTablePoint(TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the microscope stage to the specified X,Y position relative to the per + PosRef specified reference position. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Velocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveScopeTablePoint 10 5 67 + """ + MessageServerInterface.sendSciCommand("MoveScopeTablePoint",TableID,PointID,Velocity) + + +def ReadScopeTablePoint(TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read back the scope table site Information for this point from the Kernel. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadScopeTablePoint 2 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTablePoint",TableID,PointID,Unit) + global ReadScopeTablePoint_Response + if not "ReadScopeTablePoint_Response" in globals(): ReadScopeTablePoint_Response = namedtuple("ReadScopeTablePoint_Response", "CoordX,CoordY,CoordSystem") + return ReadScopeTablePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def ReadCurrentLens(): + """ + Returns the number of the current microscope lens. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:ReadCurrentLens + """ + rsp = MessageServerInterface.sendSciCommand("ReadCurrentLens") + return int(rsp[0]) + +def SetScopeTablePoint(TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set one point of the scope table inside of the Kernel. If there is still a point + with this index loaded, the Kernel returns an error. Number of positions and + number of tables are dependet on the internal memory. All positions are stored + persistent, that means after switching power on or off the positions are still + available. The table starts with point number 1 and ends with the ID 16. The + table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ValidPoint:int + Command Timeout: 5000 + Example:SetScopeTablePoint 10 10 8992.5 7883.0 Y H + """ + rsp = MessageServerInterface.sendSciCommand("SetScopeTablePoint",TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + return int(rsp[0]) + +def ClearScopeTablePoint(TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of scope table site points in the Kernel. If Start Point is + -1 or negative the whole table will be deleted. + API Status: internal + Args: + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearScopeTablePoint 2 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearScopeTablePoint",TableID,StartPoint,EndPoint) + global ClearScopeTablePoint_Response + if not "ClearScopeTablePoint_Response" in globals(): ClearScopeTablePoint_Response = namedtuple("ClearScopeTablePoint_Response", "ClearNumber,ValidNumber") + return ClearScopeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ReadScopeSiloCount(): + """ + Returns the number of silos in the scope fence. Will be zero if no silos are + configured. + API Status: published + Returns: + Count:int + Command Timeout: 5000 + Example:ReadScopeSiloCount + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSiloCount") + return int(rsp[0]) + +def ReadProbeStatus(Probe:int=""): + """ + Returns the current positioner's status. + API Status: published + Args: + Probe:int = 1 + Returns: + ProbeEcho:int + FlagsInit:int + FlagsMode:int + FlagsLimit:int + FlagsMoving:int + Comp:str + Side:str + PresetHeight:str + IsLiftUp:int + IsQuiet:int + Command Timeout: 5000 + Example:ReadProbeStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeStatus",Probe) + global ReadProbeStatus_Response + if not "ReadProbeStatus_Response" in globals(): ReadProbeStatus_Response = namedtuple("ReadProbeStatus_Response", "ProbeEcho,FlagsInit,FlagsMode,FlagsLimit,FlagsMoving,Comp,Side,PresetHeight,IsLiftUp,IsQuiet") + return ReadProbeStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str(rsp[5]),str(rsp[6]),str(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadProbePosition(Probe:int="", Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual positioner's position in X, Y and Z. The default Compensation + Mode is the currently activated compensation mode of the kernel. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + ProbeEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadProbePosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbePosition",Probe,Unit,PosRef,Comp) + global ReadProbePosition_Response + if not "ReadProbePosition_Response" in globals(): ReadProbePosition_Response = namedtuple("ReadProbePosition_Response", "ProbeEcho,X,Y,Z") + return ReadProbePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadProbeHeights(Probe:int="", Unit:str=""): + """ + Returns the actual settings for the probe Z movement. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 5000 + Example:ReadProbeHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeHeights",Probe,Unit) + global ReadProbeHeights_Response + if not "ReadProbeHeights_Response" in globals(): ReadProbeHeights_Response = namedtuple("ReadProbeHeights_Response", "ProbeEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadProbeHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def OrientProbe(Probe:int="", Side:str=""): + """ + Defines the orientation of the positioner's coordinate system and turns the + Y-axis of the probe coordinate system. + API Status: published + Args: + Probe:int = 1 + Side:str = "Left" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:OrientProbe 1 R + """ + rsp = MessageServerInterface.sendSciCommand("OrientProbe",Probe,Side) + return int(rsp[0]) + +def InitProbe(Probe:int="", FlagsInit:int="", FlagsDirection:int="", FlagsMoveRange:int="", FlagsInitInPlace:int=""): + """ + Performs an initialization move and resets the coordinate system of the given + positioner. + API Status: published + Args: + Probe:int = 1 + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsMoveRange:int = 0 + FlagsInitInPlace:int = 0 + Returns: + ProbeEcho:int + Command Timeout: 120000 + Example:InitProbe 1 7 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("InitProbe",Probe,FlagsInit,FlagsDirection,FlagsMoveRange,FlagsInitInPlace) + return int(rsp[0]) + +def MoveProbe(Probe:int="", XValue:Decimal="", YValue:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbe 1 1000. 1000. R Y 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbe",Probe,XValue,YValue,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeIndex(Probe:int="", XSteps:int="", YSteps:int="", PosRef:str="", Velocity:Decimal=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + XSteps:int = 0 + YSteps:int = 0 + PosRef:str = "Home" + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeIndex 1 1 1 R 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeIndex",Probe,XSteps,YSteps,PosRef,Velocity) + return int(rsp[0]) + +def MoveProbeContact(Probe:int="", Velocity:Decimal=""): + """ + Moves the given ProbeHeads Z axis to the preset contact height. If no contact + height is set, the kernel will return a 'Contact height not set' error. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeContact 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeContact",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeAlign(Probe:int="", Velocity:Decimal=""): + """ + Moves the given ProbeHeads Z axis to the align height. + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeAlign 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeAlign",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeSeparation(Probe:int="", Velocity:Decimal=""): + """ + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: published + Args: + Probe:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeSeparation 1 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeSeparation",Probe,Velocity) + return int(rsp[0]) + +def MoveProbeZ(Probe:int="", Height:Decimal="", PosRef:str="", Unit:str="", Velocity:Decimal="", Comp:str=""): + """ + Moves a given ProbeHeads Z axis to a defined Z height. + API Status: published + Args: + Probe:int = 1 + Height:Decimal = 0 + PosRef:str = "Zero" + Unit:str = "Microns" + Velocity:Decimal = 100 + Comp:str = "Default" + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeZ 1 1000. R Y 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeZ",Probe,Height,PosRef,Unit,Velocity,Comp) + return int(rsp[0]) + +def MoveProbeLift(Probe:int="", SetLift:int=""): + """ + Moves the positioner to the lower (0) or upper = lifted (1) position. The + command initiates the motion only, the whole movement may take some seconds. + API Status: published + Args: + Probe:int = 1 + SetLift:int = 1 + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:MoveProbeLift 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeLift",Probe,SetLift) + return int(rsp[0]) + +def MoveProbeVelocity(Probe:int="", PolarityX:str="", PolarityY:str="", PolarityZ:str="", VelocityX:Decimal="", VelocityY:Decimal="", VelocityZ:Decimal=""): + """ + '+' Move this axis into plus direction '-' Move this axis into minus direction + '0' Do not change this axis + API Status: published + Args: + Probe:int = 1 + PolarityX:str = "Fixed" + PolarityY:str = "Fixed" + PolarityZ:str = "Fixed" + VelocityX:Decimal = 100 + VelocityY:Decimal = 0 + VelocityZ:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeVelocity 1 + + Z 67 100 0 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeVelocity",Probe,PolarityX,PolarityY,PolarityZ,VelocityX,VelocityY,VelocityZ) + return int(rsp[0]) + +def StopProbeMovement(Probe:int="", FlagsStop:int=""): + """ + Stops positioner movement for the given axes immediately. A smooth stop is + performed. + API Status: published + Args: + Probe:int = 1 + FlagsStop:int = 7 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:StopProbeMovement 1 7 + """ + rsp = MessageServerInterface.sendSciCommand("StopProbeMovement",Probe,FlagsStop) + return int(rsp[0]) + +def SetProbeMode(Probe:int="", Overtravel:int="", AutoZ:int="", Interlock:int="", AutoZFollow:int="", AutoQuiet:int=""): + """ + The mode manages the way the chuck behaves when it is in contact height. + Positioner mode is made up from 5 flags and the user can control all of them by + using this command. Every flag can be turned on by setting value 1, or turned + off by setting value 0. Use the value 2 if no change for a flag is needed. + API Status: published + Args: + Probe:int = 1 + Overtravel:int = 2 + AutoZ:int = 2 + Interlock:int = 2 + AutoZFollow:int = 2 + AutoQuiet:int = 2 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeMode 1 2 2 2 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeMode",Probe,Overtravel,AutoZ,Interlock,AutoZFollow,AutoQuiet) + return int(rsp[0]) + +def SetProbeHome(Probe:int="", Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the positioner's Home position in X and Y. This position identifies the + probe coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + Probe:int = 1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHome",Probe,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetProbeIndex(Probe:int="", XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the positioner's index size or the location of the reference die relative + to the home die. + API Status: published + Args: + Probe:int = 1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeIndex",Probe,XValue,YValue,Unit) + return int(rsp[0]) + +def SetProbeHeight(Probe:int="", PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Defines the predefined contact height and corresponding gaps for overtravel, + align, load and separation height. No data sets contact height at current + position. + API Status: published + Args: + Probe:int = 1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + ProbeEcho:int + Command Timeout: 5000 + Example:SetProbeHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeHeight",Probe,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadProbeIndex(Probe:int="", Unit:str=""): + """ + Returns the current positioner's wafer index values or the current positioner's + index positions for X and Y. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Microns" + Returns: + ProbeEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 5000 + Example:ReadProbeIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeIndex",Probe,Unit) + global ReadProbeIndex_Response + if not "ReadProbeIndex_Response" in globals(): ReadProbeIndex_Response = namedtuple("ReadProbeIndex_Response", "ProbeEcho,IndexX,IndexY") + return ReadProbeIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetProbeLED(Probe:int="", NewLEDState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the positioner LED On or Off. + API Status: internal + Args: + Probe:int = 1 + NewLEDState:int = 0 + Returns: + ProbeEcho:int + LEDState:int + Command Timeout: 5000 + Example:SetProbeLED 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeLED",Probe,NewLEDState) + global SetProbeLED_Response + if not "SetProbeLED_Response" in globals(): SetProbeLED_Response = namedtuple("SetProbeLED_Response", "ProbeEcho,LEDState") + return SetProbeLED_Response(int(rsp[0]),int(rsp[1])) + +def GetProbeTableID(Probe:int="", TableName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the ID of a stored probe table or creates a new table. The ID is unique + for the name and the probe. The table itself has a string name. This name is not + case sensitive. The command has to be used before all other table commands can + be used. Access to tables is possible only with an ID Number (name dependent). + API Status: internal + Args: + Probe:int = 1 + TableName:str = "ProbeTable" + Returns: + ProbeEcho:int + TableID:int + Command Timeout: 5000 + Example:GetProbeTableID 1 ProbeTable + """ + rsp = MessageServerInterface.sendSciCommand("GetProbeTableID",Probe,TableName) + global GetProbeTableID_Response + if not "GetProbeTableID_Response" in globals(): GetProbeTableID_Response = namedtuple("GetProbeTableID_Response", "ProbeEcho,TableID") + return GetProbeTableID_Response(int(rsp[0]),int(rsp[1])) + +def MoveProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves a defined positioner to a X, Y position relative to a per PosRef specified + reference position. Notifications: 51 / 52 / 5 + API Status: internal + Args: + Probe:int = 1 + TableID:int = 1 + PointID:int = 1 + Velocity:Decimal = 100 + Returns: + ProbeEcho:int + Command Timeout: 30000 + Example:MoveProbeTablePoint 3 14 10 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveProbeTablePoint",Probe,TableID,PointID,Velocity) + return int(rsp[0]) + +def ReadProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads the data from a point of a stored table in the Kernel. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + Unit:str = "Microns" + Returns: + ProbeEcho:int + CoordX:Decimal + CoordY:Decimal + CoordSystem:str + Command Timeout: 5000 + Example:ReadProbeTablePoint 2 4 10 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTablePoint",Probe,TableID,PointID,Unit) + global ReadProbeTablePoint_Response + if not "ReadProbeTablePoint_Response" in globals(): ReadProbeTablePoint_Response = namedtuple("ReadProbeTablePoint_Response", "ProbeEcho,CoordX,CoordY,CoordSystem") + return ReadProbeTablePoint_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetProbeTablePoint(Probe:int="", TableID:int="", PointID:int="", CoordX:Decimal="", CoordY:Decimal="", Unit:str="", CoordSystem:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets one point of a ProbeHeads table inside the Kernel. If there is still a + point with this index loaded, the Kernel returns an error. Number of positions + and number of tables are dependet on the internal memory. All positions are + stored persistent, that means after switching power on or off the positions are + still available. The table starts with point number 1 and ends with the ID 16. + The table can contain 65535 points with the ID 0 up to 65534. Overwriting of + position points is not possible. The point has to be deleted before other values + are set. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + PointID:int = 0 + CoordX:Decimal = 0 + CoordY:Decimal = 0 + Unit:str = "Microns" + CoordSystem:str = "HomeSystem" + Returns: + ProbeEcho:int + ValidPoint:int + Command Timeout: 5000 + Example:SetProbeTablePoint 3 12 10 8992.5 7883.0 Y Z M + """ + rsp = MessageServerInterface.sendSciCommand("SetProbeTablePoint",Probe,TableID,PointID,CoordX,CoordY,Unit,CoordSystem) + global SetProbeTablePoint_Response + if not "SetProbeTablePoint_Response" in globals(): SetProbeTablePoint_Response = namedtuple("SetProbeTablePoint_Response", "ProbeEcho,ValidPoint") + return SetProbeTablePoint_Response(int(rsp[0]),int(rsp[1])) + +def ClearProbeTablePoint(Probe:int="", TableID:int="", StartPoint:int="", EndPoint:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clear one or a range of ProbeHead table site points in the Kernel. If StartPoint + is a negative value, the whole table will be deleted. + API Status: internal + Args: + Probe:int = 1 + TableID:int = 0 + StartPoint:int = -1 + EndPoint:int = 0 + Returns: + ProbeEcho:int + ClearNumber:int + ValidNumber:int + Command Timeout: 5000 + Example:ClearProbeTablePoint 3 4 10 15 + """ + rsp = MessageServerInterface.sendSciCommand("ClearProbeTablePoint",Probe,TableID,StartPoint,EndPoint) + global ClearProbeTablePoint_Response + if not "ClearProbeTablePoint_Response" in globals(): ClearProbeTablePoint_Response = namedtuple("ClearProbeTablePoint_Response", "ProbeEcho,ClearNumber,ValidNumber") + return ClearProbeTablePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def MoveScopeSilo(Index:int=""): + """ + Move the scope to the reference position of the given silo. The reference + position should be - if not defined otherwise - 200 um above the safe z-height + in the center of the scope. + API Status: published + Args: + Index:int = 1 + Command Timeout: 70000 + Example:MoveScopeSilo 1 + """ + MessageServerInterface.sendSciCommand("MoveScopeSilo",Index) + + +def SetScopeSiloReference(Index:int="", X:Decimal="", Y:Decimal="", Z:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the reference position of a silo. The next time the scope moves to this + silo, it woll go to this position. The Referenceposition must be inside the silo + in xy and above the lower Z-Fence of the silo. Setting the reference position + directly on the fence in x, y or z typically leads to errors. Try to keep a + safety margin. + API Status: internal + Args: + Index:int = 1 + X:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + Command Timeout: 5000 + Example:SetScopeSiloReference 1 1000 2000 3000 + """ + MessageServerInterface.sendSciCommand("SetScopeSiloReference",Index,X,Y,Z) + + +def AlignChuckTheta(XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a chuck Theta axis rotation to align the wafer to the chuck + X,Y movements. It can be used to perform a two point alignment with + P1(X1,Y1) and P2(X2,Y2) as two points on a wafer street line. The units of + the distances are not important - but both distances should use the same unit. + If one or both distances are zero, the command does not return an error and + instead ignore this alignment + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignChuckTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignChuckTheta",XDistance,YDistance,PosRef) + + +def AlignScopeTheta(XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a virtual rotation of the scope coordinate system to align + the scope to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of X and Y distances: + API Status: published + Args: + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignScopeTheta 10000 10 R + """ + MessageServerInterface.sendSciCommand("AlignScopeTheta",XDistance,YDistance,PosRef) + + +def AlignProbeTheta(Probe:int="", XDistance:Decimal="", YDistance:Decimal="", PosRef:str=""): + """ + This command causes a rotation of the coordinate system of given probe to align + the probe to the chuck X,Y axis or/and to the wafer alignment. It can be used to + perform a two point alignment with the points P1(X1,Y1) and P2(X2,Y2). + Calculation of Y and Y distances: + API Status: published + Args: + Probe:int = 1 + XDistance:Decimal = 0 + YDistance:Decimal = 0 + PosRef:str = "Relative" + Returns: + ProbeEcho:int + Command Timeout: 10000 + Example:AlignProbeTheta 1 10000 10 R + """ + rsp = MessageServerInterface.sendSciCommand("AlignProbeTheta",Probe,XDistance,YDistance,PosRef) + return int(rsp[0]) + +def AlignCardTheta(Angle:Decimal="", Unit:str="", PosRef:str=""): + """ + This command causes a rotation of the chuck coordinate system to align the chuck + X, Y axis to the probecard. The polarity of the data determines a left or a + right rotation of the chuck coordinate system. + API Status: published + Args: + Angle:Decimal = 0 + Unit:str = "Degrees" + PosRef:str = "Relative" + Command Timeout: 10000 + Example:AlignCardTheta 2.5 D R + """ + MessageServerInterface.sendSciCommand("AlignCardTheta",Angle,Unit,PosRef) + + +def ReadCardTheta(Unit:str=""): + """ + Returns the angle between the chuck-coordinate-system and the probecard- + coordinate-system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadCardTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadCardTheta",Unit) + return Decimal(rsp[0]) + +def ReadChuckTheta(Unit:str=""): + """ + Returns the current chuck alignment angle which is identical to the current + value of theta rotation. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadChuckTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckTheta",Unit) + return Decimal(rsp[0]) + +def ReadScopeTheta(Unit:str=""): + """ + Returns the scope's alignment angle, which is the angle between the chuck + coordinate system and the scope coordinate system. + API Status: published + Args: + Unit:str = "Degrees" + Returns: + Angle:Decimal + Command Timeout: 5000 + Example:ReadScopeTheta D + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeTheta",Unit) + return Decimal(rsp[0]) + +def ReadProbeTheta(Probe:int="", Unit:str=""): + """ + Returns the actual positioner's alignment angle, which is the angle between the + chuck coordinate system and the positioner coordinate system. + API Status: published + Args: + Probe:int = 1 + Unit:str = "Degrees" + Returns: + ProbeEcho:int + Angle:Decimal + Command Timeout: 5000 + Example:ReadProbeTheta 1 D + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeTheta",Probe,Unit) + global ReadProbeTheta_Response + if not "ReadProbeTheta_Response" in globals(): ReadProbeTheta_Response = namedtuple("ReadProbeTheta_Response", "ProbeEcho,Angle") + return ReadProbeTheta_Response(int(rsp[0]),Decimal(rsp[1])) + +def ReadJoystickSpeeds(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the preset speeds, which are used by the joystick controller for moving a + single stage. The speeds can be read for XY, for Z and for Theta axis + separately. Jog timing and index timing are the times, the joystick controller + waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "X" + Returns: + JogTime:Decimal + Speed2:Decimal + Speed3:Decimal + Speed4:Decimal + IndexTime:Decimal + Command Timeout: 5000 + Example:ReadJoystickSpeeds S Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeeds",Stage,Axis) + global ReadJoystickSpeeds_Response + if not "ReadJoystickSpeeds_Response" in globals(): ReadJoystickSpeeds_Response = namedtuple("ReadJoystickSpeeds_Response", "JogTime,Speed2,Speed3,Speed4,IndexTime") + return ReadJoystickSpeeds_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetJoystickSpeeds(Stage:str="", JogTime:Decimal="", Speed2:Decimal="", Speed3:Decimal="", Speed4:Decimal="", IndexTime:Decimal="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the preset speeds, which are used by the joystick controller for moving a + single stage. After setting, the speeds can be selected by pressing the Speed n + buttons at the controller. The speeds must be set separately for XY, for Z and + for Theta axis. Jog timing and index timing are the times, the joystick + controller waits between two single jog or index moves. + API Status: internal + Args: + Stage:str = "Chuck" + JogTime:Decimal = 0 + Speed2:Decimal = 0 + Speed3:Decimal = 0 + Speed4:Decimal = 0 + IndexTime:Decimal = 0 + Axis:str = "X" + Command Timeout: 5000 + Example:SetJoystickSpeeds S 10 20 30 40 50 Z + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeeds",Stage,JogTime,Speed2,Speed3,Speed4,IndexTime,Axis) + + +def SetLoaderGate(Open:int=""): + """ + Opens or closes the loader gate. Automatic handling systems can load wafers to + the chuck through the gate. + API Status: published + Args: + Open:int = 0 + Command Timeout: 5000 + Example:SetLoaderGate 0 + """ + MessageServerInterface.sendSciCommand("SetLoaderGate",Open) + + +def ReadWaferStatus(): + """ + Returns whether the system detected a wafer. This feature can be used if the + probe station is equipped with a vacuum sensor and while vacuum is activated. + API Status: published + Returns: + SensedByVac:str + Command Timeout: 5000 + Example:ReadWaferStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadWaferStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadContactCount(Stage:str=""): + """ + Returns the number of times this stage moved to contact since the last time the + counter was reset. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Count:int + Command Timeout: 5000 + Example:ReadContactCount C + """ + rsp = MessageServerInterface.sendSciCommand("ReadContactCount",Stage) + return int(rsp[0]) + +def ResetContactCount(Stage:str=""): + """ + Resets the contact counter for the specified stage to zero. Notifications: 23 + API Status: published + Args: + Stage:str = "Chuck" + Command Timeout: 5000 + Example:ResetContactCount C + """ + MessageServerInterface.sendSciCommand("ResetContactCount",Stage) + + +def SetManualMode(Enable:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command enables the manual mode on Elite/Summit/S300 systems. This mode + will allow to move the chuck using the knobs. + API Status: internal + Args: + Enable:int = 1 + Command Timeout: 10000 + Example:SetManualMode 1 + """ + MessageServerInterface.sendSciCommand("SetManualMode",Enable) + + +def GetManualMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of the manual mode on Elite/Summit/S300 stations. + API Status: internal + Returns: + Enable:int + Command Timeout: 10000 + Example:GetManualMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetManualMode") + return int(rsp[0]) + +def GetAxisReverse(Stage:str="", Axis:str=""): + """ + Allows reading if an axis is reverse. + API Status: published + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + IsReverse:int + Command Timeout: 5000 + Example:GetAxisReverse C X + """ + rsp = MessageServerInterface.sendSciCommand("GetAxisReverse",Stage,Axis) + return int(rsp[0]) + +def EnableEdgeSensor(EdgeSensor:int="", Enable:int=""): + """ + Enables/disables the use of an edge sensor. + API Status: published + Args: + EdgeSensor:int = 1 + Enable:int = 1 + Command Timeout: 5000 + Example:EnableEdgeSensor 1 1 + """ + MessageServerInterface.sendSciCommand("EnableEdgeSensor",EdgeSensor,Enable) + + +def SetTypedOutput(Channel:str="", WantOutputOn:int="", PulseTime:int=""): + """ + Controls the kernel valve driver signals and can be used to drive the outputs. + API Status: published + Args: + Channel:str = "NoSensor" + WantOutputOn:int = 0 + PulseTime:int = -1 + Command Timeout: 5000 + Example:SetTypedOutput WaferVacuum 1 + """ + MessageServerInterface.sendSciCommand("SetTypedOutput",Channel,WantOutputOn,PulseTime) + + +def ReadTypedSensor(Channel:str=""): + """ + Returns the status of the specified input channel, output channel, or edge + sensor. + API Status: published + Args: + Channel:str = "NoSensor" + Returns: + IsSensorOn:int + Command Timeout: 10000 + Example:ReadTypedSensor EmoIn I + """ + rsp = MessageServerInterface.sendSciCommand("ReadTypedSensor",Channel) + return int(rsp[0]) + +def MoveCoolDownPosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck to the cool down position that is defined in KernelSetup. The + cooldown position is used to move the chuck away in XY while the robot is in the + chamber and tries to get a hot wafer. + API Status: internal + Command Timeout: 30000 + Example:MoveCoolDownPosition + """ + MessageServerInterface.sendSciCommand("MoveCoolDownPosition") + + +def ReadJoystickSpeedsCycle(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the cycling speeds - these are the speeds that are used by + the USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + CycleJog:int + CycleSpeed2:int + CycleSpeed3:int + CycleSpeed4:int + CycleIndex:int + Command Timeout: 5000 + Example:ReadJoystickSpeedsCycle S + """ + rsp = MessageServerInterface.sendSciCommand("ReadJoystickSpeedsCycle",Stage) + global ReadJoystickSpeedsCycle_Response + if not "ReadJoystickSpeedsCycle_Response" in globals(): ReadJoystickSpeedsCycle_Response = namedtuple("ReadJoystickSpeedsCycle_Response", "CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex") + return ReadJoystickSpeedsCycle_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetJoystickSpeedsCycle(Stage:str="", CycleJog:int="", CycleSpeed2:int="", CycleSpeed3:int="", CycleSpeed4:int="", CycleIndex:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets the cycling speeds - these are the speeds that are used by the + USB joystick when cycling through the speeds. Can be setup in ControlCenter. + API Status: internal + Args: + Stage:str = "Chuck" + CycleJog:int = 0 + CycleSpeed2:int = 0 + CycleSpeed3:int = 0 + CycleSpeed4:int = 0 + CycleIndex:int = 0 + Command Timeout: 5000 + Example:SetJoystickSpeedsCycle C 1 1 1 1 1 + """ + MessageServerInterface.sendSciCommand("SetJoystickSpeedsCycle",Stage,CycleJog,CycleSpeed2,CycleSpeed3,CycleSpeed4,CycleIndex) + + +def SendAUCSCommand(Command:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows sending low level AUCS commands to the ECX box stage. Only + applies to Elite/Summit/S300 stations. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 60000 + Example:SendAUCSCommand "MM 1 0 INIT 0" + """ + rsp = MessageServerInterface.sendSciCommand("SendAUCSCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadCompensationStatus(Stage:str="", Compensation:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command allows reading if a specific type of compensation is enabled or + disabled. Returns an error if this type of compensation is not available for + this stage. + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Returns: + Enabled:int + Active:int + Command Timeout: 5000 + Example:ReadCompensationStatus C A + """ + rsp = MessageServerInterface.sendSciCommand("ReadCompensationStatus",Stage,Compensation) + global ReadCompensationStatus_Response + if not "ReadCompensationStatus_Response" in globals(): ReadCompensationStatus_Response = namedtuple("ReadCompensationStatus_Response", "Enabled,Active") + return ReadCompensationStatus_Response(int(rsp[0]),int(rsp[1])) + +def RegisterNotification(NotificationCode:int="", WantNotification:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deprecated. All Kernel notifications are now enabled by default. + API Status: internal + Args: + NotificationCode:int = 0 + WantNotification:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterNotification",NotificationCode,WantNotification) + + +def AlertNotification(NotificationId:int="", Value1:Decimal="", Value2:Decimal="", Value3:Decimal=""): + """ + This is not a regular command. Asynchronous notifications will be sent from the + Kernel controller to the host system only. All notifications can be switched off + and on, except the Prober reset notification (ID01). /warning This is a stub + implementation without appropriate handling + API Status: published + Args: + NotificationId:int = 0 + Value1:Decimal = 0 + Value2:Decimal = 0 + Value3:Decimal = 0 + Command Timeout: 5000 + Example:AlertNotification 31 195000 160000 0 + """ + MessageServerInterface.sendSciCommand("AlertNotification",NotificationId,Value1,Value2,Value3) + + +def SetCompensationStatus(Stage:str="", Compensation:str="", Status:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables a compensation mode for the specified stage + API Status: internal + Args: + Stage:str = "None" + Compensation:str = "None" + Status:int = -1 + Command Timeout: 5000 + Example:SetCompensationStatus C A 1 + """ + MessageServerInterface.sendSciCommand("SetCompensationStatus",Stage,Compensation,Status) + + +def GetControllerInfo(ControllerInfo:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command gets the value "Value" for the parameter "Parameter". The unit is + parameter specific. + API Status: internal + Args: + ControllerInfo:str = "Unknown" + Returns: + Value:Decimal + Command Timeout: 1000 + Example:GetControllerInfo HasScanChuckZ + """ + rsp = MessageServerInterface.sendSciCommand("GetControllerInfo",ControllerInfo) + return Decimal(rsp[0]) + +def SetOperationalMode(OperationalMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + In unprotected mode a number of security features like software fence and + initialization necessity are deactivated. Unprotected mode is + deactivated automatically after 5 minutes. Sending 'SetOperationalMode U' + anytime before resets the timer back to 5 minutes. It is not necessary to + deactivate it before. **WARNING**: If unprotected mode is enabled, even the + most basic safety- and sanity-checks are skipped. Any movement may cause + irreparable damage to the prober or attached hardware. + API Status: internal + Args: + OperationalMode:str = "ProtectedMode" + Command Timeout: 5000 + Example:SetOperationalMode P + """ + MessageServerInterface.sendSciCommand("SetOperationalMode",OperationalMode) + + +def GetNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured Nano-chamber-state. + API Status: internal + Returns: + NanoChamberState:str + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetNanoChamberState(NanoChamberState:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the NanoChamber-state. + API Status: internal + Args: + NanoChamberState:str = "Free" + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetNanoChamberState",NanoChamberState) + + +def SetCameraCool(State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows to force activate/deactivate the camera cool output or to let it be set + automatically by purge control. + API Status: internal + Args: + State:int = 2 + Command Timeout: 10000 + Example:SetCameraCool 0 + """ + MessageServerInterface.sendSciCommand("SetCameraCool",State) + + +def ActivateChuckVacuum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the chuck vacuum and forces it to be on. This command ignores the + vacuum sensor and timeout. + API Status: internal + Command Timeout: 10000 + Example:ActivateChuckVacuum + """ + MessageServerInterface.sendSciCommand("ActivateChuckVacuum") + + +def ReadMatrixValues(Stage:str="", MatrixIndexX:int="", MatrixIndexY:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns a point from the matrix compensation table for the + specified axis from the kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + Returns: + XVal:Decimal + YVal:Decimal + Command Timeout: 5000 + Example:ReadMatrixValues C 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMatrixValues",Stage,MatrixIndexX,MatrixIndexY) + global ReadMatrixValues_Response + if not "ReadMatrixValues_Response" in globals(): ReadMatrixValues_Response = namedtuple("ReadMatrixValues_Response", "XVal,YVal") + return ReadMatrixValues_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetMatrixValues(Stage:str="", MatrixIndexX:int="", MatrixIndexY:int="", XVal:Decimal="", YVal:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Downloads a point of the matrix compensation table for a specified stage to the + kernel. All command parameters are mandatory. + API Status: internal + Args: + Stage:str = "Chuck" + MatrixIndexX:int = 0 + MatrixIndexY:int = 0 + XVal:Decimal = 0 + YVal:Decimal = 0 + Command Timeout: 5000 + Example:SetMatrixValues C 0 0 5000.0 5000.0 2500.0 + """ + MessageServerInterface.sendSciCommand("SetMatrixValues",Stage,MatrixIndexX,MatrixIndexY,XVal,YVal) + + +def ReadMEAStatus(Stage:str="", Type:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads if the MEA file for a stage is loaded/enabled (Nucleus legacy stations + only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Returns: + Enable:int + Command Timeout: 5000 + Example:ReadMEAStatus C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMEAStatus",Stage,Type) + return int(rsp[0]) + +def LoadMEAFile(Stage:str="", Type:int="", Load:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Load the MEA file for a stage (Nucleus legacy stations only) + API Status: internal + Args: + Stage:str = "Chuck" + Type:int = 0 + Load:int = 0 + Command Timeout: 5000 + Example:LoadMEAFile C 0 1 + """ + MessageServerInterface.sendSciCommand("LoadMEAFile",Stage,Type,Load) + + +def ReadSoftwareLimits(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The command returns the positions of the actual software limits (end of move + range) for each axis of the specified stage in microns. If the Theta stage is + selected Z1 and Z2 include the values for the Theta limits. + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + ZLowValue:Decimal + ZHighValue:Decimal + X1Value:Decimal + Y1Value:Decimal + X2Value:Decimal + Y2Value:Decimal + X3Value:Decimal + Y3Value:Decimal + X4Value:Decimal + Y4Value:Decimal + Command Timeout: 5000 + Example:ReadSoftwareLimits C + """ + rsp = MessageServerInterface.sendSciCommand("ReadSoftwareLimits",Stage) + global ReadSoftwareLimits_Response + if not "ReadSoftwareLimits_Response" in globals(): ReadSoftwareLimits_Response = namedtuple("ReadSoftwareLimits_Response", "ZLowValue,ZHighValue,X1Value,Y1Value,X2Value,Y2Value,X3Value,Y3Value,X4Value,Y4Value") + return ReadSoftwareLimits_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def SetSoftwareFence(Stage:str="", AuxID:int="", FenceForm:str="", XBase:Decimal="", YBase:Decimal="", XDist:Decimal="", YDist:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command sets types and dimensions of technological software fences. It can + also be used for enabling and disabling the software fence. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + FenceForm:str = "None" + XBase:Decimal = 0 + YBase:Decimal = 0 + XDist:Decimal = 0 + YDist:Decimal = 0 + Command Timeout: 10000 + Example:SetSoftwareFence C 0 R 5000 5000 25000 25000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareFence",Stage,AuxID,FenceForm,XBase,YBase,XDist,YDist) + + +def GetSoftwareFence(Stage:str="", AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the type and the dimensions of an actual set technological + software fence. In case of a rectangular software fence, X and Y coordinates of + the four edge points of the fence are given back. In case of a circular software + fence, X and Y coordinates of the center point and the radius are given back. + All other return values are filled with zeros. All position values are in + microns from zero. + API Status: internal + Args: + Stage:str = "Chuck" + AuxID:int = 0 + Returns: + FenceForm:str + XValue1:Decimal + YValue1:Decimal + XValue2:Decimal + YValue2:Decimal + XValue3:Decimal + YValue3:Decimal + XValue4:Decimal + YValue4:Decimal + Command Timeout: 10000 + Example:GetSoftwareFence C + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareFence",Stage,AuxID) + global GetSoftwareFence_Response + if not "GetSoftwareFence_Response" in globals(): GetSoftwareFence_Response = namedtuple("GetSoftwareFence_Response", "FenceForm,XValue1,YValue1,XValue2,YValue2,XValue3,YValue3,XValue4,YValue4") + return GetSoftwareFence_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8])) + +def GetZFence(Stage:str="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands reads if the Z-Fence is activated and the currently set Z-fence + values for the specified stage. + API Status: internal + Args: + Stage:str = "Chuck" + CompLayer:str = "Default" + Returns: + Enabled:int + ZLow:Decimal + ZHigh:Decimal + Command Timeout: 10000 + Example:GetZFence S + """ + rsp = MessageServerInterface.sendSciCommand("GetZFence",Stage,CompLayer) + global GetZFence_Response + if not "GetZFence_Response" in globals(): GetZFence_Response = namedtuple("GetZFence_Response", "Enabled,ZLow,ZHigh") + return GetZFence_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetZFence(Stage:str="", Enabled:int="", ZLow:Decimal="", ZHigh:Decimal="", CompLayer:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This commands sets Z-Fence and the Z-fence values for the specified stage. + Values are stored uncompensated internally and set default compensated as + default. + API Status: internal + Args: + Stage:str = "Chuck" + Enabled:int = 0 + ZLow:Decimal = 0 + ZHigh:Decimal = 0 + CompLayer:str = "Default" + Command Timeout: 10000 + Example:SetZFence S 1 5000 10000 + """ + MessageServerInterface.sendSciCommand("SetZFence",Stage,Enabled,ZLow,ZHigh,CompLayer) + + +def ResetProber(Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the Prober and replaces the current configuration with a formerly + written recovery file. If no recovery file was written, the configuration is + reset to the version of the last Prober restart. For ProberBench electronics, + 'H' will restart the Operating system, 'S' will only restart the Kernel + application. For Windows Kernel, 'H' and 'S' are identical. + API Status: internal + Args: + Mode:str = "S" + Command Timeout: 20000 + Example:ResetProber S + """ + MessageServerInterface.sendSciCommand("ResetProber",Mode) + + +def ResetCBox(ResetMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reboots the operation system inside the Joystick Controller and restarts the + functionality. The restart will need a time of around 20 seconds. + API Status: internal + Args: + ResetMode:str = "S" + Command Timeout: 20000 + Example:ResetCBox S + """ + MessageServerInterface.sendSciCommand("ResetCBox",ResetMode) + + +def ReadStageLocations(Stage:str="", LocationType:str="", AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The Home Position on the Chuck or ProbeHead Z axis is also called contact + height. The Home Position on the Scope Z axis is also called focus height. + API Status: internal + Args: + Stage:str = "Chuck" + LocationType:str = "Center" + AuxID:int = 0 + Returns: + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 5000 + Example:ReadStageLocations C C 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReadStageLocations",Stage,LocationType,AuxID) + global ReadStageLocations_Response + if not "ReadStageLocations_Response" in globals(): ReadStageLocations_Response = namedtuple("ReadStageLocations_Response", "X,Y,Z") + return ReadStageLocations_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def GetDataIterator(ShowAll:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters. + and requires the GetNextDatum command. + API Status: internal + Args: + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 10000 + Example:GetDataIterator 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetDataIterator",ShowAll) + global GetDataIterator_Response + if not "GetDataIterator_Response" in globals(): GetDataIterator_Response = namedtuple("GetDataIterator_Response", "IdentityToken,SizeNoAll") + return GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def GetNextDatum(IdentityToken:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + Attributes:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:GetNextDatum 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetNextDatum",IdentityToken) + global GetNextDatum_Response + if not "GetNextDatum_Response" in globals(): GetNextDatum_Response = namedtuple("GetNextDatum_Response", "IsLastDatum,DatumCode,Attributes,PathNameDescrValue") + return GetNextDatum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetDatum(PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:SetDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetDatum",PathNameAndValue) + + +def GetDatum(PathName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + PathName:str = "" + Returns: + Attributes:int + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:GetDatum Chuck:AlignGap + """ + rsp = MessageServerInterface.sendSciCommand("GetDatum",PathName) + global GetDatum_Response + if not "GetDatum_Response" in globals(): GetDatum_Response = namedtuple("GetDatum_Response", "Attributes,DatumCode,ValueDesc") + return GetDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def SetRecoveryDatum(PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + PathNameAndValue:str = "" + Command Timeout: 5000 + Example:SetRecoveryDatum Chuck:AlignGap:25 + """ + MessageServerInterface.sendSciCommand("SetRecoveryDatum",PathNameAndValue) + + +def TraceStart(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the motion recording. The recording parameters are set in dynamic + kernel setup. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStart C + """ + MessageServerInterface.sendSciCommand("TraceStart",Controller) + + +def TraceStatus(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Checks the motion recording status for one stage. + API Status: internal + Args: + Controller:str = "Chuck" + Returns: + IsReady:int + SizeCh0Raw:int + SizeCh0Comp:int + SizeCh1Raw:int + SizeCh1Comp:int + SizeCh2Raw:int + SizeCh2Comp:int + SizeCh3Raw:int + SizeCh3Comp:int + Command Timeout: 10000 + Example:TraceStatus C + """ + rsp = MessageServerInterface.sendSciCommand("TraceStatus",Controller) + global TraceStatus_Response + if not "TraceStatus_Response" in globals(): TraceStatus_Response = namedtuple("TraceStatus_Response", "IsReady,SizeCh0Raw,SizeCh0Comp,SizeCh1Raw,SizeCh1Comp,SizeCh2Raw,SizeCh2Comp,SizeCh3Raw,SizeCh3Comp") + return TraceStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8])) + +def TraceGetData(Controller:str="", Channel:int="", PointOne:int="", IsCompress:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a collection of five data pairs. A pair is the index and the value of a + recording point. If the stream is empty or at the end the index is 1 and the + value 0. The index is relative to the start of the motion recording. The + recording is clocked by the motion controller cycle. The cycle time is contained + in the Kernel setup. In the raw stream all recorded trace points are contained. + But in the compressed stream only the non-linear depending trace points are + contained. To reload the recording points the stream must be reset to the first + recording point. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + PointOne:int = 1 + IsCompress:int = 1 + Returns: + Point1:int + Value1:int + Point2:int + Value2:int + Point3:int + Value3:int + Point4:int + Value4:int + Point5:int + Value5:int + Command Timeout: 10000 + Example:TraceGetData C 0 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("TraceGetData",Controller,Channel,PointOne,IsCompress) + global TraceGetData_Response + if not "TraceGetData_Response" in globals(): TraceGetData_Response = namedtuple("TraceGetData_Response", "Point1,Value1,Point2,Value2,Point3,Value3,Point4,Value4,Point5,Value5") + return TraceGetData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def TraceSetDataPosition(Controller:str="", Channel:int="", NewPos:int="", IsCompress:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the index position in the raw or compressed stream for the next call of the + command TraceGetData. + API Status: internal + Args: + Controller:str = "Chuck" + Channel:int = 0 + NewPos:int = 0 + IsCompress:int = 1 + Command Timeout: 10000 + Example:TraceSetDataPosition C 0 1000 1 + """ + MessageServerInterface.sendSciCommand("TraceSetDataPosition",Controller,Channel,NewPos,IsCompress) + + +def TraceStop(Controller:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the motion recording. + API Status: internal + Args: + Controller:str = "Chuck" + Command Timeout: 10000 + Example:TraceStop C + """ + MessageServerInterface.sendSciCommand("TraceStop",Controller) + + +def SetZProfilePoint(Stage:str="", XValue:Decimal="", YValue:Decimal="", ZGap:Decimal="", PosRef:str="", Unit:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set a point for the Z height profile. If this profile is enabled, the Z height + depends on a X and Y coordinate. The Z value is a gap to the current Z height. + Positive values are elevated spots, negative values are hollows. The height + profile is used to adjust the Z height. The adjusted Z height at a X and Y + position is derivated from the nearest profile point. The Z contact level will + be calculated from the contact height and the stored Z gap at this point. See + GetZProfilePoint for details. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + ZGap:Decimal = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + ValueCount:int + Command Timeout: 5000 + Example:SetZProfilePoint C 5000 5000 -3 H Y + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfilePoint",Stage,XValue,YValue,ZGap,PosRef,Unit,ZProfileType) + return int(rsp[0]) + +def ReadZProfilePoint(Stage:str="", Index:int="", PosRef:str="", Unit:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get a single point and the corresponding Z gap of the Z height profile. The + different z profiles are: - transient: meant to be used on a per-wafer-basis, + default - persistent: configured once, stays in memory - persistent-offset: same + as persistent, active when offset is enabled - scratch: not used internaly. Can + be used to translate KernelDatums <-> ZProfile-Points + API Status: internal + Args: + Stage:str = "Chuck" + Index:int = 0 + PosRef:str = "Home" + Unit:str = "Microns" + ZProfileType:int = 0 + Returns: + XValue:Decimal + YValue:Decimal + ZGap:Decimal + ValueCount:int + Command Timeout: 5000 + Example:ReadZProfilePoint C 1 H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfilePoint",Stage,Index,PosRef,Unit,ZProfileType) + global ReadZProfilePoint_Response + if not "ReadZProfilePoint_Response" in globals(): ReadZProfilePoint_Response = namedtuple("ReadZProfilePoint_Response", "XValue,YValue,ZGap,ValueCount") + return ReadZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3])) + +def ClearZProfile(Stage:str="", ZProfileType:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Clears all profile points. See GetZProfile for type description. + API Status: internal + Args: + Stage:str = "Chuck" + ZProfileType:int = 0 + Command Timeout: 5000 + Example:ClearZProfile C + """ + MessageServerInterface.sendSciCommand("ClearZProfile",Stage,ZProfileType) + + +def ReadScopeSilo(Index:int=""): + """ + Returns the definition of a silo. If the type is rectangle, center means + _Point1_. If the type is circle, the meaning of Pos2X and Pos2Y is undefined. + API Status: published + Args: + Index:int = 1 + Returns: + Type:str + CenterX:Decimal + CenterY:Decimal + Radius:Decimal + Pos2X:Decimal + Pos2Y:Decimal + ZHigh:Decimal + RefX:Decimal + RefY:Decimal + RefZ:Decimal + Command Timeout: 5000 + Example:ReadScopeSilo 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSilo",Index) + global ReadScopeSilo_Response + if not "ReadScopeSilo_Response" in globals(): ReadScopeSilo_Response = namedtuple("ReadScopeSilo_Response", "Type,CenterX,CenterY,Radius,Pos2X,Pos2Y,ZHigh,RefX,RefY,RefZ") + return ReadScopeSilo_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7]),Decimal(rsp[8]),Decimal(rsp[9])) + +def NewProjectFile(FileName:str=""): + """ + Alerts applications if the project file was changed. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("NewProjectFile",FileName) + + +def SaveProjectFile(FileName:str=""): + """ + Alerts applications to save the current project. This notification _MUST_ only + be invoked by CommonCommands. Sending this notification directly _WILL_ give + erroneous results. + API Status: published + Args: + FileName:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectFile",FileName) + + +def NewAccessLevel(AccessLevel:str="", UserName:str="", VeloxLocked:int=""): + """ + Alerts applications of new access level. + API Status: published + Args: + AccessLevel:str = "Engineer" + UserName:str = "" + VeloxLocked:int = 0 + Command Timeout: 5000 + Example:NewAccessLevel 1 + """ + MessageServerInterface.sendSciCommand("NewAccessLevel",AccessLevel,UserName,VeloxLocked) + + +def LicenseInfo(AnnualEnabled:int="", AnnualDaysLeft:int="", VeloxProEnabled:int="", VueTrackEnabled:int="", VueTrack4PEnabled:int="", ReAlignEnabled:int="", AutomationEnabled:int="", IdToolsEnabled:int="", IVistaEnabled:int="", IVistaProEnabled:int="", LaserCutterEnabled:int="", SiPToolsEnabled:int="", AutoRfEnabled:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener about the licensed Velox features. Is sent cyclically by + CommonCommands. + API Status: internal + Args: + AnnualEnabled:int = 1 + AnnualDaysLeft:int = 460 + VeloxProEnabled:int = 0 + VueTrackEnabled:int = 0 + VueTrack4PEnabled:int = 0 + ReAlignEnabled:int = 0 + AutomationEnabled:int = 0 + IdToolsEnabled:int = 0 + IVistaEnabled:int = 0 + IVistaProEnabled:int = 0 + LaserCutterEnabled:int = 0 + SiPToolsEnabled:int = 0 + AutoRfEnabled:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicenseInfo",AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled) + + +def RegisterProberAppChange(AppName:str="", SecName:str="", NewRegistered:int=""): + """ + Alerts applications that an application is registered or unregistered on + MsgServer. + API Status: published + Args: + AppName:str = "SharedTest" + SecName:str = "SharedTest" + NewRegistered:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("RegisterProberAppChange",AppName,SecName,NewRegistered) + + +def AlignmentModeChange(AlignmentMode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications of a change of the current alignment mode + API Status: internal + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + Example:AlignmentModeChange OnAxis + """ + MessageServerInterface.sendSciCommand("AlignmentModeChange",AlignmentMode) + + +def KernelConnectionStatus(ControllerNum:int="", Type:str="", Result:str="", Desc:str=""): + """ + An example of Kernel Connection Status is "Windows Socket Error Number and + Error Description." + API Status: published + Args: + ControllerNum:int = 1 + Type:str = "Socket" + Result:str = "Disconnected" + Desc:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelConnectionStatus",ControllerNum,Type,Result,Desc) + + +def KernelCompensationStatusChange(Stage:str="", Compensation:str="", Enabled:int="", Active:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Compensation:str = "None" + Enabled:int = 0 + Active:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationStatusChange",Stage,Compensation,Enabled,Active) + + +def KernelCompensationLevelChange(Stage:str="", Comp:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Alerts applications that a Kernel compensation level has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Comp:str = "None" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelCompensationLevelChange",Stage,Comp) + + +def MoveZCombinedStatusChange(Status:str="", PlatenSafe:int="", Height:Decimal="", HeightMax:Decimal="", HeightRelative:Decimal="", SafeHeight:Decimal="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the combined-z-move-system + API Status: internal + Args: + Status:str = "Off" + PlatenSafe:int = 0 + Height:Decimal = 0 + HeightMax:Decimal = 0 + HeightRelative:Decimal = 0 + SafeHeight:Decimal = 0 + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedStatusChange",Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message) + + +def MachineStateChange(MachineState:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies about changes in the machine state + API Status: internal + Args: + MachineState:str = "Off" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MachineStateChange",MachineState) + + +def ChuckVacuumChangeRequest(VacuumState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if the user requests a chuck vacuum change + API Status: internal + Args: + VacuumState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ChuckVacuumChangeRequest",VacuumState) + + +def SoftwareStopChangedNotify(SoftwareStopState:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies if software stop was activated or deactivated + API Status: internal + Args: + SoftwareStopState:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SoftwareStopChangedNotify",SoftwareStopState) + + +def KernelQuietModeChange(IsQuiet:int="", Stage:str="", IsStageQuiet:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs if the overall quiet mode changes and about changes of single stages + API Status: internal + Args: + IsQuiet:int = 0 + Stage:str = "None" + IsStageQuiet:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("KernelQuietModeChange",IsQuiet,Stage,IsStageQuiet) + + +def ConfigurationChanged(ParameterChanged:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies that a configuration item has changed by some application + API Status: internal + Args: + ParameterChanged:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ConfigurationChanged",ParameterChanged) + + +def ScopeWorkingStageChanged(ScopeWorkingStage:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Informs that a new working stage is active + API Status: internal + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ScopeWorkingStageChanged",ScopeWorkingStage) + + +def BnR_AxisNotify(Stage:str="", Axis:str="", State:str="", AdditionalStateInfo:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the user Interface and Kernel if the state of the axis has changed. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + State:str = "NotExisting" + AdditionalStateInfo:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisNotify",Stage,Axis,State,AdditionalStateInfo) + + +def BnR_StageNotify(Stage:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the stage status has changed. + API Status: internal + Args: + Stage:str = "Chuck" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_StageNotify",Stage,State) + + +def BnR_InputNotify(Channel:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an input channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InputNotify",Channel,State) + + +def BnR_OutputNotify(Channel:str="", State:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state of an output channel has changed. + API Status: internal + Args: + Channel:str = "0" + State:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_OutputNotify",Channel,State) + + +def BnR_AxisStatusNotify(Stage:str="", Axis:str="", Initialized:int="", PositiveLimit:int="", NegativeLimit:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifys the listener that an axis status has changed. Currently used to notify + the Kernel about the init state of a BnR axis. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Initialized:int = 0 + PositiveLimit:int = 0 + NegativeLimit:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AxisStatusNotify",Stage,Axis,Initialized,PositiveLimit,NegativeLimit) + + +def AutoXYModeChange(AutoXYModeOn:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by Spectrum if Automation was enabled or disabled. This can be AutoXY, + AutoZ or VueTrack. Handled by WaferMap to ensure that automation is executed + when stepping. + API Status: internal + Args: + AutoXYModeOn:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("AutoXYModeChange",AutoXYModeOn) + + +def ZoomLevelChange(ZoomLevel:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent by OpticalControl when the AZoom zoom level is changed. Spectrum should + handle this so it doesn't have to poll OpticalControl for the current zoom + level. + API Status: internal + Args: + ZoomLevel:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ZoomLevelChange",ZoomLevel) + + +def BnR_AnalogIONotify(AnalogIO:str="", ValuePercent:Decimal="", UnderOverflow:int="", Error:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notify the listener that the state or value of an analog input or output channel + has changed. + API Status: internal + Args: + AnalogIO:str = "AO_PurgeDewPoint" + ValuePercent:Decimal = 0 + UnderOverflow:int = 0 + Error:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_AnalogIONotify",AnalogIO,ValuePercent,UnderOverflow,Error) + + +def BnR_ControllerInfoNotify(ControllerNum:int="", ControllerInfo:str="", Value:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notifies the listener about changed controller info. Currently used to inform + Toolbar about the battery state of the BnR controller. + API Status: internal + Args: + ControllerNum:int = 1 + ControllerInfo:str = "BatteryOK" + Value:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_ControllerInfoNotify",ControllerNum,ControllerInfo,Value) + + +def BnR_PositionNotify(Stage:str="", XorT:Decimal="", Y:Decimal="", Z:Decimal="", CommandedXorT:Decimal="", CommandedY:Decimal="", CommandedZ:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by BnR controller if a axis position has changed. Currently + used to notify the Kernel about the new axis position. + API Status: internal + Args: + Stage:str = "Chuck" + XorT:Decimal = 0 + Y:Decimal = 0 + Z:Decimal = 0 + CommandedXorT:Decimal = 0 + CommandedY:Decimal = 0 + CommandedZ:Decimal = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_PositionNotify",Stage,XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ) + + +def BnR_InfoNotify(InfoType:str="", Info:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Generic Information Notification + API Status: internal + Args: + InfoType:str = "" + Info:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("BnR_InfoNotify",InfoType,Info) + + +def WMNewCurrentDie(DieX:int="", DieY:int="", XFromHome:Decimal="", YFromHome:Decimal="", CurSite:int="", LastSiteIndex:int=""): + """ + Alerts applications that WaferMap has a new position. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + XFromHome:Decimal = 0 + YFromHome:Decimal = 0 + CurSite:int = 1 + LastSiteIndex:int = 1 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMNewCurrentDie",DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex) + + +def WMSetupChange(): + """ + Alerts applications that a wafer's parameters have been changed. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("WMSetupChange") + + +def ButtonPress(TargetIdent:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when button instrumented for guided workflow is pressed. The TargetIdent is + the identifier for the button as defined for the guided workflow. + API Status: internal + Args: + TargetIdent:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("ButtonPress",TargetIdent) + + +def CryoCmdReady(State:str="", Error:int="", ErrorDescription:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sent when the cooling or heating process was terminated successfully or + incorrectly. Returns the status with which the process was finished (IDLE, COLD, + COOL DOWN, WARMUP) and sends the error code and error message. + API Status: internal + Args: + State:str = "IDLE" + Error:int = 0 + ErrorDescription:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CryoCmdReady",State,Error,ErrorDescription) + + +def VMProjectLoaded(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent when Spectrum VS project has finished loading. + API Status: internal + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProjectLoaded") + + +def VMProbeCardData(Access:str="", FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent when a probe card file is loaded. + API Status: internal + Args: + Access:str = "L" + FileName:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("VMProbeCardData",Access,FileName) + + +def TTLTestDone(): + """ + Alerts applications that the TTL Test is ready. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("TTLTestDone") + + +def PSStateChanged(State:str="", SubState:str="", Message:str="", Error:int=""): + """ + Notification sent when VeloxPro changes its running state. + API Status: published + Args: + State:str = "Unknown" + SubState:str = "Unknown" + Message:str = "" + Error:int = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSStateChanged",State,SubState,Message,Error) + + +def PSProgressChanged(ProgressPercent:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification sent during wafer stepping process. It updates the progress + information. 'Progress' is the relationship of dies tested to dies to be tested. + API Status: internal + Args: + ProgressPercent:Decimal = 0 + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSProgressChanged",ProgressPercent) + + +def PSLoaderUsage(UseLoader:int="", UseAutoWafer:int="", WaferSizes:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent to notify the listener about usage of Loader, usage of + fully/semiautomatic mode and supported wafer sizes of process station. + API Status: internal + Args: + UseLoader:int = 0 + UseAutoWafer:int = 0 + WaferSizes:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("PSLoaderUsage",UseLoader,UseAutoWafer,WaferSizes) + + +def LoaderMessage(Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Notification is sent by loader to display a message on the process station. + API Status: internal + Args: + Message:str = "" + Command Timeout: 30000 + """ + MessageServerInterface.sendSciCommand("LoaderMessage",Message) + + +def OpenProjectDialog(ProjectFilename:str="", Option:int=""): + """ + Asks if the current project should be saved and then brings up the Open Project + window which opens the selected project file if the user clicks ok. + API Status: published + Args: + ProjectFilename:str = "" + Option:int = 0 + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("OpenProjectDialog",ProjectFilename,Option) + + +def SaveProjectAsDialog(): + """ + Brings up the Save Project window which saves the project if the user clicks ok. + API Status: published + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsDialog") + + +def LoginDialog(LevelToOffer:str=""): + """ + Brings up the Login window and sends a New Access Level alert if the user enters + a valid password. + API Status: published + Args: + LevelToOffer:str = "1" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoginDialog",LevelToOffer) + + +def GetStatus(): + """ + Returns the current software status. The server holds and maintains the software + status. Status can be changed by using any of the following commands: + BeginProbing, LoginDialog, AbortProbing, SetExternalMode, PauseProbing, + UnloadWafer, ResumeProbing + API Status: published + Returns: + DummyCommonMode:int + RunningMode:str + AccessLevel:str + ExternalMode:int + LicenseDaysLeft:int + MKH:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetStatus") + global GetStatus_Response + if not "GetStatus_Response" in globals(): GetStatus_Response = namedtuple("GetStatus_Response", "DummyCommonMode,RunningMode,AccessLevel,ExternalMode,LicenseDaysLeft,MKH") + return GetStatus_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def LicensingDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Licensing window. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LicensingDialog") + + +def GetLicenseInfo(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current license information. + API Status: internal + Returns: + AnnualEnabled:int + AnnualDaysLeft:int + VeloxProEnabled:int + VueTrackEnabled:int + VueTrack4PEnabled:int + ReAlignEnabled:int + AutomationEnabled:int + IdToolsEnabled:int + IVistaEnabled:int + IVistaProEnabled:int + LaserCutterEnabled:int + SiPToolsEnabled:int + AutoRfEnabled:int + SecsGemEnabled:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLicenseInfo") + global GetLicenseInfo_Response + if not "GetLicenseInfo_Response" in globals(): GetLicenseInfo_Response = namedtuple("GetLicenseInfo_Response", "AnnualEnabled,AnnualDaysLeft,VeloxProEnabled,VueTrackEnabled,VueTrack4PEnabled,ReAlignEnabled,AutomationEnabled,IdToolsEnabled,IVistaEnabled,IVistaProEnabled,LaserCutterEnabled,SiPToolsEnabled,AutoRfEnabled,SecsGemEnabled") + return GetLicenseInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13])) + +def GetProjectFile(): + """ + Returns the current project file. + API Status: published + Returns: + ProjectFilename:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProjectFile") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReportSoftwareVersion(): + """ + Returns the Velox software version as string. + API Status: published + Returns: + SoftwareVersion:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReportSoftwareVersion") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OpenProject(ProjectFilename:str=""): + """ + The OpenProject command opens the specified project. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("OpenProject",ProjectFilename) + + +def IsAppRegistered(Application:str=""): + """ + Checks the server to see if the application "AppName" is registered with the + server. + API Status: published + Args: + Application:str = "" + Returns: + IsAppRegistered:int + Command Timeout: 5000 + Example:IsAppRegistered WaferMap + """ + rsp = MessageServerInterface.sendSciCommand("IsAppRegistered",Application) + return int(rsp[0]) + +def SaveProject(ProjectFilename:str=""): + """ + Saves the current data to the project file. + API Status: published + Args: + ProjectFilename:str = "" + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("SaveProject",ProjectFilename) + + +def GetSoftwarePath(PathType:str=""): + """ + Returns the path for either the applications/data or project files. + API Status: published + Args: + PathType:str = "User" + Returns: + SoftwarePath:str + Command Timeout: 5000 + Example:GetSoftwarePath User + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwarePath",PathType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CCSelectLens(Lens:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. + API Status: internal + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:CCSelectLens 1 + """ + MessageServerInterface.sendSciCommand("CCSelectLens",Lens) + + +def CCReadCurrentLens(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Internal AZoom Helper Command. Probably no longer used. + API Status: internal + Returns: + Lens:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("CCReadCurrentLens") + return int(rsp[0]) + +def CCMoveAuxSite(AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calls the Kernel command MoveAuxSite to move the chuck to the + position of a given AUX site. For the transfer move a safe height is used. If + AUX ID is set to 0, the target of the move is the wafer site. If the flag 'Auto + Align by Spectrum' in ControlCenter-SystemSetup-Aux Sites is True, the Spectrum + command AlignAux is executed after MoveAuxSite to align the site automatically. + The flag is only visible, if the aux site type is CalSubstrate and Spectrum is + installed. AUX ID in the response is the ID of the new active site. + API Status: internal + Args: + AuxID:int = 1 + Command Timeout: 200000 + """ + MessageServerInterface.sendSciCommand("CCMoveAuxSite",AuxID) + + +def ExecuteCleaningSequence(SequenceName:str="", AllowMediaReuse:int="", SkipAlignAux:int="", SkipReturnMove:int=""): + """ + This command moves to the single cleaning site, executes CleanProbeTip, moves to + the contact verify site, and then moves to contact. Returns an error if the + clean or verify sites aren't defined. + API Status: published + Args: + SequenceName:str = "" + AllowMediaReuse:int = 0 + SkipAlignAux:int = 0 + SkipReturnMove:int = 0 + Command Timeout: 1800000 + Example:ExecuteCleaningSequence "DeepClean" + """ + MessageServerInterface.sendSciCommand("ExecuteCleaningSequence",SequenceName,AllowMediaReuse,SkipAlignAux,SkipReturnMove) + + +def GetAlignmentMode(): + """ + Get the active alignment mode (either on axis or off axis). + API Status: published + Returns: + AlignmentMode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetAlignmentMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetAlignmentMode(AlignmentMode:str=""): + """ + Sets the active alignment mode (either on axis or off axis). + API Status: published + Args: + AlignmentMode:str = "OnAxis" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetAlignmentMode",AlignmentMode) + + +def GetLoginData(CmdUserName:str=""): + """ + Gets the Velox user data: name, full name, group, access level. If the + commanded user name is empty, the data of the current user will be responded + API Status: published + Args: + CmdUserName:str = "" + Returns: + UserName:str + LongUserName:str + UserGroup:str + AccessLevel:str + VeloxLocked:int + Command Timeout: 5000 + Example:GetLoginData + """ + rsp = MessageServerInterface.sendSciCommand("GetLoginData",CmdUserName) + global GetLoginData_Response + if not "GetLoginData_Response" in globals(): GetLoginData_Response = namedtuple("GetLoginData_Response", "UserName,LongUserName,UserGroup,AccessLevel,VeloxLocked") + return GetLoginData_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4])) + +def NucleusInitChuck(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to warn user of chuck initialization for Nucleus stations. + Allows user to OK/Cancel. + API Status: internal + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("NucleusInitChuck") + + +def ShutdownVeloxWithSave(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up message box to allow saving project before shutting down Velox. Allows + user to OK/Cancel. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("ShutdownVeloxWithSave") + + +def WinCalAutoCal(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCal command to WinCal. + API Status: internal + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCal") + + +def WinCalCheckAutoRFStability(AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCheckAutoRFStability command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Returns: + StabilityPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalCheckAutoRFStability",AllowMove) + return int(rsp[0]) + +def WinCalCloseRFStabilityReport(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalCloseRFStabilityReport command to WinCal. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalCloseRFStabilityReport") + + +def WinCalMoveToIssRef(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalMoveToIssRef command to WinCal to move to the specified ISS + reference. The ISS index is the IssIdxMap index as returned from + WinCalGetIssListForAuxSite. + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("WinCalMoveToIssRef",IssIdx) + + +def WinCalVerifyIssRefLocAtHome(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalVerifyIssRefLocAtHome command to WinCal and returns AllRefAtHome + as 1 if stage and positioners at home. + API Status: internal + Args: + IssIdx:int = 0 + Returns: + AllRefAtHome:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalVerifyIssRefLocAtHome",IssIdx) + return int(rsp[0]) + +def WinCalGetIssForAuxSite(AuxID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetIssForAuxSite command to WinCal and returns the ISS + information for the given aux site ID. + API Status: internal + Args: + AuxID:int = 0 + Returns: + IssIdx:int + IssPN:str + IssDescription:str + IssEnabled:int + AuxSiteName:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetIssForAuxSite",AuxID) + global WinCalGetIssForAuxSite_Response + if not "WinCalGetIssForAuxSite_Response" in globals(): WinCalGetIssForAuxSite_Response = namedtuple("WinCalGetIssForAuxSite_Response", "IssIdx,IssPN,IssDescription,IssEnabled,AuxSiteName") + return WinCalGetIssForAuxSite_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def WinCalGetNameAndVersion(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalGetNameAndVersion command to WinCal. + API Status: internal + Returns: + ServerName:str + Version:str + MajorVersion:int + MinorVersion:int + Revision:int + Build:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNameAndVersion") + global WinCalGetNameAndVersion_Response + if not "WinCalGetNameAndVersion_Response" in globals(): WinCalGetNameAndVersion_Response = namedtuple("WinCalGetNameAndVersion_Response", "ServerName,Version,MajorVersion,MinorVersion,Revision,Build") + return WinCalGetNameAndVersion_Response(str(rsp[0]),str(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def WinCalMonitorNoMove(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMonitorNoMove command to WinCal. Triggers WinCal to measure the + monitor portion of the current calibration setup. + API Status: internal + Returns: + MonitorPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalMonitorNoMove") + return int(rsp[0]) + +def WinCalValidateAdvanced(ProbeSpacing:Decimal="", ResetTrace:int="", AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidateAdvanced command to WinCal. Performs the validation step of + the currently selected calibration setup. Resets the controller used in WinCal + for validataion. + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + ResetTrace:int = 1 + AllowMove:int = 1 + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidateAdvanced",ProbeSpacing,ResetTrace,AllowMove) + return int(rsp[0]) + +def WinCalMeasureMonitorReference(AllowMove:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalMeasureMonitorReference command to WinCal. + API Status: internal + Args: + AllowMove:int = 0 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalMeasureMonitorReference",AllowMove) + + +def WinCalGetNumValidationPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumValidationPorts command to WinCal. + API Status: internal + Returns: + NumValidationPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumValidationPorts") + return int(rsp[0]) + +def WinCalSetNumValidationPorts(NumValidationPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumValidationPorts command to WinCal. + API Status: internal + Args: + NumValidationPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumValidationPorts",NumValidationPorts) + + +def WinCalGetNumMonitoringPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumMonitoringPorts command to WinCal. + API Status: internal + Returns: + NumMonitoringPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumMonitoringPorts") + return int(rsp[0]) + +def WinCalSetNumMonitoringPorts(NumMonitoringPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumMonitoringPorts command to WinCal. + API Status: internal + Args: + NumMonitoringPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumMonitoringPorts",NumMonitoringPorts) + + +def WinCalGetNumRepeatabilityPorts(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetNumRepeatabilityPorts command to WinCal. + API Status: internal + Returns: + NumRepeatabilityPorts:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumRepeatabilityPorts") + return int(rsp[0]) + +def WinCalSetNumRepeatabilityPorts(NumRepeatabilityPorts:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalSetNumRepeatabilityPorts command to WinCal. + API Status: internal + Args: + NumRepeatabilityPorts:int = 2 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalSetNumRepeatabilityPorts",NumRepeatabilityPorts) + + +def WinCalValidate(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalValidate command to WinCal. Performs the validation step of the + currently selected calibration setup in WinCal. + API Status: internal + Returns: + ValidationPassed:int + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalValidate") + return int(rsp[0]) + +def WinCalGetValidationSetup(Port:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends CalGetValidationSetup command to WinCal. Returns calibration setup + parameters. + API Status: internal + Args: + Port:int = 1 + Returns: + StandardType:str + StandardPorts:int + StandardCompareType:int + StructureType:str + PostCorrect:int + PostCorrectMatching:int + AutoConfigure:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetValidationSetup",Port) + global WinCalGetValidationSetup_Response + if not "WinCalGetValidationSetup_Response" in globals(): WinCalGetValidationSetup_Response = namedtuple("WinCalGetValidationSetup_Response", "StandardType,StandardPorts,StandardCompareType,StructureType,PostCorrect,PostCorrectMatching,AutoConfigure") + return WinCalGetValidationSetup_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def WinCalAutoCalNoValidation(ProbeSpacing:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalAutoCalNoValidation command to WinCal. Performs an AutoCal + without the validation step + API Status: internal + Args: + ProbeSpacing:Decimal = 130 + Command Timeout: 300000 + """ + MessageServerInterface.sendSciCommand("WinCalAutoCalNoValidation",ProbeSpacing) + + +def WinCalHideAllWindows(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalHideAllWindows command to WinCal. This minimizes all the WinCal + windows + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalHideAllWindows") + + +def WinCalGetReferenceStructureInfo(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalGetReferenceStructureInfo command to WinCal. Given the WinCal ISS + index it will return a string with the reference information + API Status: internal + Args: + IssIdx:int = 0 + Returns: + ReferenceInfo:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetReferenceStructureInfo",IssIdx) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def WinCalSystemSetupHasUnappliedChanges(ShowErrors:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the WinCalSystemSetupHasUnappliedChanges command to WinCal. Returns true + if WinCal has unapplied changes + API Status: internal + Args: + ShowErrors:int = 0 + Returns: + HasUnappliedChanges:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalSystemSetupHasUnappliedChanges",ShowErrors) + return int(rsp[0]) + +def WinCalRecordIssRefAtCurrentLoc(IssIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends the CalRecordIssRefAtCurrentLoc command to WinCal. Record the ISS, + indicated by the index, reference as being the current location + API Status: internal + Args: + IssIdx:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("WinCalRecordIssRefAtCurrentLoc",IssIdx) + + +def SaveProjectAsTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the Save Project as Template window which saves the project template + if the user clicks ok. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SaveProjectAsTemplateDialog") + + +def CreateProjectFromTemplateDialog(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Brings up the New Project from Template dialog which allows the user to select a + template and create a new project. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CreateProjectFromTemplateDialog") + + +def WinCalGetNumPortsAndProbes(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns Max Ports and Number of probes connected to a port + API Status: internal + Returns: + MaxPorts:int + NumPortsConnectedtoProbes:int + Command Timeout: 1000 + Example:WinCalGetNumPortsAndProbes + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetNumPortsAndProbes") + global WinCalGetNumPortsAndProbes_Response + if not "WinCalGetNumPortsAndProbes_Response" in globals(): WinCalGetNumPortsAndProbes_Response = namedtuple("WinCalGetNumPortsAndProbes_Response", "MaxPorts,NumPortsConnectedtoProbes") + return WinCalGetNumPortsAndProbes_Response(int(rsp[0]),int(rsp[1])) + +def WinCalGetProbeInfoForPort(VnaPortNum:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the properties from one probe, based on the passed in index. Pass in a + physical VNA port number that is less than or equal to Max Probes from the call + to CalGetNumPortsAndProbes + API Status: internal + Args: + VnaPortNum:int = 1 + Returns: + IsSelected:int + BaseProbe:str + Options:str + PhysicalOrient:str + IsDual:int + IsSymmetric:int + SignalConfig:str + SelectedPitch:int + Command Timeout: 1000 + Example:WinCalGetProbeInfoForPort 1 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalGetProbeInfoForPort",VnaPortNum) + global WinCalGetProbeInfoForPort_Response + if not "WinCalGetProbeInfoForPort_Response" in globals(): WinCalGetProbeInfoForPort_Response = namedtuple("WinCalGetProbeInfoForPort_Response", "IsSelected,BaseProbe,Options,PhysicalOrient,IsDual,IsSymmetric,SignalConfig,SelectedPitch") + return WinCalGetProbeInfoForPort_Response(int(rsp[0]),str(rsp[1]),str(rsp[2]),str(rsp[3]),int(rsp[4]),int(rsp[5]),str(rsp[6]),int(rsp[7])) + +def GetMachineState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current state of the machine. + API Status: internal + Returns: + MachineState:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMachineState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowAboutDialog(Pid:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the help about dialog for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowAboutDialog",Pid) + + +def ShowSplashScreen(Pid:int="", TimeoutMs:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shows the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + TimeoutMs:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ShowSplashScreen",Pid,TimeoutMs) + + +def CloseSplashScreen(Pid:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the splash screen for the given application + API Status: internal + Args: + Pid:int = -1 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseSplashScreen",Pid) + + +def GetLastFourProjects(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the last four project files that were opened. + API Status: internal + Returns: + ProjectFile1:str + ProjectFile2:str + ProjectFile3:str + ProjectFile4:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLastFourProjects") + global GetLastFourProjects_Response + if not "GetLastFourProjects_Response" in globals(): GetLastFourProjects_Response = namedtuple("GetLastFourProjects_Response", "ProjectFile1,ProjectFile2,ProjectFile3,ProjectFile4") + return GetLastFourProjects_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def WinCalExecuteCommand(Command:str=""): + """ + Sends the WinCalExecuteCommand command to WinCal and returns the response + string. + API Status: published + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 300000 + """ + rsp = MessageServerInterface.sendSciCommand("WinCalExecuteCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDemoMode(TurnOnDemoMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will return an error if its called with any other parameter as 0. + API Status: internal + Args: + TurnOnDemoMode:int = 1 + Command Timeout: 5000 + Example:SetDemoMode 0 + """ + MessageServerInterface.sendSciCommand("SetDemoMode",TurnOnDemoMode) + + +def ChangeDemoRsp(Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Override a command with a demo response. The command will not reach its + destination but the supplied demo response will be returned. An active overide + for a command will be removed if the provided timeout is negative. Format: [ID] + [Time] [ErrorCode]:[Response] - Id: command id in hex withoud leding 0x - Time: + time in ms between command and response, negativ to reset demo mode for this + command - Errorcode: 0 for success, everything else indicates an error - + Response: response string + API Status: internal + Args: + Param:str = "" + Command Timeout: 5000 + Example:ChangeDemoRsp 31 200 0:5000.0 5000.0 8500 + """ + MessageServerInterface.sendSciCommand("ChangeDemoRsp",Param) + + +def GetDemoMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The DemoMode is not supported anymore. Use ChangeDemoRsp to install a demo mode. + This command will always return 0. + API Status: internal + Returns: + DemoModeOn:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDemoMode") + return int(rsp[0]) + +def ResetNetworkPort(Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + (Re)sets the IP address and listen port of the socket to which the NetworkDriver + tries to connect to (IP address and listen port of Kernel socket). Dummy + implementation for Kernel to support backwards. + API Status: internal + Args: + Param:str = "" + Command Timeout: 10000 + Example:ResetNetworkPort 192.168.3.1 10000 + """ + MessageServerInterface.sendSciCommand("ResetNetworkPort",Param) + + +def GetNDriverClientStatus(ClientNum:int="", Param:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets status information about the connection NetworkDriver to Kernel. Socket + Error is the Windows socket error, Description the Windows socket error + description. If Socket Error is 0, the description 'Registered' informs that the + Kernel is ready to receive Remote Commands. + API Status: internal + Args: + ClientNum:int = 1 + Param:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:GetNDriverClientStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetNDriverClientStatus",ClientNum,Param) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def OverrideCommandTimeout(CmdID:int="", TimeoutMilliSec:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows specifying a separate command timeout for a single instance + of a command. This is especially useful if the application that receives a + command knows how long a command will take. This command had been added for + SoakTime-handling of StepNextDie. A safe guess for the timeout of StepNextDie is + 5s. + API Status: internal + Args: + CmdID:int = 0 + TimeoutMilliSec:int = 1000 + Command Timeout: 5000 + Example:OverrideCommandTimeout 3234 20000 + """ + MessageServerInterface.sendSciCommand("OverrideCommandTimeout",CmdID,TimeoutMilliSec) + + +def ShutdownVelox(IgnorePID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Shutdown all Velox applications in an ordered fashion. When this command returns + success, all non-mandatory apps are closed and the mandatory ones will follow + shortly + API Status: internal + Args: + IgnorePID:int = 0 + Command Timeout: 120000 + Example:ShutdownVelox + """ + MessageServerInterface.sendSciCommand("ShutdownVelox",IgnorePID) + + +def InitializationDone(CommandGroup:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Registration of an application can be delayed. To trigger this behavior, + RegisterProberApp has to be called with flag 3 set (0x04). From + RegisterProberApp to the time this command is sent, the application can send + commands but can't receive commands. This is necessary because some application + have to communicate with others during initialization and can not handle + commands properly during this time. The command group is necessary because of + architectural reasons (By design, the command receiver does not now the sender + of a command). + API Status: internal + Args: + CommandGroup:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("InitializationDone",CommandGroup) + + +def StepFirstZProfilePoint(XPos:Decimal="", YPos:Decimal="", NumberOfPoints:int="", NumberOfEPoints:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command goes to the first Z Profile Point, adjusts Z (in the automatic mode + only) and pauses after it (even in the automatic mode) + API Status: internal + Args: + XPos:Decimal = 0 + YPos:Decimal = 0 + NumberOfPoints:int = 0 + NumberOfEPoints:int = 0 + Command Timeout: 60000 + Example:StepFirstZProfilePoint 10000 20000 5 5 + """ + MessageServerInterface.sendSciCommand("StepFirstZProfilePoint",XPos,YPos,NumberOfPoints,NumberOfEPoints) + + +def StepNextZProfilePoint(Point:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command calculates a delta value for the current point and then moves to + the specified point (if it's presented) or to the next one. Note, that in case + of the automatic Z detecting a return ZDelta parameter is a value for the + current point, but in case of the semiautomatic mode the command returns ZDelta + as a value for a previous tested point. If the profiling is finished this + command will return #807 error (End of the profile). Point indices are started + from 1 (1 is first, 2 is second, and so on). + API Status: internal + Args: + Point:int = 0 + Returns: + XPos:Decimal + YPos:Decimal + Delta:Decimal + CurPoint:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 60000 + Example:StepNextZProfilePoint 1 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextZProfilePoint",Point) + global StepNextZProfilePoint_Response + if not "StepNextZProfilePoint_Response" in globals(): StepNextZProfilePoint_Response = namedtuple("StepNextZProfilePoint_Response", "XPos,YPos,Delta,CurPoint,NumberOfPoints,NumberOfEPoints") + return StepNextZProfilePoint_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5])) + +def SetZProfileOptions(ProfileMode:str="", SepSpeed:Decimal="", ProfileSensor:str="", Stage:str="", SearchSpeed:Decimal="", Gap:Decimal="", Units:str="", ClearElectronics:int="", ClearRefZ:int="", Inaccuracy:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets some Z Profile Program Options remotely. + API Status: internal + Args: + ProfileMode:str = "S" + SepSpeed:Decimal = 25 + ProfileSensor:str = "E" + Stage:str = "C" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + Units:str = "Y" + ClearElectronics:int = 1 + ClearRefZ:int = 1 + Inaccuracy:Decimal = 0 + Command Timeout: 10000 + Example:SetZProfileOptions S 25 E C 50 10 Y 1 1 0 + """ + MessageServerInterface.sendSciCommand("SetZProfileOptions",ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy) + + +def GetZProfileOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Return predefined settings of the Z Profile Program. + API Status: internal + Returns: + ProfileMode:str + SepSpeed:Decimal + ProfileSensor:str + Stage:str + SearchSpeed:Decimal + Gap:Decimal + Units:str + ClearElectronics:int + ClearRefZ:int + Inaccuracy:Decimal + Command Timeout: 10000 + Example:GetZProfileOptions + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOptions") + global GetZProfileOptions_Response + if not "GetZProfileOptions_Response" in globals(): GetZProfileOptions_Response = namedtuple("GetZProfileOptions_Response", "ProfileMode,SepSpeed,ProfileSensor,Stage,SearchSpeed,Gap,Units,ClearElectronics,ClearRefZ,Inaccuracy") + return GetZProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str(rsp[6]),int(rsp[7]),int(rsp[8]),Decimal(rsp[9])) + +def OpenZProfileFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command opens the file inside of the Z Profiling. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 240000 + Example:OpenZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("OpenZProfileFile",FileName) + global OpenZProfileFile_Response + if not "OpenZProfileFile_Response" in globals(): OpenZProfileFile_Response = namedtuple("OpenZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return OpenZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def SaveZProfileFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves the current profile in the specified file. + API Status: internal + Args: + FileName:str = "" + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:SaveZProfileFile Profile1 + """ + rsp = MessageServerInterface.sendSciCommand("SaveZProfileFile",FileName) + global SaveZProfileFile_Response + if not "SaveZProfileFile_Response" in globals(): SaveZProfileFile_Response = namedtuple("SaveZProfileFile_Response", "NumberOfPoints,NumberOfEPoints") + return SaveZProfileFile_Response(int(rsp[0]),int(rsp[1])) + +def ReadZProfile(NewOrigin:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Read a profile from the ProberBench Electronics II to the application. Return a + number of available points. + API Status: internal + Args: + NewOrigin:str = "Z" + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:ReadZProfile H + """ + rsp = MessageServerInterface.sendSciCommand("ReadZProfile",NewOrigin) + return int(rsp[0]) + +def SetZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Uploads the current profile to the ProberBench Electronics II. Returns a number + of written points. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:SetZProfile + """ + rsp = MessageServerInterface.sendSciCommand("SetZProfile") + return int(rsp[0]) + +def CloseZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Z-Profiling application. + API Status: internal + Command Timeout: 5000 + Example:CloseZProfiling + """ + MessageServerInterface.sendSciCommand("CloseZProfiling") + + +def SetZProfileStartPoint(X:Decimal="", Y:Decimal="", PosRef:str="", Units:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets new start point for the profile. All points of the profile will be shifted + accordingly. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + PosRef:str = "Z" + Units:str = "Y" + Command Timeout: 10000 + Example:SetZProfileStartPoint 0 0 H Y + """ + MessageServerInterface.sendSciCommand("SetZProfileStartPoint",X,Y,PosRef,Units) + + +def GetZProfilingStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the profiling process. If this status is true it means the + process is started. + API Status: internal + Returns: + Started:int + Command Timeout: 10000 + Example:GetZProfilingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilingStatus") + return int(rsp[0]) + +def StopZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the profiling process. + API Status: internal + Command Timeout: 10000 + Example:StopZProfiling + """ + MessageServerInterface.sendSciCommand("StopZProfiling") + + +def SetZProfileOrigin(Pos:str="", X:Decimal="", Y:Decimal="", Z:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an origin for the profile. If the origin position is H the command ignores + X and Y parameters. If Z is None the command clears Z value of the origin. + Otherwise it tries to extract a double value from the string and set it. + API Status: internal + Args: + Pos:str = "H" + X:Decimal = 0 + Y:Decimal = 0 + Z:str = "None" + Command Timeout: 10000 + Example:SetZProfileOrigin H 0 0 None + """ + MessageServerInterface.sendSciCommand("SetZProfileOrigin",Pos,X,Y,Z) + + +def GetZProfileOrigin(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current parameters of the profile origin. If the origin Z has no value + the return string for it will be None, otherwise it consists a double value of + the profile Z. + API Status: internal + Returns: + Pos:str + X:Decimal + Y:Decimal + Z:str + Command Timeout: 10000 + Example:GetZProfileOrigin + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileOrigin") + global GetZProfileOrigin_Response + if not "GetZProfileOrigin_Response" in globals(): GetZProfileOrigin_Response = namedtuple("GetZProfileOrigin_Response", "Pos,X,Y,Z") + return GetZProfileOrigin_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def StartZProfiling(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Command Timeout: 10000 + Example:StartZProfiling + """ + MessageServerInterface.sendSciCommand("StartZProfiling") + + +def ZProfileWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command works in the automatic mode only. It starts the profiling process, + profiles the entire wafer and then returns a number of tested points. This + command does upload the current profile to the ProberBench Electronics II. To do + it please use SetZProfile command + API Status: internal + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 36000000 + Example:ZProfileWafer + """ + rsp = MessageServerInterface.sendSciCommand("ZProfileWafer") + global ZProfileWafer_Response + if not "ZProfileWafer_Response" in globals(): ZProfileWafer_Response = namedtuple("ZProfileWafer_Response", "NumberOfPoints,NumberOfEPoints") + return ZProfileWafer_Response(int(rsp[0]),int(rsp[1])) + +def GetZProfileStartPoint(PosRef:str="", Units:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current start point of the profile by using given units and a + reference position. + API Status: internal + Args: + PosRef:str = "Z" + Units:str = "Y" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + Example:GetZProfileStartPoint H Y + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfileStartPoint",PosRef,Units) + global GetZProfileStartPoint_Response + if not "GetZProfileStartPoint_Response" in globals(): GetZProfileStartPoint_Response = namedtuple("GetZProfileStartPoint_Response", "X,Y") + return GetZProfileStartPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AddZProfilePoint(X:Decimal="", Y:Decimal="", After:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Adds new point to the profile at the end (default) or after the given point. + Returns an index of new point and a number of all points in the profile. Point + indices are started from 1. + API Status: internal + Args: + X:Decimal = 0 + Y:Decimal = 0 + After:int = 0 + Returns: + Index:int + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:AddZProfilePoint 50000 50000 + """ + rsp = MessageServerInterface.sendSciCommand("AddZProfilePoint",X,Y,After) + global AddZProfilePoint_Response + if not "AddZProfilePoint_Response" in globals(): AddZProfilePoint_Response = namedtuple("AddZProfilePoint_Response", "Index,NumberOfPoints,NumberOfEPoints") + return AddZProfilePoint_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def DeleteZProfilePoint(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Deletes the point from the profile. Returns a number of all and enabled points + in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + NumberOfPoints:int + NumberOfEPoints:int + Command Timeout: 10000 + Example:DeleteZProfilePoint 11 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteZProfilePoint",Index) + global DeleteZProfilePoint_Response + if not "DeleteZProfilePoint_Response" in globals(): DeleteZProfilePoint_Response = namedtuple("DeleteZProfilePoint_Response", "NumberOfPoints,NumberOfEPoints") + return DeleteZProfilePoint_Response(int(rsp[0]),int(rsp[1])) + +def SetZProfilePointStatus(Index:int="", Status:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Status:str = "0" + Command Timeout: 10000 + Example:SetZProfilePointStatus 11 E + """ + MessageServerInterface.sendSciCommand("SetZProfilePointStatus",Index,Status) + + +def GetZProfilePointStatus(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a status of the point in the profile. Point indices are started from 1. + API Status: internal + Args: + Index:int = 0 + Returns: + Status:str + Command Timeout: 10000 + Example:GetZProfilePointStatus 11 + """ + rsp = MessageServerInterface.sendSciCommand("GetZProfilePointStatus",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def PreciseZProfile(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + All points are covered by triangles, each vertex of the triangle is a point of + the profile. The centers of the triangles are new points of the profile. If all + three vertexes of the triangle are tested points the new point will be marked as + tested also and has Z value equal to average Z of all three vertexes. Otherwise + the new point will be marked as untested. The command returns a number of points + in the profile after the update. + API Status: internal + Returns: + NumberOfPoints:int + Command Timeout: 10000 + Example:PreciseZProfile + """ + rsp = MessageServerInterface.sendSciCommand("PreciseZProfile") + return int(rsp[0]) + +def CloseTableView(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the TableView application. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CloseTableView") + + +def StepChuckSite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Site no. of the chuck table view. + If no Site no is specified the chuck will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSite",Site) + return int(rsp[0]) + +def StepChuckSubsite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the wafer chuck stage to the requested Subsite no. of the chuck subsite + table view. If no Subsite no. is specified the chuck will step automatically to + the next logical site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepChuckSubsite",Site) + return int(rsp[0]) + +def StepScopeSite(Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the microscope stage to the requested Site no. of the scope table view. If + no Site no is specified the scope will step automatically to the next logical + site location. The first site in the table is site 1. + API Status: internal + Args: + Site:int = -1 + Returns: + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepScopeSite",Site) + return int(rsp[0]) + +def StepProbeSite(Probe:int="", Site:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Steps the specified probe to the requested Site no. of the Probe no table view. + If no Site no. is specified the Probe no. will step automatically to the next + logical site location. The first site in the table is site 1. + API Status: internal + Args: + Probe:int = -1 + Site:int = -1 + Returns: + ProbeRet:int + SiteRet:int + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("StepProbeSite",Probe,Site) + global StepProbeSite_Response + if not "StepProbeSite_Response" in globals(): StepProbeSite_Response = namedtuple("StepProbeSite_Response", "ProbeRet,SiteRet") + return StepProbeSite_Response(int(rsp[0]),int(rsp[1])) + +def ReadChuckSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual chuck site position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSitePosition") + global ReadChuckSitePosition_Response + if not "ReadChuckSitePosition_Response" in globals(): ReadChuckSitePosition_Response = namedtuple("ReadChuckSitePosition_Response", "Site,X,Y") + return ReadChuckSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadScopeSitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadScopeSitePosition") + global ReadScopeSitePosition_Response + if not "ReadScopeSitePosition_Response" in globals(): ReadScopeSitePosition_Response = namedtuple("ReadScopeSitePosition_Response", "Site,X,Y") + return ReadScopeSitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ReadProbeSitePosition(Probe:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the site position of the specified probe. The first site in the table is + site 1. + API Status: internal + Args: + Probe:int = -1 + Returns: + ProbeRet:int + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadProbeSitePosition",Probe) + global ReadProbeSitePosition_Response + if not "ReadProbeSitePosition_Response" in globals(): ReadProbeSitePosition_Response = namedtuple("ReadProbeSitePosition_Response", "ProbeRet,Site,X,Y") + return ReadProbeSitePosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadChuckSubsitePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the chuck subsite position. The first site in the table is site 1. + API Status: internal + Returns: + Site:int + X:Decimal + Y:Decimal + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadChuckSubsitePosition") + global ReadChuckSubsitePosition_Response + if not "ReadChuckSubsitePosition_Response" in globals(): ReadChuckSubsitePosition_Response = namedtuple("ReadChuckSubsitePosition_Response", "Site,X,Y") + return ReadChuckSubsitePosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def StepFirstDie(ClearBins:int="", RecalcRoute:int=""): + """ + Steps the chuck to the first die of the wafer map. Returns the row and column + number of the actual die location after the move is completed. If ClearBins is + 1, all binning data will be cleared from dies. If yes the route will be + recalculated. All dies marked to skip during the last test (marked to skip with + SetDieStatus) will be eliminated from the route. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + DieX:int + DieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstDie",ClearBins,RecalcRoute) + global StepFirstDie_Response + if not "StepFirstDie_Response" in globals(): StepFirstDie_Response = namedtuple("StepFirstDie_Response", "DieX,DieY,CurSite,LastSiteIndex") + return StepFirstDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def StepNextDie(CDieX:int="", CDieY:int="", Site:int=""): + """ + Steps the chuck to the specified x,y die location of the wafer map. If no + command data is passed, the chuck automatically steps to the next logical wafer + map die location. Returns the row and column number of the actual die location + after the move is completed. In addition, the SubDie location, and total number + of SubDies is also returned. If Site (i.e. SubDie) is -1, the chuck will move + to SubDie 0, on the next die; in this case, the first 2 parameters are ignored. + If sent without parameters, it will literally 'step to the next die'. When using + this command from shared code, use SendWithoutParameter(). + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDie",CDieX,CDieY,Site) + global StepNextDie_Response + if not "StepNextDie_Response" in globals(): StepNextDie_Response = namedtuple("StepNextDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepNextDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinMapDie(Bin:int="", CDieX:int="", CDieY:int=""): + """ + Assigns the bin information to the wafer map at the current die, unless a row + and column is specified. Inks the device if the real time inking option (of the + wafer map) is enabled. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 30000 + Example:BinMapDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinMapDie",Bin,CDieX,CDieY) + global BinMapDie_Response + if not "BinMapDie_Response" in globals(): BinMapDie_Response = namedtuple("BinMapDie_Response", "RDieX,RDieY") + return BinMapDie_Response(int(rsp[0]),int(rsp[1])) + +def AssignMapBins(Bins:str=""): + """ + Assigns the pass or fail information to the actual bin value. Redundant to + SetBinCode. + API Status: published + Args: + Bins:str = "" + Command Timeout: 10000 + Example:AssignMapBins PFFFFFF + """ + MessageServerInterface.sendSciCommand("AssignMapBins",Bins) + + +def StepFailedBack(): + """ + Steps the chuck back the number of consecutive failed dies (goes back to the + last known good die) and returns the number of consecutive failed dies. + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedBack") + return int(rsp[0]) + +def StepFailedForward(): + """ + Steps the chuck forward the number of consecutive failed dies (goes to next + untested die). + API Status: published + Returns: + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedForward") + return int(rsp[0]) + +def ReadMapPosition(Pos:int="", FromPos:str=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 1-based, + the first value is 1, not 0. M_pnCurSite returns the currently selected + Subdie (1-based) or 0 if no Subdie is currently selected. This command (i.e. + ReadMapPosition) has been included for legacy support. ReadMapPosition2 is + the preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition",Pos,FromPos) + global ReadMapPosition_Response + if not "ReadMapPosition_Response" in globals(): ReadMapPosition_Response = namedtuple("ReadMapPosition_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def ReadMapYield(): + """ + Returns the actual wafer map yield data information. + API Status: published + Returns: + TotalDies:int + TestedDies:int + Passed:int + Failed:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapYield") + global ReadMapYield_Response + if not "ReadMapYield_Response" in globals(): ReadMapYield_Response = namedtuple("ReadMapYield_Response", "TotalDies,TestedDies,Passed,Failed") + return ReadMapYield_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def BinStepDie(Bin:int="", CDieX:int="", CDieY:int="", Site:int=""): + """ + Bins the current die and steps the chuck to the next selected die location of + the wafer map (default) or steps to the specified Column and Row position, if + these values are passed. In contrast to StepNextDie, the BinStepDie command + will only step from die to die while staying on the current subdie. It will not + step through the subdies so it cannot be used for subdie stepping. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + Example:BinStepDie 1 + """ + rsp = MessageServerInterface.sendSciCommand("BinStepDie",Bin,CDieX,CDieY,Site) + global BinStepDie_Response + if not "BinStepDie_Response" in globals(): BinStepDie_Response = namedtuple("BinStepDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinStepDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetMapHome(DieX:int="", DieY:int=""): + """ + If the command has no parameters it sets the current position as home position + both for the wafer map and for the chuck. Otherwise, it changes the wafer map + home position using the given die coordinates. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapHome",DieX,DieY) + + +def SaveMapFile(FileName:str="", FileType:str=""): + """ + Saves current map file with specified name. + API Status: published + Args: + FileName:str = "" + FileType:str = "m" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SaveMapFile",FileName,FileType) + + +def SetWaferMapMode(Mode:str=""): + """ + Enables or disables an external mode for the application. In the external mode, + all controls are disabled. The application handles all its remote commands in + both modes. Special interactive modes can also be turned on. + API Status: published + Args: + Mode:str = "" + Returns: + ModeType:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("SetWaferMapMode",Mode) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetWaferMapMode(ModeType:str=""): + """ + Returns whether the application is in external mode or not. + API Status: published + Args: + ModeType:str = "" + Returns: + Mode:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapMode",ModeType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferNum(Number:str=""): + """ + Specifies the wafer number. + API Status: published + Args: + Number:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferNum",Number) + + +def GetWaferNum(): + """ + Returns the wafer number for the current wafer. + API Status: published + Returns: + Number:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferNum") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWaferID(ID:str=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferID",ID) + + +def GetWaferID(): + """ + Returns the wafer ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetProductID(ID:str=""): + """ + Specifies the product ID for the current wafer. + API Status: published + Args: + ID:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetProductID",ID) + + +def GetProductID(): + """ + Displays the product ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetProductID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DoInkerRun(): + """ + Instructs the WaferMap to perform an ink run on the current wafer. Returns the + number of dies which were inked during the inker run. + API Status: published + Returns: + InkedDies:int + Command Timeout: 30000 + """ + rsp = MessageServerInterface.sendSciCommand("DoInkerRun") + return int(rsp[0]) + +def CloseWaferMap(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the Wafer Map application. + API Status: internal + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("CloseWaferMap") + + +def GetNumSelectedDies(): + """ + Gets the number of dies in the map which are selected for probing. + API Status: published + Returns: + SelectedDies:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedDies") + return int(rsp[0]) + +def GetSelectedDieCoords(Die:int=""): + """ + Given the index of a selected die in the range [1..NumSelectedDies], returns the + column and row indices for the selected die. + API Status: published + Args: + Die:int = 0 + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedDieCoords",Die) + global GetSelectedDieCoords_Response + if not "GetSelectedDieCoords_Response" in globals(): GetSelectedDieCoords_Response = namedtuple("GetSelectedDieCoords_Response", "DieX,DieY") + return GetSelectedDieCoords_Response(int(rsp[0]),int(rsp[1])) + +def StepNextDieOffset(XOffset:Decimal="", YOffset:Decimal="", CDieX:int="", CDieY:int=""): + """ + Moves to a user-specified offset within a die. The optional col row params can + be used to specify the die. If they are omitted, WaferMap moves to the specified + offset within the next selected die. + API Status: published + Args: + XOffset:Decimal = 0 + YOffset:Decimal = 0 + CDieX:int = 0 + CDieY:int = 0 + Returns: + RDieX:int + RDieY:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextDieOffset",XOffset,YOffset,CDieX,CDieY) + global StepNextDieOffset_Response + if not "StepNextDieOffset_Response" in globals(): StepNextDieOffset_Response = namedtuple("StepNextDieOffset_Response", "RDieX,RDieY") + return StepNextDieOffset_Response(int(rsp[0]),int(rsp[1])) + +def ReadMapPosition2(Pos:int="", FromPos:str=""): + """ + Returns the actual Wafer Map chuck position. The SubDie collection is 0-based, + the first value is 0, not 1. M_pnCurSite returns the currently selected Subdie + (0-based) or -1 if no Subdie is currently selected. This command is the + preferred method for reading Wafer Map chuck position. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + DieX:int + DieY:int + XFromHome:Decimal + YFromHome:Decimal + CurSite:int + LastSiteIndex:int + CurDie:int + DiesCount:int + CurCluster:int + ClustersCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadMapPosition2",Pos,FromPos) + global ReadMapPosition2_Response + if not "ReadMapPosition2_Response" in globals(): ReadMapPosition2_Response = namedtuple("ReadMapPosition2_Response", "DieX,DieY,XFromHome,YFromHome,CurSite,LastSiteIndex,CurDie,DiesCount,CurCluster,ClustersCount") + return ReadMapPosition2_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9])) + +def DeleteSubDie2(Site:int=""): + """ + Deletes selected subdie. The SubDie collection is 0-based, the first value is 0, + not 1. This command is the preferred method for deleting a selected + subdie. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie2",Site) + return int(rsp[0]) + +def DeleteAllSubDie(): + """ + Deletes all subdies for all dies. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("DeleteAllSubDie") + + +def GetDieLabel(DieX:int="", DieY:int=""): + """ + Returns a label from the wafer map at the current die, unless a row and column + are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabel",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabel(Label:str="", DieX:int="", DieY:int=""): + """ + Assigns a label to the wafer map at the current die, unless a row and column are + specified. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabel",Label,DieX,DieY) + + +def StepNextSubDie(Site:int=""): + """ + Steps the chuck to the specified SubDie number relative to the current die + origin of the wafer map. Returns the SubDie number of the actual die location + after the move is completed and the total number of subdies. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextSubDie",Site) + global StepNextSubDie_Response + if not "StepNextSubDie_Response" in globals(): StepNextSubDie_Response = namedtuple("StepNextSubDie_Response", "CurSite,LastSiteIndex") + return StepNextSubDie_Response(int(rsp[0]),int(rsp[1])) + +def OpenWaferMap(FileName:str=""): + """ + Opens a Wafer Map file. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenWaferMap",FileName) + + +def SetDieResult(Result:str="", DieX:int="", DieY:int=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResult",Result,DieX,DieY) + + +def GetDieResult(DieX:int="", DieY:int=""): + """ + Returns a measurement result from the wafer map at the current die, unless a row + and column are specified. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResult",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResult(Result:str="", DieX:int="", DieY:int="", Site:int=""): + """ + Assigns a measurement result to the wafer die map at the current die and the + current subdie, unless a subdie, row, and column are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResult",Result,DieX,DieY,Site) + + +def GetDieMapResult(DieX:int="", DieY:int="", Site:int=""): + """ + Returns a measurement result from the wafer map at the current die and current + subdie, unless a row, column, and subdie are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResult",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BinSubDie(Bin:int="", CDieX:int="", CDieY:int="", Site:int=""): + """ + Assigns the bin information for the current subdie in the current die, unless a + subdie, row, and column are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + Bin:int = 0 + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("BinSubDie",Bin,CDieX,CDieY,Site) + global BinSubDie_Response + if not "BinSubDie_Response" in globals(): BinSubDie_Response = namedtuple("BinSubDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return BinSubDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SetSubDieData(Site:int="", X:Decimal="", Y:Decimal="", Label:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + Site:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieData",Site,X,Y,Label) + + +def GetSubDieData(Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + CurSite:int + X:Decimal + Y:Decimal + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieData",Site) + global GetSubDieData_Response + if not "GetSubDieData_Response" in globals(): GetSubDieData_Response = namedtuple("GetSubDieData_Response", "CurSite,X,Y,Label") + return GetSubDieData_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def GetMapHome(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the home die location of the WaferMap. + API Status: internal + Returns: + DieX:int + DieY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapHome") + global GetMapHome_Response + if not "GetMapHome_Response" in globals(): GetMapHome_Response = namedtuple("GetMapHome_Response", "DieX,DieY") + return GetMapHome_Response(int(rsp[0]),int(rsp[1])) + +def GetMapDims(): + """ + Returns the parameters for the current wafer. + API Status: published + Returns: + MapType:str + XIndex:Decimal + YIndex:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapDims") + global GetMapDims_Response + if not "GetMapDims_Response" in globals(): GetMapDims_Response = namedtuple("GetMapDims_Response", "MapType,XIndex,YIndex,Columns,Rows") + return GetMapDims_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetWaferMapParams(Diameter:Decimal="", DieWidth:Decimal="", DieHeight:Decimal="", FlatLength:Decimal="", FlatAngle:int="", XOffset:Decimal="", YOffset:Decimal="", EdgeArea:Decimal=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are percentages. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def SetRectMapParams(DieWidth:Decimal="", DieHeight:Decimal="", Columns:int="", Rows:int=""): + """ + Creates the rectangle wafer with specified parameters. + API Status: published + Args: + DieWidth:Decimal = 0 + DieHeight:Decimal = 0 + Columns:int = 0 + Rows:int = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetRectMapParams",DieWidth,DieHeight,Columns,Rows) + + +def StepToDie(DieNumber:int="", Site:int=""): + """ + Steps the chuck to the die location specified by the die number of the wafer + map. If no command data is passed, the chuck automatically steps to the next + logical wafer map die location. Returns the row and column number of the actual + die location after the move is completed. In addition, the SubDie location, and + total number of SubDies is also returned. + API Status: published + Args: + DieNumber:int = -1 + Site:int = 0 + Returns: + RDieX:int + RDieY:int + CurSite:int + LastSiteIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepToDie",DieNumber,Site) + global StepToDie_Response + if not "StepToDie_Response" in globals(): StepToDie_Response = namedtuple("StepToDie_Response", "RDieX,RDieY,CurSite,LastSiteIndex") + return StepToDie_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetMapOrientation(UseOrientationCornerForShift:int=""): + """ + Returns parameters of the map coordinate system. + API Status: published + Args: + UseOrientationCornerForShift:int = 0 + Returns: + Orientation:int + OriginShiftX:int + OriginShiftY:int + UseAlphas:int + UseIOs:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapOrientation",UseOrientationCornerForShift) + global GetMapOrientation_Response + if not "GetMapOrientation_Response" in globals(): GetMapOrientation_Response = namedtuple("GetMapOrientation_Response", "Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs") + return GetMapOrientation_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4])) + +def SetMapOrientation(Orientation:int="", OriginShiftX:int="", OriginShiftY:int="", UseAlphas:int="", UseIOs:int="", UseOrientationCornerForShift:int=""): + """ + Sets up new map origin and new coordinate system after that. + API Status: published + Args: + Orientation:int = 0 + OriginShiftX:int = 0 + OriginShiftY:int = 0 + UseAlphas:int = 0 + UseIOs:int = 1 + UseOrientationCornerForShift:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapOrientation",Orientation,OriginShiftX,OriginShiftY,UseAlphas,UseIOs,UseOrientationCornerForShift) + + +def SetDieStatus(DieX:int="", DieY:int="", Status:str=""): + """ + Sets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieStatus",DieX,DieY,Status) + + +def GetDieStatus(DieX:int="", DieY:int=""): + """ + Gets the die status. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieStatus",DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieStatus(Site:int="", Status:str=""): + """ + Sets the SubDie status. The SubDie collection is 0-based, the first value is 0, + not 1. + API Status: published + Args: + Site:int = 0 + Status:str = "0" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieStatus",Site,Status) + + +def GetSubDieStatus(Site:int=""): + """ + Returns the SubDie status. The SubDie collection is 0-based, the first value is + 0, not 1. + API Status: published + Args: + Site:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieStatus",Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetBinCode(Bin:int=""): + """ + Returns the Die size from the current map. + API Status: published + Args: + Bin:int = 0 + Returns: + Chars:str + Color:int + Status:str + Inker1:int + Inker2:int + Inker3:int + Inker4:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinCode",Bin) + global GetBinCode_Response + if not "GetBinCode_Response" in globals(): GetBinCode_Response = namedtuple("GetBinCode_Response", "Chars,Color,Status,Inker1,Inker2,Inker3,Inker4") + return GetBinCode_Response(str(rsp[0]),int(rsp[1]),str(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetBinCode(Bin:int="", Chars:str="", Color:int="", Status:str="", Inker1:int="", Inker2:int="", Inker3:int="", Inker4:int=""): + """ + Appends the Bin information to a bin code. + API Status: published + Args: + Bin:int = 0 + Chars:str = "" + Color:int = 0 + Status:str = "" + Inker1:int = 0 + Inker2:int = 0 + Inker3:int = 0 + Inker4:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinCode",Bin,Chars,Color,Status,Inker1,Inker2,Inker3,Inker4) + + +def GetDieDataAsNum(CDieIndex:int=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Number is absent it uses the current die + on the wafer. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsNum",CDieIndex) + global GetDieDataAsNum_Response + if not "GetDieDataAsNum_Response" in globals(): GetDieDataAsNum_Response = namedtuple("GetDieDataAsNum_Response", "RDieIndex,DieX,DieY,Bin,Result") + return GetDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsNum(DieIndex:int="", Bin:int="", Result:str=""): + """ + Sets the Die Information. If the Die Number is invalid it returns an error. + API Status: published + Args: + DieIndex:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsNum",DieIndex,Bin,Result) + + +def GetSubDieDataAsNum(CDieIndex:int="", Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + RDieIndex:int + DieX:int + DieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsNum",CDieIndex,Site) + global GetSubDieDataAsNum_Response + if not "GetSubDieDataAsNum_Response" in globals(): GetSubDieDataAsNum_Response = namedtuple("GetSubDieDataAsNum_Response", "RDieIndex,DieX,DieY,CurSite,Bin,Result") + return GetSubDieDataAsNum_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsNum(DieIndex:int="", Site:int="", Bin:int="", Result:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieIndex:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsNum",DieIndex,Site,Bin,Result) + + +def GetDieDataAsColRow(CDieX:int="", CDieY:int=""): + """ + Returns the Die Information in the Row Column format. If the Die Number is + invalid it returns an error. If the Die Column and Row are absent it uses the + current die on the wafer. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieDataAsColRow",CDieX,CDieY) + global GetDieDataAsColRow_Response + if not "GetDieDataAsColRow_Response" in globals(): GetDieDataAsColRow_Response = namedtuple("GetDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,Bin,Result") + return GetDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def SetDieDataAsColRow(DieX:int="", DieY:int="", Bin:int="", Result:str=""): + """ + Sets the Data in the Row Column format. If the Die is invalid it returns an + error. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieDataAsColRow",DieX,DieY,Bin,Result) + + +def GetSubDieDataAsColRow(CDieX:int="", CDieY:int="", Site:int=""): + """ + Returns the information of a SubDie. The SubDie collection is 0-based, the first + value is 0, not 1. + API Status: published + Args: + CDieX:int = 0 + CDieY:int = 0 + Site:int = 0 + Returns: + DieIndex:int + RDieX:int + RDieY:int + CurSite:int + Bin:int + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieDataAsColRow",CDieX,CDieY,Site) + global GetSubDieDataAsColRow_Response + if not "GetSubDieDataAsColRow_Response" in globals(): GetSubDieDataAsColRow_Response = namedtuple("GetSubDieDataAsColRow_Response", "DieIndex,RDieX,RDieY,CurSite,Bin,Result") + return GetSubDieDataAsColRow_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def SetSubDieDataAsColRow(DieX:int="", DieY:int="", Site:int="", Bin:int="", Result:str=""): + """ + Sets up SubDie data. The SubDie collection is 0-based, the first value is 0, not + 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Bin:int = 0 + Result:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieDataAsColRow",DieX,DieY,Site,Bin,Result) + + +def SelectAllDiesForProbing(DoSelectAll:int="", DoEdgeDies:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables all dies. + API Status: internal + Args: + DoSelectAll:int = 0 + DoEdgeDies:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SelectAllDiesForProbing",DoSelectAll,DoEdgeDies) + + +def GetMapName(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current WaferMap Filename. + API Status: internal + Returns: + Name:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapName") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetLotID(ID:str=""): + """ + Specifies the ID for the current wafer. + API Status: published + Args: + ID:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetLotID",ID) + + +def GetLotID(): + """ + Returns the Lot ID for the current wafer. + API Status: published + Returns: + ID:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetLotID") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StepFirstCluster(ClearBins:int="", RecalcRoute:int=""): + """ + Steps the chuck to the first die cluster of the cluster map. If clusters are not + defined, the first Die is used. Returns the row and column information of the + actual cluster and die location after the move is completed. Switches to remote + control if the "Disable Velox" flag is set in the external options window. + API Status: published + Args: + ClearBins:int = 1 + RecalcRoute:int = 1 + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFirstCluster",ClearBins,RecalcRoute) + global StepFirstCluster_Response + if not "StepFirstCluster_Response" in globals(): StepFirstCluster_Response = namedtuple("StepFirstCluster_Response", "ClusterX,ClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepFirstCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def StepNextCluster(CClusterX:int="", CClusterY:int=""): + """ + Steps the chuck to the specified x,y cluster die location of the cluster map. If + no command data is passed, the chuck automatically steps to the next logical + cluster map location. If clusters are not defined, the Die information is used. + Returns the row and column number of the actual die location after the move is + completed. + API Status: published + Args: + CClusterX:int = 0 + CClusterY:int = 0 + Returns: + RClusterX:int + RClusterY:int + ClusterIndex:int + IncompleteCluster:int + DieX:int + DieY:int + DieIndex:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepNextCluster",CClusterX,CClusterY) + global StepNextCluster_Response + if not "StepNextCluster_Response" in globals(): StepNextCluster_Response = namedtuple("StepNextCluster_Response", "RClusterX,RClusterY,ClusterIndex,IncompleteCluster,DieX,DieY,DieIndex") + return StepNextCluster_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def SetMapRoute(MoveMode:str="", StartColumn:str="", StartRow:str="", MoveParam:str=""): + """ + Specifies the Move Path for the probe station inside the Wafer Map. Optimization + is done for the shortest move way for the station. + API Status: published + Args: + MoveMode:str = "B" + StartColumn:str = "L" + StartRow:str = "T" + MoveParam:str = "H" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetMapRoute",MoveMode,StartColumn,StartRow,MoveParam) + + +def GetMapRoute(): + """ + Returns the specified move path for the probe station inside the Wafer Map. + API Status: published + Returns: + MoveMode:str + StartColumn:str + StartRow:str + MoveParam:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetMapRoute") + global GetMapRoute_Response + if not "GetMapRoute_Response" in globals(): GetMapRoute_Response = namedtuple("GetMapRoute_Response", "MoveMode,StartColumn,StartRow,MoveParam") + return GetMapRoute_Response(str(rsp[0]),str(rsp[1]),str(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def SetClusterParams(UseClusters:int="", ClusterWidth:int="", ClusterHeight:int="", TestIncomplete:int=""): + """ + Specifies the clusters parameters. + API Status: published + Args: + UseClusters:int = 0 + ClusterWidth:int = 1 + ClusterHeight:int = 1 + TestIncomplete:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterParams",UseClusters,ClusterWidth,ClusterHeight,TestIncomplete) + + +def GetClusterParams(): + """ + Returns current clusters parameters. + API Status: published + Returns: + UseClusters:int + ClusterWidth:int + ClusterHeight:int + TestIncomplete:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterParams") + global GetClusterParams_Response + if not "GetClusterParams_Response" in globals(): GetClusterParams_Response = namedtuple("GetClusterParams_Response", "UseClusters,ClusterWidth,ClusterHeight,TestIncomplete") + return GetClusterParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def NewWaferMap(): + """ + Deletes current wafer map, sub dies and binning information; then creates new + wafer map with defaults parameters. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("NewWaferMap") + + +def AddSubDie(X:Decimal="", Y:Decimal="", Label:str=""): + """ + Adds new subdie at the end of the table. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Label:str = "" + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("AddSubDie",X,Y,Label) + return int(rsp[0]) + +def DeleteSubDie(Site:int=""): + """ + Deletes selected subdie. The SubDie collection is 1-based, the first value is 1, + not 0. If 0 is passed in as the subdie index, WaferMap will delete all subdies + for all dies.This command (i.e. DeleteSubDie) has been included for legacy + support. DeleteSubDie2 is the preferred method for deleting a selected + subdie. DeleteAllSubDie is the preferred method for deleting all subdies for all + dies. + API Status: published + Args: + Site:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DeleteSubDie",Site) + return int(rsp[0]) + +def GetNumSelectedClusters(): + """ + Gets the number of clusters in the map which are selected for probing. + API Status: published + Returns: + SelectedClusters:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetNumSelectedClusters") + return int(rsp[0]) + +def GetSelectedClusterCoords(ClusterIndex:int=""): + """ + Given the index of a selected cluster in the range [1..NumSelectedClusters], + returns the column and row indices for the selected cluster. + API Status: published + Args: + ClusterIndex:int = 0 + Returns: + ClusterX:int + ClusterY:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSelectedClusterCoords",ClusterIndex) + global GetSelectedClusterCoords_Response + if not "GetSelectedClusterCoords_Response" in globals(): GetSelectedClusterCoords_Response = namedtuple("GetSelectedClusterCoords_Response", "ClusterX,ClusterY") + return GetSelectedClusterCoords_Response(int(rsp[0]),int(rsp[1])) + +def GetClusterDieStatus(ClusterX:int="", ClusterY:int="", DieX:int="", DieY:int=""): + """ + Gets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Returns: + Status:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterDieStatus",ClusterX,ClusterY,DieX,DieY) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetClusterDieStatus(ClusterX:int="", ClusterY:int="", DieX:int="", DieY:int="", Status:str=""): + """ + Sets the die status in the cluster. Die coordinates are internal for the cluster + using the wafer map coordinate system. (0,0) die in the cluster is left top + corner (whether this die exists or not). + API Status: published + Args: + ClusterX:int = 0 + ClusterY:int = 0 + DieX:int = 0 + DieY:int = 0 + Status:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetClusterDieStatus",ClusterX,ClusterY,DieX,DieY,Status) + + +def OpenBinCodeTable(FileName:str=""): + """ + Opens a Bin Code Table file (.bct) with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("OpenBinCodeTable",FileName) + + +def SaveBinCodeTable(FileName:str=""): + """ + Saves bin code table to a file with the specified name. + API Status: published + Args: + FileName:str = "" + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SaveBinCodeTable",FileName) + + +def SetBinTableSize(BinsSize:int=""): + """ + Sets size of the bin code table. This is the size of bins used in statistics and + binning. + API Status: published + Args: + BinsSize:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetBinTableSize",BinsSize) + + +def GetBinTableSize(): + """ + Gets size of the bin code table. + API Status: published + Returns: + BinsSize:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetBinTableSize") + return int(rsp[0]) + +def StepFailedClusterBack(): + """ + Steps the chuck the consecutive failed clusters back (goes back to the last + known good cluster) and returns the number of consecutive failed clusters. + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterBack") + return int(rsp[0]) + +def StepFailedClusterForward(): + """ + Steps the chuck the consecutive failed clusters forward and returns the number + of consecutive failed clusters (goes to next untested cluster). + API Status: published + Returns: + FailedClusters:int + Command Timeout: 6000000 + """ + rsp = MessageServerInterface.sendSciCommand("StepFailedClusterForward") + return int(rsp[0]) + +def GoToWaferHome(): + """ + Moves the chuck to the wafer home position. + API Status: published + Command Timeout: 6000000 + """ + MessageServerInterface.sendSciCommand("GoToWaferHome") + + +def GetWaferInfo(): + """ + Returns a number of all units marked to test. Note that TestSites is a number of + all sites for all dies. + API Status: published + Returns: + ClustersCount:int + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferInfo") + global GetWaferInfo_Response + if not "GetWaferInfo_Response" in globals(): GetWaferInfo_Response = namedtuple("GetWaferInfo_Response", "ClustersCount,DiesCount,SitesCount") + return GetWaferInfo_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetClusterInfo(Cluster:int=""): + """ + Returns a number of all dies and sites marked to test in the given cluster. + API Status: published + Args: + Cluster:int = 0 + Returns: + DiesCount:int + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetClusterInfo",Cluster) + global GetClusterInfo_Response + if not "GetClusterInfo_Response" in globals(): GetClusterInfo_Response = namedtuple("GetClusterInfo_Response", "DiesCount,SitesCount") + return GetClusterInfo_Response(int(rsp[0]),int(rsp[1])) + +def GetDieInfo(Die:int=""): + """ + Returns a number of sites marked to test in the given die. + API Status: published + Args: + Die:int = 0 + Returns: + SitesCount:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieInfo",Die) + return int(rsp[0]) + +def ConvertToAlphas(Start:int="", Finish:int=""): + """ + Returns a string of the alpha column coordinates for the given range divided by + spaces. + API Status: published + Args: + Start:int = 0 + Finish:int = 0 + Returns: + Alphas:str + Command Timeout: 240000 + """ + rsp = MessageServerInterface.sendSciCommand("ConvertToAlphas",Start,Finish) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetActiveLayer(Layer:str=""): + """ + Sets new active layer. + API Status: published + Args: + Layer:str = "" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetActiveLayer",Layer) + + +def GetActiveLayer(): + """ + Returns current active layer. + API Status: published + Returns: + Layer:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetActiveLayer") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieRefPoint(RefX:Decimal="", RefY:Decimal=""): + """ + Sets a new reference point for the die. This point is NOT used for die stepping, + nor for subdie stepping. When using the "Chuck Position from Reference" WaferMap + GUI setting, the Die Reference Point can be set to be more representative of the + actual reference location within the die. A setting of (0.0, 0.0) is defined as + the upper left corner of the die. All subdie coordinates are relative to upper + left corner of the die. + API Status: published + Args: + RefX:Decimal = 0 + RefY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieRefPoint",RefX,RefY) + + +def GetDieRefPoint(): + """ + Returns current reference point for the die. For details see SetDieRefPoint + command. + API Status: published + Returns: + RefX:Decimal + RefY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieRefPoint") + global GetDieRefPoint_Response + if not "GetDieRefPoint_Response" in globals(): GetDieRefPoint_Response = namedtuple("GetDieRefPoint_Response", "RefX,RefY") + return GetDieRefPoint_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ClearAllBins(): + """ + Clears all binning data in the wafer map. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("ClearAllBins") + + +def SetWindowState(State:str="", Window:str=""): + """ + Has sense in the application only (not for ActiveX controls). It shows or hides + a window. All parameters are case-insensitive. + API Status: published + Args: + State:str = "s" + Window:str = "setup" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWindowState",State,Window) + + +def SetCurrentBin(Bin:int="", ButtonStatus:int=""): + """ + Sets the current bin for the application. Second parameter allows to enable or + disable "Mark with Bin" mode in the application. + API Status: published + Args: + Bin:int = 0 + ButtonStatus:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetCurrentBin",Bin,ButtonStatus) + + +def GetCurrentBin(): + """ + Returns the current bin in the application. + API Status: published + Returns: + Bin:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetCurrentBin") + return int(rsp[0]) + +def ReadClusterPosition(Pos:int="", FromPos:str=""): + """ + Returns the actual wafer map cluster position. If the cluster probing is + disabled, the command will assume a cluster of size 1x1. + API Status: published + Args: + Pos:int = 0 + FromPos:str = "R" + Returns: + ClusterX:int + ClusterY:int + ClusterIndex:int + DieX:int + DieY:int + DieIndex:int + ClusterWidth:int + ClusterHeight:int + EnabledDies:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("ReadClusterPosition",Pos,FromPos) + global ReadClusterPosition_Response + if not "ReadClusterPosition_Response" in globals(): ReadClusterPosition_Response = namedtuple("ReadClusterPosition_Response", "ClusterX,ClusterY,ClusterIndex,DieX,DieY,DieIndex,ClusterWidth,ClusterHeight,EnabledDies") + return ReadClusterPosition_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),str("" if len(rsp) < 9 else ' '.join(rsp[8:]))) + +def GetWaferMapParams(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are percentages. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams") + global GetWaferMapParams_Response + if not "GetWaferMapParams_Response" in globals(): GetWaferMapParams_Response = namedtuple("GetWaferMapParams_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def GetRectMapParams(): + """ + Creates a rectangular wafermap with specified parameters. + API Status: published + Returns: + DieWidth:Decimal + DieHeight:Decimal + Columns:int + Rows:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetRectMapParams") + global GetRectMapParams_Response + if not "GetRectMapParams_Response" in globals(): GetRectMapParams_Response = namedtuple("GetRectMapParams_Response", "DieWidth,DieHeight,Columns,Rows") + return GetRectMapParams_Response(Decimal(rsp[0]),Decimal(rsp[1]),int(rsp[2]),int(rsp[3])) + +def SyncMapHome(X:Decimal="", Y:Decimal=""): + """ + Tries to find an appropriate position in the wafer for the current chuck + position. X and Y describe the chuck position of the wafer center relatively to + the chuck zero position. If the wafer position is found the command sets it as + the wafer map home position and sets the current chuck position as the chuck + home position. If there is no corresponding wafer position the command returns + error 701. Command is used by AutoAlign for the BuildMap feature. + API Status: published + Args: + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SyncMapHome",X,Y) + + +def SetWaferProfileOptions(ProfileSensor:str="", SearchSpeed:Decimal="", Gap:Decimal="", SuccessRatio:Decimal="", ProfDistX:Decimal="", ProfDistY:Decimal=""): + """ + Sets some WaferMap profiling options remotely. + API Status: published + Args: + ProfileSensor:str = "e" + SearchSpeed:Decimal = 50 + Gap:Decimal = 10 + SuccessRatio:Decimal = 75 + ProfDistX:Decimal = 0 + ProfDistY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferProfileOptions",ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY) + + +def GetWaferProfileOptions(): + """ + Returns predefined settings of the WaferMap profiling options. + API Status: published + Returns: + ProfileSensor:str + SearchSpeed:Decimal + Gap:Decimal + SuccessRatio:Decimal + ProfDistX:Decimal + ProfDistY:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfileOptions") + global GetWaferProfileOptions_Response + if not "GetWaferProfileOptions_Response" in globals(): GetWaferProfileOptions_Response = namedtuple("GetWaferProfileOptions_Response", "ProfileSensor,SearchSpeed,Gap,SuccessRatio,ProfDistX,ProfDistY") + return GetWaferProfileOptions_Response(str(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def StartWaferProfiling(DoContinue:int=""): + """ + Starts the profiling process. To determine the current profiling state, use + GetWaferProfilingStatus command. + API Status: published + Args: + DoContinue:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StartWaferProfiling",DoContinue) + + +def GetWaferProfilingStatus(): + """ + Returns status of the profiling process. If this status is true, the process is + started. + API Status: published + Returns: + Started:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferProfilingStatus") + return int(rsp[0]) + +def StopWaferProfiling(): + """ + Stops the profiling process. + API Status: published + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("StopWaferProfiling") + + +def DoWaferProfiling(): + """ + Profiles the wafer and returns a status of the profiling as an error code. + API Status: published + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfiling") + + +def DoWaferProfilingOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Profiles the wafer and returns a status of the profiling as an error code. + Executes profiling using the off axis camera + API Status: internal + Command Timeout: 36000000 + """ + MessageServerInterface.sendSciCommand("DoWaferProfilingOffAxis") + + +def GetSubDieLabel(DieX:int="", DieY:int="", Site:int=""): + """ + Returns a label from the wafer map at the current die and current subdie, unless + a row, column, and subdie are specified. The SubDie collection is 0-based, the + first value is 0, not 1. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabel",DieX,DieY,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabel(Label:str="", DieX:int="", DieY:int="", Site:int=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, row, and column are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + DieX:int = 0 + DieY:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabel",Label,DieX,DieY,Site) + + +def GetSubDieLabelAsNum(CDieIndex:int="", Site:int=""): + """ + Returns a label from the wafer map the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSubDieLabelAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSubDieLabelAsNum(Label:str="", CDieIndex:int="", Site:int=""): + """ + Assigns a label to the wafer map at the current die and the current subdie, + unless a subdie, and die number are specified. The SubDie collection is 0-based, + the first value is 0, not 1. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetSubDieLabelAsNum",Label,CDieIndex,Site) + + +def GetDieLabelAsNum(CDieIndex:int=""): + """ + Returns a label from the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Label:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieLabelAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieLabelAsNum(Label:str="", CDieIndex:int=""): + """ + Assigns a label to the wafer map at the current die, unless a die number is + specified. + API Status: published + Args: + Label:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieLabelAsNum",Label,CDieIndex) + + +def GetHomeDieOffset(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the XY offset from the reference position of the Home Die to wafer + center in chuck coordinates. + API Status: internal + Returns: + X:Decimal + Y:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetHomeDieOffset") + global GetHomeDieOffset_Response + if not "GetHomeDieOffset_Response" in globals(): GetHomeDieOffset_Response = namedtuple("GetHomeDieOffset_Response", "X,Y") + return GetHomeDieOffset_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetWaferMapParams2(Diameter:Decimal="", DieWidth:Decimal="", DieHeight:Decimal="", FlatLength:Decimal="", FlatAngle:int="", XOffset:Decimal="", YOffset:Decimal="", EdgeArea:Decimal=""): + """ + Creates the circle wafer with specified parameters. If parameter is omitted, + then zero is used. For this version of the command, units for XOffset and + YOffset are microns. + API Status: published + Args: + Diameter:Decimal = 200 + DieWidth:Decimal = 10000 + DieHeight:Decimal = 10000 + FlatLength:Decimal = 20 + FlatAngle:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + EdgeArea:Decimal = 0 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("SetWaferMapParams2",Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea) + + +def GetWaferMapParams2(): + """ + Returns the circle wafer parameters. For this version of the command, units for + XOffset and YOffset are microns. + API Status: published + Returns: + Diameter:Decimal + DieWidth:Decimal + DieHeight:Decimal + FlatLength:Decimal + FlatAngle:int + XOffset:Decimal + YOffset:Decimal + EdgeArea:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferMapParams2") + global GetWaferMapParams2_Response + if not "GetWaferMapParams2_Response" in globals(): GetWaferMapParams2_Response = namedtuple("GetWaferMapParams2_Response", "Diameter,DieWidth,DieHeight,FlatLength,FlatAngle,XOffset,YOffset,EdgeArea") + return GetWaferMapParams2_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),Decimal(rsp[5]),Decimal(rsp[6]),Decimal(rsp[7])) + +def SetWaferTestAngle(Angle:int=""): + """ + This command sets the Wafer Test Angle. This is different from the notch angle + and allows rotating the WaferMap. + API Status: published + Args: + Angle:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetWaferTestAngle",Angle) + + +def GetWaferTestAngle(): + """ + This returns the Wafer Test Angle. This is different from the notch angle and + allows rotating the WaferMap. + API Status: published + Returns: + Angle:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferTestAngle") + return int(rsp[0]) + +def LoadPreMappedDiesTable(FileName:str="", ClearMap:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads the Pre-Mapped Dies Table file with specified name. + API Status: internal + Args: + FileName:str = "" + ClearMap:int = 1 + Command Timeout: 240000 + """ + MessageServerInterface.sendSciCommand("LoadPreMappedDiesTable",FileName,ClearMap) + + +def GetPreMappedDieInfo(DieX:int="", DieY:int=""): + """ + This command is valid when a PreMapped Dies Table has been loaded. Returns + values at the current die, unless a column (M_pnDieX) and row (M_pnDieY) are + specified. Returns actual (as measured during the Pre-Mapping) x, y, z, and + theta die positions. Also returns whether or not Z and Theta are being used. + This command is only valid when a Pre-Mapped Dies Table has been loaded. If a + PreMapped Dies Table has NOT been loaded, ERR_IllegalParameters (715) is + returned. + API Status: published + Args: + DieX:int = 0 + DieY:int = 0 + Returns: + UseZ:int + UseTheta:int + ActualX:Decimal + ActualY:Decimal + ActualZ:Decimal + Theta:Decimal + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPreMappedDieInfo",DieX,DieY) + global GetPreMappedDieInfo_Response + if not "GetPreMappedDieInfo_Response" in globals(): GetPreMappedDieInfo_Response = namedtuple("GetPreMappedDieInfo_Response", "UseZ,UseTheta,ActualX,ActualY,ActualZ,Theta") + return GetPreMappedDieInfo_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def GetDieResultAsNum(CDieIndex:int=""): + """ + Returns a measurement result from the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + CDieIndex:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieResultAsNum",CDieIndex) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieResultAsNum(Result:str="", CDieIndex:int=""): + """ + Assigns a measurement result to the wafer map at the current die, unless a die + number is specified. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieResultAsNum",Result,CDieIndex) + + +def GetDieMapResultAsNum(CDieIndex:int="", Site:int=""): + """ + Returns a measurement result from the wafer map the current die and the current + subdie, unless a subdie, and die number are specified. The SubDie collection is + 0-based, the first value is 0, not 1. + API Status: published + Args: + CDieIndex:int = 0 + Site:int = 0 + Returns: + Result:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetDieMapResultAsNum",CDieIndex,Site) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetDieMapResultAsNum(Result:str="", CDieIndex:int="", Site:int=""): + """ + Assigns a measurement result to the wafer die map at the current die at the + current subdie, unless a subdie, and die number are specified. The SubDie + collection is 0-based, the first value is 0, not 1. + API Status: published + Args: + Result:str = "" + CDieIndex:int = 0 + Site:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetDieMapResultAsNum",Result,CDieIndex,Site) + + +def MapEdgeDies(Enable:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Enables or disables edge dies for test + API Status: internal + Args: + Enable:int = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("MapEdgeDies",Enable) + + +def GetSpectrumData(DataPath:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows access to read any data item in Spectrum explorer. GetSpectrumData + AlignWafer/ProjectData/Mark1/ChuckPosition/X GetSpectrumData Chuck + Camera/Camera Settings/Shutter + API Status: internal + Args: + DataPath:str = "" + Returns: + Value:str + Command Timeout: 6000 + Example:GetSpectrumData Chuck Camera/Camera Settings/Shutter + """ + rsp = MessageServerInterface.sendSciCommand("GetSpectrumData",DataPath) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumData(PathAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Allows changing any data item in Spectrum explorer. Works independent of access + level. SetSpectrumData AlignWafer/ProjectData/Mark1/ChuckPosition/X=1000 + SetSpectrumData Chuck Camera/Camera Settings/Shutter=17 + API Status: internal + Args: + PathAndValue:str = "" + Command Timeout: 6000 + Example:SetSpectrumData Scope Camera/Camera Settings/Shutter=17 + """ + MessageServerInterface.sendSciCommand("SetSpectrumData",PathAndValue) + + +def ReadVMPosition(ToolName:str="", XY:int="", Z:int="", Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command reads the current chuck and microscope position and sets them as + new controller or chuck and microscope positions. The command was originally used + by ReAlignWizard but may be removed in the future because of direct access to + tooldata within Spectrum. + API Status: internal + Args: + ToolName:str = "" + XY:int = 1 + Z:int = 0 + Model:int = -1 + Command Timeout: 60000 + Example:ReadVMPosition AlignWafer 1 0 0 + """ + MessageServerInterface.sendSciCommand("ReadVMPosition",ToolName,XY,Z,Model) + + +def MoveToVMPosition(ToolName:str="", XYChuck:int="", ZChuck:int="", XYScope:int="", ZScope:int="", Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command moves to trained stages positions of a requested tool. Command is + used by ReAlignWizard to move to the trained positions for AutoAlign and + DetectWaferHeight. + API Status: internal + Args: + ToolName:str = "" + XYChuck:int = 1 + ZChuck:int = 1 + XYScope:int = 0 + ZScope:int = 0 + Model:int = -1 + Command Timeout: 120000 + Example:MoveToVMPosition AlignWafer 1 0 0 0 0 + """ + MessageServerInterface.sendSciCommand("MoveToVMPosition",ToolName,XYChuck,ZChuck,XYScope,ZScope,Model) + + +def ShapeTracker(SetHome:int="", AutoEdgeFind:int="", FileName:str=""): + """ + ShapeTracker automatically tracks the shape of a substrate (e.g. a broken wafer) + to determine the contour of it. The data will be memorized as xy coordinates of + contour points referenced to the home position. These Points are written to a + file after tracking the shape. + API Status: published + Args: + SetHome:int = 1 + AutoEdgeFind:int = 0 + FileName:str = "" + Command Timeout: 600000 + Example:ShapeTracker 1 + """ + MessageServerInterface.sendSciCommand("ShapeTracker",SetHome,AutoEdgeFind,FileName) + + +def DetectWaferHeight(SetStartPosition:int="", Synchronize:int="", ChuckX:Decimal="", ChuckY:Decimal=""): + """ + Synchronizes chuck and top camera in X, Y and Z. Then the wafer surface is + focused on the trained chuck position or the manual adjusted reference position. + This tool uses the FindFocus tool with its own Range. + API Status: published + Args: + SetStartPosition:int = 0 + Synchronize:int = 0 + ChuckX:Decimal = -1 + ChuckY:Decimal = -1 + Returns: + PositionX:Decimal + PositionY:Decimal + WaferHeight:Decimal + SynchGap:Decimal + ZOffset:Decimal + Stage:str + Command Timeout: 300000 + Example:DetectWaferHeight 0 1 + """ + rsp = MessageServerInterface.sendSciCommand("DetectWaferHeight",SetStartPosition,Synchronize,ChuckX,ChuckY) + global DetectWaferHeight_Response + if not "DetectWaferHeight_Response" in globals(): DetectWaferHeight_Response = namedtuple("DetectWaferHeight_Response", "PositionX,PositionY,WaferHeight,SynchGap,ZOffset,Stage") + return DetectWaferHeight_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),str("" if len(rsp) < 6 else ' '.join(rsp[5:]))) + +def CheckSpectrumPlugin(Plugin:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command checks if a plugin is trained and returns a string of error/warning + messages including information about what is not trained, setup for the tool to + run. + API Status: internal + Args: + Plugin:str = "" + Returns: + PluginAvailable:int + Message:str + Command Timeout: 1000 + Example:CheckSpectrumPlugin AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("CheckSpectrumPlugin",Plugin) + global CheckSpectrumPlugin_Response + if not "CheckSpectrumPlugin_Response" in globals(): CheckSpectrumPlugin_Response = namedtuple("CheckSpectrumPlugin_Response", "PluginAvailable,Message") + return CheckSpectrumPlugin_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AutoAlign(SetValue:int="", SkipSettingHome:int=""): + """ + Executes the AutoAlign tool to do a theta alignment of the wafer with optional + index calculation or thermal expansion measurement. The command will update home + if home was trained. It will only move to its trained chuck/scope position + before starting the alignment if the option "MoveToTrainedXYPosition" and/or + "MoveToTrainedZPosition" is true. + API Status: published + Args: + SetValue:int = 0 + SkipSettingHome:int = 0 + Command Timeout: 300000 + Example:AutoAlign 1 + """ + MessageServerInterface.sendSciCommand("AutoAlign",SetValue,SkipSettingHome) + + +def SetCameraQuiet(Active:int=""): + """ + Activates/deactivates the camera quiet mode. (Applies only to ATM300A and + SPS300/SUMMIT200 stations.) The camera quiet mode deactivates the chuck, + platen and contact view camera and triggers a digital output which + connects/disconnects these cameras firewire connection to the PC. + API Status: published + Args: + Active:int = 0 + Command Timeout: 30000 + Example:SetCameraQuiet 1 + """ + MessageServerInterface.sendSciCommand("SetCameraQuiet",Active) + + +def SetRefDieOffset(RefDieCol:int="", RefDieRow:int="", RefDieDistToCentreX:Decimal="", RefDieDistToCentreY:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is based on the SetMapOrientation command. It allows shifting the + center of the reference die to the center of the wafer. + API Status: internal + Args: + RefDieCol:int = 0 + RefDieRow:int = 0 + RefDieDistToCentreX:Decimal = 0 + RefDieDistToCentreY:Decimal = 0 + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetRefDieOffset",RefDieCol,RefDieRow,RefDieDistToCentreX,RefDieDistToCentreY) + + +def AlignWafer(TrackPosition:int=""): + """ + Performs a two-point alignment and moves chuck to the trained align position. XY + correction is made afterwards to calculate the new home position. + API Status: published + Args: + TrackPosition:int = 0 + Returns: + ThetaOffset:Decimal + Command Timeout: 120000 + Example:AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("AlignWafer",TrackPosition) + return Decimal(rsp[0]) + +def AlignChip(): + """ + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). The + current chip is assumed to be in the region of interest when the command is + called. + API Status: published + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChip + """ + rsp = MessageServerInterface.sendSciCommand("AlignChip") + global AlignChip_Response + if not "AlignChip_Response" in globals(): AlignChip_Response = namedtuple("AlignChip_Response", "ThetaOffset,XOffset,YOffset") + return AlignChip_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def FindFocus(StepCount:int="", Range:Decimal=""): + """ + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. + API Status: published + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocus 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocus",StepCount,Range) + global FindFocus_Response + if not "FindFocus_Response" in globals(): FindFocus_Response = namedtuple("FindFocus_Response", "ZPosition,Stage") + return FindFocus_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAux(AuxSiteID:int=""): + """ + Performs an automated aux site alignment in XYZ. Tool can correct reference + position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAux 1 + """ + MessageServerInterface.sendSciCommand("AlignAux",AuxSiteID) + + +def FindFeature(Model:int="", ReturnDistanceFromModelOrigin:int="", UseSingleImageAcquisition:int=""): + """ + Search user-defined models. Up to 40 different models can be trained. After + training, these models can be searched on screen either by direct user + interaction or from external applications with a remote command. The remote + command returns the X/Y-Positions, angle (degree) and score value (0 - 1.0) for + each instance of the controller found in the region of interest. + API Status: published + Args: + Model:int = 1 + ReturnDistanceFromModelOrigin:int = 0 + UseSingleImageAcquisition:int = 1 + Returns: + Data:str + Command Timeout: 10000 + Example:FindFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("FindFeature",Model,ReturnDistanceFromModelOrigin,UseSingleImageAcquisition) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CloseSpectrum(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + CloseSpectrum closes the Spectrum application. Used internally by CommonCommands + during Project loading. Does save configuration data but does not save project + data. + API Status: internal + Command Timeout: 6000 + Example:CloseSpectrum + """ + MessageServerInterface.sendSciCommand("CloseSpectrum") + + +def SnapImage(MountPos:str="", FullPath:str="", SnapShotMode:int=""): + """ + Saves the currently displayed image to the specified file. The image is stored + in the requested file format (bmp, jpg or png). By default. it will save the raw + camera image and an image with the overlays that are currently visible on the + camera view. Using a parameter, one can decide to only save either raw image, + overlay image or both. By Specifying 'ALL' as the mount position, the captured + screenshot will consist of the currently selected camera layout without + providing the raw image. If MountPos and FullPath are empty then the current + camera view with overlays is copied to the clipboard. + API Status: published + Args: + MountPos:str = "Scope" + FullPath:str = "Image.bmp" + SnapShotMode:int = 2 + Command Timeout: 60000 + Example:SnapImage Scope C:/Temp/Image.bmp + """ + MessageServerInterface.sendSciCommand("SnapImage",MountPos,FullPath,SnapShotMode) + + +def SetCameraView(Name:str="", Zoom:int="", LiveVideo:int="", WindowState:int=""): + """ + Switches the desired video window of Spectrum as foreground and active view. The + camera view can be determined over a tool name or the camera mount position. The + second parameter defines the displays zoom factor to be used. Third parameter is + used to toogle the live video. Last parameter can be used to maximize a window. + API Status: published + Args: + Name:str = "" + Zoom:int = 0 + LiveVideo:int = 2 + WindowState:int = 1 + Command Timeout: 6000 + Example:SetCameraView AlignWafer 0 2 2 + """ + MessageServerInterface.sendSciCommand("SetCameraView",Name,Zoom,LiveVideo,WindowState) + + +def SetCameraLight(Name:str="", State:int="", Shutter:Decimal="", Gain:Decimal="", Brightness:int="", Contrast:int="", Sharpness:int="", Illumination:int=""): + """ + Switches the light of the choosen camera on or off. Light values of -1 will + cause that the parameter is not affected. + API Status: published + Args: + Name:str = "" + State:int = 0 + Shutter:Decimal = -1 + Gain:Decimal = -1 + Brightness:int = -1 + Contrast:int = -1 + Sharpness:int = -1 + Illumination:int = -1 + Command Timeout: 6000 + Example:SetCameraLight AlignWafer 1 20 5 + """ + MessageServerInterface.sendSciCommand("SetCameraLight",Name,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination) + + +def ShowWizard(ToolName:str="", MountPosition:str="", AskExecute:int=""): + """ + Starts the wizard of a given tool on the display defined in the tool settings. + Additionally it can start a wizard for training single models with the syntax + e.g. ShowWizard FindFeature/ProjectData/Features/Feature1/Model For the tools + MeasureOnScreen, Calibrate and CameraOrigin you can specify a mount position + e.g. ShowWizard Calibrate Platen + API Status: published + Args: + ToolName:str = "" + MountPosition:str = "" + AskExecute:int = 0 + Returns: + Cancelled:int + Command Timeout: 10000000 + Example:ShowWizard AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("ShowWizard",ToolName,MountPosition,AskExecute) + return int(rsp[0]) + +def ProbeToPadAlign(Position:str=""): + """ + Sets a new Home position. The command is used during ReAlign to search the + trained home reference controller and to calculate the new xy home position. + API Status: published + Args: + Position:str = "H" + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + Command Timeout: 120000 + Example:ProbeToPadAlign H + """ + rsp = MessageServerInterface.sendSciCommand("ProbeToPadAlign",Position) + global ProbeToPadAlign_Response + if not "ProbeToPadAlign_Response" in globals(): ProbeToPadAlign_Response = namedtuple("ProbeToPadAlign_Response", "XOffsetWafer,YOffsetWafer") + return ProbeToPadAlign_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def ReadOcrString(): + """ + Reads the wafer ID string from the wafer's surface. Returns the read ID as + string. Requires IDTools license. + API Status: published + Returns: + OcrString:str + Command Timeout: 60000 + Example:ReadOcrString + """ + rsp = MessageServerInterface.sendSciCommand("ReadOcrString") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadBarCode(): + """ + Reads the wafers barcode and decodes it to a string. Requires IDTools license. + API Status: published + Returns: + BarCodeString:str + Command Timeout: 60000 + Example:ReadBarCode + """ + rsp = MessageServerInterface.sendSciCommand("ReadBarCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def Read2DMatrixCode(): + """ + Reads the wafers matrix code and decodes it to a string. Requires IDTools + license. + API Status: published + Returns: + MatrixCodeString:str + Command Timeout: 60000 + Example:Read2DMatrixCode + """ + rsp = MessageServerInterface.sendSciCommand("Read2DMatrixCode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetSpectrumRemote(Activate:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Activates the Spectrum remote mode. In this mode all user interface elements are + hidden and disabled. This is used when Spectrum is hosted inside VeloxPro. + API Status: internal + Args: + Activate:int = 1 + Command Timeout: 10000 + Example:SetSpectrumRemote 1 + """ + MessageServerInterface.sendSciCommand("SetSpectrumRemote",Activate) + + +def GetCameraLight(Name:str=""): + """ + Returns light properties of choosen camera. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + State:int + Shutter:Decimal + Gain:Decimal + Brightness:int + Contrast:int + Sharpness:int + Illumination:int + Command Timeout: 6000 + Example:GetCameraLight Scope + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraLight",Name) + global GetCameraLight_Response + if not "GetCameraLight_Response" in globals(): GetCameraLight_Response = namedtuple("GetCameraLight_Response", "MountPosition,State,Shutter,Gain,Brightness,Contrast,Sharpness,Illumination") + return GetCameraLight_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7])) + +def GetCameraView(Name:str=""): + """ + Returns the present camera view state of a desired tool or active view. + API Status: published + Args: + Name:str = "" + Returns: + MountPosition:str + Zoom:int + LiveVideo:int + WindowState:int + Command Timeout: 6000 + Example:GetCameraView AlignWafer + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraView",Name) + global GetCameraView_Response + if not "GetCameraView_Response" in globals(): GetCameraView_Response = namedtuple("GetCameraView_Response", "MountPosition,Zoom,LiveVideo,WindowState") + return GetCameraView_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetPattern(ToolName:str="", ModelName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Transforms the specific controller of a demanded tool into a bitmap. This bitmap will + be stored in the same folder as the project file. The command was originally + required by ReAlignWizard and is currently no longer in use. + API Status: internal + Args: + ToolName:str = "" + ModelName:str = "" + Returns: + BitmapPath:str + Command Timeout: 30000 + Example:GetPattern AlignWafer Model1 + """ + rsp = MessageServerInterface.sendSciCommand("GetPattern",ToolName,ModelName) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ShowPosition(MountPosition:str="", DistPositionX:Decimal="", DistPositionY:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the ChuckCenter under a given camera. When no camera mount position is + given, Spectrum uses active view. If there is an Offset different from zero, + this position will be moved under the camera. + API Status: internal + Args: + MountPosition:str = "" + DistPositionX:Decimal = 0 + DistPositionY:Decimal = 0 + Command Timeout: 60000 + Example:ShowPosition Scope + """ + MessageServerInterface.sendSciCommand("ShowPosition",MountPosition,DistPositionX,DistPositionY) + + +def GetCameraHomePosition(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the home die coordinates when the home die is under the alignment camera + (for instance, the top camera). Command was used during TrainReAlign to get + the start position for Z-Profiling. Command is no longer used. + API Status: internal + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 6000 + Example:GetCameraHomePosition + """ + rsp = MessageServerInterface.sendSciCommand("GetCameraHomePosition") + global GetCameraHomePosition_Response + if not "GetCameraHomePosition_Response" in globals(): GetCameraHomePosition_Response = namedtuple("GetCameraHomePosition_Response", "XPosition,YPosition,ZPosition") + return GetCameraHomePosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SynchronizeCamera(MountPos:str="", SynchronizeXY:int="", SynchronizeZ:int=""): + """ + Synchronizes the Platen camera with the calibration mark. The mark is mounted on + the chuck camera. The chuck must be moved to get the mark in view of the + specified camera. + API Status: published + Args: + MountPos:str = "Scope" + SynchronizeXY:int = 0 + SynchronizeZ:int = 0 + Returns: + XPosition:Decimal + YPosition:Decimal + ZPosition:Decimal + Command Timeout: 120000 + Example:SynchronizeCamera S 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SynchronizeCamera",MountPos,SynchronizeXY,SynchronizeZ) + global SynchronizeCamera_Response + if not "SynchronizeCamera_Response" in globals(): SynchronizeCamera_Response = namedtuple("SynchronizeCamera_Response", "XPosition,YPosition,ZPosition") + return SynchronizeCamera_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def ProbeCardOCS(UpdateZ:int="", MeasureBothGroups:int=""): + """ + Determines the chuck XYZ axis position where the needles of the probe card are + in focus. The output parameter is the Z axis value in microns from zero of the + new focus height. + API Status: published + Args: + UpdateZ:int = 1 + MeasureBothGroups:int = 1 + Returns: + ZPosition:Decimal + Command Timeout: 360000 + Example:ProbeCardOCS 1 + """ + rsp = MessageServerInterface.sendSciCommand("ProbeCardOCS",UpdateZ,MeasureBothGroups) + return Decimal(rsp[0]) + +def MoveChuckAutoXY(XPosition:Decimal="", YPosition:Decimal="", XSubsiteOffset:Decimal="", YSubsiteOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is sent by WaferMap to trigger AutoXY, AutoZ or VueTrack for each die + move. Automation must be activated/trained before command can be used. Response + is X, Y relative distance of adjustment from requested position. + API Status: internal + Args: + XPosition:Decimal = 0 + YPosition:Decimal = 0 + XSubsiteOffset:Decimal = 0 + YSubsiteOffset:Decimal = 0 + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:MoveChuckAutoXY 5000 10000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveChuckAutoXY",XPosition,YPosition,XSubsiteOffset,YSubsiteOffset) + global MoveChuckAutoXY_Response + if not "MoveChuckAutoXY_Response" in globals(): MoveChuckAutoXY_Response = namedtuple("MoveChuckAutoXY_Response", "XOffset,YOffset") + return MoveChuckAutoXY_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def VueTrackAlign(FullVueTrackAlign:int=""): + """ + Alignment for the next wafer when using VueTrack. + API Status: published + Args: + FullVueTrackAlign:int = 1 + Command Timeout: 6000000 + Example:VueTrackAlign + """ + MessageServerInterface.sendSciCommand("VueTrackAlign",FullVueTrackAlign) + + +def AutoFocusEVue(DistBelow:Decimal="", DistAbove:Decimal="", XOffsetCenter:int="", YOffsetCenter:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command is only used internally for software testing and for providing backwards + compatibility with SCPI legacy commands. It executes a focus search using the + eVue focus drive. + API Status: internal + Args: + DistBelow:Decimal = 0 + DistAbove:Decimal = 0 + XOffsetCenter:int = 0 + YOffsetCenter:int = 0 + Returns: + FocusScore:Decimal + ZPosition:Decimal + Command Timeout: 30000 + Example:AutoFocusEVue 200 200 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("AutoFocusEVue",DistBelow,DistAbove,XOffsetCenter,YOffsetCenter) + global AutoFocusEVue_Response + if not "AutoFocusEVue_Response" in globals(): AutoFocusEVue_Response = namedtuple("AutoFocusEVue_Response", "FocusScore,ZPosition") + return AutoFocusEVue_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def AutoAlignOffAxis(SetValue:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes the ReAlign Wafer Alignment tool to do a theta alignment of the wafer + with optional index calculation or thermal expansion measurement. AutoAlign is + performed using the Platen camera. Only supported for systems with off-axis + camera. + API Status: internal + Args: + SetValue:int = 0 + Command Timeout: 300000 + Example:AutoAlignOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AutoAlignOffAxis",SetValue) + + +def FindFocusOffAxis(StepCount:int="", Range:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Focus search is performed using the Platen camera. Only supported for + systems with off-axis camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusOffAxis 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusOffAxis",StepCount,Range) + global FindFocusOffAxis_Response + if not "FindFocusOffAxis_Response" in globals(): FindFocusOffAxis_Response = namedtuple("FindFocusOffAxis_Response", "ZPosition,Stage") + return FindFocusOffAxis_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignAuxOffAxis(AuxSiteID:int=""): + """ + Performs an automated aux site alignment in XYZ using the Off Axis camera. Tool + can correct reference position and contact height for the given aux site. + API Status: published + Args: + AuxSiteID:int = 0 + Command Timeout: 300000 + Example:AlignAuxOffAxis 1 + """ + MessageServerInterface.sendSciCommand("AlignAuxOffAxis",AuxSiteID) + + +def FindFocusPlaten(StepCount:int="", Range:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Determines the Z axis position where an object in the region of interest is in + focus. First output parameter is the Z axis value in microns from zero of the + new focus height. Second output parameter is the used stage to perform focus + search. Uses the FindFocus tool settings but always the Platen camera - + independent of the FindFocus mount. This command is used on e.g. BlueRay systems + that have a platen camera but can't use ReAlign/DetectWaferHeight as they don't + have an upward looking camera. + API Status: internal + Args: + StepCount:int = -1 + Range:Decimal = -1 + Returns: + ZPosition:Decimal + Stage:str + Command Timeout: 120000 + Example:FindFocusPlaten 50 500 + """ + rsp = MessageServerInterface.sendSciCommand("FindFocusPlaten",StepCount,Range) + global FindFocusPlaten_Response + if not "FindFocusPlaten_Response" in globals(): FindFocusPlaten_Response = namedtuple("FindFocusPlaten_Response", "ZPosition,Stage") + return FindFocusPlaten_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AlignChipOffAxis(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a single or two point alignment and moves the current chip to the + trained aligned position in Theta (in degrees) and X, Y (in microns). This + command is using the off axis platen camera with functionality of ReAlign. + API Status: internal + Returns: + ThetaOffset:Decimal + XOffset:Decimal + YOffset:Decimal + Command Timeout: 180000 + Example:AlignChipOffAxis + """ + rsp = MessageServerInterface.sendSciCommand("AlignChipOffAxis") + global AlignChipOffAxis_Response + if not "AlignChipOffAxis_Response" in globals(): AlignChipOffAxis_Response = namedtuple("AlignChipOffAxis_Response", "ThetaOffset,XOffset,YOffset") + return AlignChipOffAxis_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SelectAZoomLens(Lens:int=""): + """ + Selects 1 of 4 symbolic lenses (4 classified coarse ranges). + API Status: published + Args: + Lens:int = 1 + Command Timeout: 10000 + Example:SelectAZoomLens 1 + """ + MessageServerInterface.sendSciCommand("SelectAZoomLens",Lens) + + +def GetAZoomLens(): + """ + Returns 1 of 4 symbolic lenses, coarse ranges. + API Status: published + Returns: + Lens:int + Command Timeout: 5000 + Example:GetAZoomLens + """ + rsp = MessageServerInterface.sendSciCommand("GetAZoomLens") + return int(rsp[0]) + +def AZoomSetupDialog(): + """ + Opens the operator panel. In this window you can change the settings for all + defined lenses. + API Status: published + Command Timeout: 5000 + Example:AZoomSetupDialog + """ + MessageServerInterface.sendSciCommand("AZoomSetupDialog") + + +def MoveAZoomFocus(Focus:int="", Ref:str=""): + """ + Changes the focus magnitude. + API Status: published + Args: + Focus:int = 100 + Ref:str = "R" + Returns: + RetFocus:int + Command Timeout: 10000 + Example:MoveAZoomFocus 100 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomFocus",Focus,Ref) + return int(rsp[0]) + +def ReadAZoomFocus(): + """ + Returns the focus magnitude. + API Status: published + Returns: + Focus:int + Command Timeout: 5000 + Example:ReadAZoomFocus + """ + rsp = MessageServerInterface.sendSciCommand("ReadAZoomFocus") + return int(rsp[0]) + +def MoveAZoomVelocity(Direction:str="", Velocity:int=""): + """ + Moves the A-Zoom using the set focus speed. + API Status: published + Args: + Direction:str = "" + Velocity:int = 100 + Returns: + RetVelocity:Decimal + Command Timeout: 240000 + Example:MoveAZoomVelocity + 67 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAZoomVelocity",Direction,Velocity) + return Decimal(rsp[0]) + +def StopAZoom(): + """ + Stops the A-Zoom movements. + API Status: published + Command Timeout: 5000 + Example:StopAZoom + """ + MessageServerInterface.sendSciCommand("StopAZoom") + + +def SetAZoomLight(Light:int=""): + """ + Switches all lights ON or OFF. ON means the values defined by the current lens. + 1 switches the light on, 0 switches the light off. Without parameter toggles + between on an off. + API Status: published + Args: + Light:int = 0 + Command Timeout: 5000 + Example:SetAZoomLight 1 + """ + MessageServerInterface.sendSciCommand("SetAZoomLight",Light) + + +def CloseAZoom(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the OpticalControl application. Used during Project File handling. + API Status: internal + Command Timeout: 5000 + Example:CloseAZoom + """ + MessageServerInterface.sendSciCommand("CloseAZoom") + + +def OCLightVal(Value:int="", Channel:int="", Segment:int=""): + """ + Set the brightness of given channel and segment to the given value. + API Status: published + Args: + Value:int = 0 + Channel:int = 1 + Segment:int = 1 + Command Timeout: 5000 + Example:OCLightVal 128 1 4 + """ + MessageServerInterface.sendSciCommand("OCLightVal",Value,Channel,Segment) + + +def OCLightOn(On:int="", Channel:int=""): + """ + Switch the light (if it has segments then all) in a given channel ON or OFF. + Switch ON - that means: light to the before adjusted brightness. + API Status: published + Args: + On:int = 0 + Channel:int = 1 + Command Timeout: 5000 + Example:OCLightOn 1 1 + """ + MessageServerInterface.sendSciCommand("OCLightOn",On,Channel) + + +def OCSetZoomLevel(Zoom:int="", Motor:int=""): + """ + Set logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Zoom:int = 0 + Motor:int = 1 + Command Timeout: 5000 + Example:OCSetZoomLevel 50 1 + """ + MessageServerInterface.sendSciCommand("OCSetZoomLevel",Zoom,Motor) + + +def OCGetZoomLevel(Motor:int=""): + """ + Get logical zoom factor for given motor (if has more then one, else to the one) + API Status: published + Args: + Motor:int = 1 + Returns: + Zoom:int + Command Timeout: 5000 + Example:OCGetZoomLevel 1 + """ + rsp = MessageServerInterface.sendSciCommand("OCGetZoomLevel",Motor) + return int(rsp[0]) + +def StartReAlignTemperature(TargetTemperature:Decimal="", ThetaAlignOnFinish:int="", ContactOnFinish:int=""): + """ + Starts temperature ramping using ReAlign. ReAlign will re-adjust the probes and + wafer during ramping to the new target temperature. Command returns immediately. + The status of temperature ramping must be checked using the + GetReAlignTemperatureStatus command. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + Command Timeout: 5000 + Example:StartReAlignTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartReAlignTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish) + + +def StopReAlignTemperature(): + """ + Stops temperature ramping using ReAlign. + API Status: published + Command Timeout: 10000 + Example:StopReAlignTemperature + """ + MessageServerInterface.sendSciCommand("StopReAlignTemperature") + + +def GetReAlignTemperatureStatus(): + """ + Returns the status of the current temperature ramping using ReAlign process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetReAlignTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignTemperatureStatus") + global GetReAlignTemperatureStatus_Response + if not "GetReAlignTemperatureStatus_Response" in globals(): GetReAlignTemperatureStatus_Response = namedtuple("GetReAlignTemperatureStatus_Response", "StatusId,StatusStr") + return GetReAlignTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ReAlign(Repeats:int="", Mode:str="", AlignProbeCard:int="", CorrectZ:int=""): + """ + Performs an automatic realignment of the wafer. This includes measuring the + needle drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck + drift XYZ and optionally a Z-Profile. Alternatively the tool performs a + ProbeToDie Alignment to correct the needle position for the current die. Command + returns once ReAlign is finished or aborted because of an error. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Returns: + XOffsetWafer:Decimal + YOffsetWafer:Decimal + ZOffsetWafer:Decimal + XOffsetCard:Decimal + YOffsetCard:Decimal + ZOffsetCard:Decimal + Command Timeout: 1000000 + Example:ReAlign 2 H 0 0 + """ + rsp = MessageServerInterface.sendSciCommand("ReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + global ReAlign_Response + if not "ReAlign_Response" in globals(): ReAlign_Response = namedtuple("ReAlign_Response", "XOffsetWafer,YOffsetWafer,ZOffsetWafer,XOffsetCard,YOffsetCard,ZOffsetCard") + return ReAlign_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def NextWafer(): + """ + Starts the NextWafer routine. + API Status: published + Returns: + Canceled:int + Command Timeout: 60000000 + Example:NextWafer + """ + rsp = MessageServerInterface.sendSciCommand("NextWafer") + return int(rsp[0]) + +def StartReAlign(Repeats:int="", Mode:str="", AlignProbeCard:int="", CorrectZ:int=""): + """ + Starts an automatic realignment of the wafer. This includes measuring the needle + drift XYZ, aligning the wafer, measuring chuck expansion, measuring chuck drift + XYZ and optionally a Z-Profile. Alternatively the tool performs a ProbeToPad + Alignment to correct the needle position for the current die. Command returns + immediately. The status of the asynchronous ReAlign execution must be checked + using the GetReAlignStatus command. + API Status: published + Args: + Repeats:int = 1 + Mode:str = "H" + AlignProbeCard:int = 2 + CorrectZ:int = 2 + Command Timeout: 60000 + Example:StartReAlign 2 H 0 0 + """ + MessageServerInterface.sendSciCommand("StartReAlign",Repeats,Mode,AlignProbeCard,CorrectZ) + + +def StopReAlign(): + """ + Stops the ReAlign procedure. + API Status: published + Command Timeout: 120000 + Example:StopReAlign + """ + MessageServerInterface.sendSciCommand("StopReAlign") + + +def GetReAlignStatus(): + """ + Returns a status of the ReAlign procedure. If the return value is true, ReAlign + is running. + API Status: published + Returns: + Running:int + Command Timeout: 60000 + Example:GetReAlignStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetReAlignStatus") + return int(rsp[0]) + +def EnableOverlay(Overlay:int=""): + """ + Allows activating the overlay of the needles for the top camera. + API Status: published + Args: + Overlay:int = 0 + Command Timeout: 6000 + Example:EnableOverlay 0 + """ + MessageServerInterface.sendSciCommand("EnableOverlay",Overlay) + + +def SwitchOffset(Offset:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Switches the offset compensation. Applicable for MicroAlign stations only. + API Status: internal + Args: + Offset:int = 0 + Command Timeout: 60000 + Example:SwitchOffset 1 + """ + MessageServerInterface.sendSciCommand("SwitchOffset",Offset) + + +def TrainFeature(Model:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command was only implemented for supporting a SCPI legacy command. Does not make + sense in Velox, as there is no default training rectangle on the screen as in + Nucleus. + API Status: internal + Args: + Model:int = 1 + Returns: + Data:str + Command Timeout: 30000 + Example:TrainFeature 1 + """ + rsp = MessageServerInterface.sendSciCommand("TrainFeature",Model) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetEvueExposureLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Returns: + Exposure:Decimal + Command Timeout: 10000 + Example:GetEvueExposureLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueExposureLevel") + return Decimal(rsp[0]) + +def SetEvueExposureLevel(Exposure:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the exposure value of the eVue. Implemented for supporting SCPI legacy + command. + API Status: internal + Args: + Exposure:Decimal = 0 + Command Timeout: 10000 + Example:SetEvueExposureLevel + """ + MessageServerInterface.sendSciCommand("SetEvueExposureLevel",Exposure) + + +def MoveEvueFocusStage(EvueZ:Decimal="", EvueVelocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the eVue focus stage to a specified position. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + EvueZ:Decimal = 0 + EvueVelocity:Decimal = 100 + Command Timeout: 30000 + Example:MoveEvueFocusStage 1000 + """ + MessageServerInterface.sendSciCommand("MoveEvueFocusStage",EvueZ,EvueVelocity) + + +def GetEvueFocusStagePos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the eVue focus stage. Implemented for supporting + SCPI legacy command. + API Status: internal + Returns: + EvueZ:Decimal + Command Timeout: 5000 + Example:GetEvueFocusStagePos + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueFocusStagePos") + return Decimal(rsp[0]) + +def RunEvueAutoExpose(UseCB:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command runs the AutoExpose function for the eVue. Implemented for supporting + SCPI legacy command. + API Status: internal + Args: + UseCB:int = 1 + Command Timeout: 20000 + Example:RunEvueAutoExpose 1 + """ + MessageServerInterface.sendSciCommand("RunEvueAutoExpose",UseCB) + + +def GetEvueZoomLevel(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope that is connected to Velox. On eVue + systems, this command, returns values ranging from 0.5 to 5.0 for a 10x system + and 0.5 to 20.0 for a 40x system. + API Status: internal + Returns: + Zoom:Decimal + Command Timeout: 5000 + Example:GetEvueZoomLevel + """ + rsp = MessageServerInterface.sendSciCommand("GetEvueZoomLevel") + return Decimal(rsp[0]) + +def SetEvueZoomLevel(Zoom:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Valid only with the eVue microscope or an A-Zoom microscope that is connected to + Velox. On eVue systems, this command sets the proper CCD zoom level to the + appropriate optical path. + API Status: internal + Args: + Zoom:Decimal = 0 + Command Timeout: 5000 + Example:SetEvueZoomLevel 2.0 + """ + MessageServerInterface.sendSciCommand("SetEvueZoomLevel",Zoom) + + +def StartAutomationTemperature(TargetTemperature:Decimal="", ThetaAlignOnFinish:int="", ContactOnFinish:int="", AlignOnFinish:int=""): + """ + Starts temperature ramping using Automation. The Automation (mostly VueTrack) + will re-adjust the probes and wafer during ramping to the new target + temperature. + API Status: published + Args: + TargetTemperature:Decimal = 0 + ThetaAlignOnFinish:int = 0 + ContactOnFinish:int = 0 + AlignOnFinish:int = 1 + Command Timeout: 5000 + Example:StartAutomationTemperature 150 + """ + MessageServerInterface.sendSciCommand("StartAutomationTemperature",TargetTemperature,ThetaAlignOnFinish,ContactOnFinish,AlignOnFinish) + + +def StopAutomationTemperature(): + """ + Stops temperature ramping using Automation. + API Status: published + Command Timeout: 10000 + Example:StopAutomationTemperature + """ + MessageServerInterface.sendSciCommand("StopAutomationTemperature") + + +def GetAutomationTemperatureStatus(): + """ + Returns the status of the current temperature ramping using automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 300000 + Example:GetAutomationTemperatureStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationTemperatureStatus") + global GetAutomationTemperatureStatus_Response + if not "GetAutomationTemperatureStatus_Response" in globals(): GetAutomationTemperatureStatus_Response = namedtuple("GetAutomationTemperatureStatus_Response", "StatusId,StatusStr") + return GetAutomationTemperatureStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationActive(): + """ + Command to read from Spectrum if Automation (AutoXY, AutoZ or VueTrack) is + active. Command is used by WaferMap to read if it must send MoveChuckAutoXY + instead of MoveChuck + API Status: published + Returns: + Active:int + Command Timeout: 1000 + Example:GetAutomationActive + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationActive") + return int(rsp[0]) + +def AutomationNeedleSearch(NeedleIndex:int="", MoveScope:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + VueTrack vision search of the given needle index. + API Status: internal + Args: + NeedleIndex:int = 1 + MoveScope:int = 1 + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + ZMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationNeedleSearch 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("AutomationNeedleSearch",NeedleIndex,MoveScope) + global AutomationNeedleSearch_Response + if not "AutomationNeedleSearch_Response" in globals(): AutomationNeedleSearch_Response = namedtuple("AutomationNeedleSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore,ZMatchScore") + return AutomationNeedleSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def AutomationReferenceSearch(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + AutomationReferenceSearch exposes the functionality of searching the Automation + reference target via remote command + API Status: internal + Returns: + XOffset:Decimal + YOffset:Decimal + ZOffset:Decimal + XYMatchScore:Decimal + Command Timeout: 60000 + Example:AutomationReferenceSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationReferenceSearch") + global AutomationReferenceSearch_Response + if not "AutomationReferenceSearch_Response" in globals(): AutomationReferenceSearch_Response = namedtuple("AutomationReferenceSearch_Response", "XOffset,YOffset,ZOffset,XYMatchScore") + return AutomationReferenceSearch_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def MovePositionersSafe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the configured motorized positioners to a safe position + API Status: internal + Command Timeout: 60000 + Example:MovePositionersSafe + """ + MessageServerInterface.sendSciCommand("MovePositionersSafe") + + +def SetConstantContactMode(IsOn:int="", ForceLastCorrection:int=""): + """ + Starts Constant Contact mode using Automation. The Automation will re-adjust the + wafer during ramping to the new target temperature. + API Status: published + Args: + IsOn:int = 0 + ForceLastCorrection:int = 0 + Command Timeout: 5000 + Example:SetConstantContactMode 1 + """ + MessageServerInterface.sendSciCommand("SetConstantContactMode",IsOn,ForceLastCorrection) + + +def GetConstantContactModeStatus(): + """ + Returns the status of the current ConstantContact automation process. + API Status: published + Returns: + StatusId:int + StatusStr:str + Command Timeout: 5000 + Example:GetConstantContactModeStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetConstantContactModeStatus") + global GetConstantContactModeStatus_Response + if not "GetConstantContactModeStatus_Response" in globals(): GetConstantContactModeStatus_Response = namedtuple("GetConstantContactModeStatus_Response", "StatusId,StatusStr") + return GetConstantContactModeStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetAutomationActive(Activate:int=""): + """ + Command to set if Automation (AutoXY, AutoZ or VueTrack) is active. Command can + be used to e.g. deactivate automation programmatically in case it is no + longer used. When activating automation, the command will return an error in + case it is not possible (e.g. not trained) + API Status: published + Args: + Activate:int = 0 + Command Timeout: 1000 + Example:SetAutomationActive 1 + """ + MessageServerInterface.sendSciCommand("SetAutomationActive",Activate) + + +def AutomationSearchCurrentDie(): + """ + Performs an Automation search and position correction using the current chuck + position. Response is X, Y relative distance of adjustment. + API Status: published + Returns: + XOffset:Decimal + YOffset:Decimal + Command Timeout: 6000000 + Example:AutomationSearchCurrentDie + """ + rsp = MessageServerInterface.sendSciCommand("AutomationSearchCurrentDie") + global AutomationSearchCurrentDie_Response + if not "AutomationSearchCurrentDie_Response" in globals(): AutomationSearchCurrentDie_Response = namedtuple("AutomationSearchCurrentDie_Response", "XOffset,YOffset") + return AutomationSearchCurrentDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def PreMapWafer(): + """ + PreMapWafer finds actual singulated die locations and updates positions used by + WaferMap. + API Status: published + Returns: + NumberOfDies:int + Command Timeout: 14400000 + Example:PreMapWafer + """ + rsp = MessageServerInterface.sendSciCommand("PreMapWafer") + return int(rsp[0]) + +def ISSProbeAlign(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs an probe to pad operation on the ISS with two RF positioners. + API Status: internal + Command Timeout: 6000000 + Example:ISSProbeAlign + """ + MessageServerInterface.sendSciCommand("ISSProbeAlign") + + +def FindWaferCenter(NoManualRecovery:int=""): + """ + FindWaferCenter finds the center of the wafer using edge detection. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:FindWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("FindWaferCenter",NoManualRecovery) + global FindWaferCenter_Response + if not "FindWaferCenter_Response" in globals(): FindWaferCenter_Response = namedtuple("FindWaferCenter_Response", "ChuckX,ChuckY") + return FindWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def LocateHomeDie(NoManualRecovery:int=""): + """ + LocateHomeDie finds the center of the wafer using edge detection and sets the + home position. + API Status: published + Args: + NoManualRecovery:int = 0 + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 300000 + Example:LocateHomeDie + """ + rsp = MessageServerInterface.sendSciCommand("LocateHomeDie",NoManualRecovery) + global LocateHomeDie_Response + if not "LocateHomeDie_Response" in globals(): LocateHomeDie_Response = namedtuple("LocateHomeDie_Response", "ChuckX,ChuckY") + return LocateHomeDie_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def SetAutomationProbeLayout(LayoutName:str="", ProbeID:int="", XOffset:Decimal="", YOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stores the provided X or Y offset for the given probe for the specified layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Command Timeout: 10000 + Example:SetAutomationProbeLayout "layout1" 1 100.0 0 + """ + MessageServerInterface.sendSciCommand("SetAutomationProbeLayout",LayoutName,ProbeID,XOffset,YOffset) + + +def DeleteAutomationProbeLayout(LayoutName:str="", ProbeID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Delete the specfied layout. If LayoutName is empty then all layouts are deleted. + If optional ProbeID parmameter is set, it removes just that probe from the + layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 10000 + Example:DeleteAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("DeleteAutomationProbeLayout",LayoutName,ProbeID) + + +def CaptureAutomationProbeLayout(LayoutName:str="", ProbeID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Capture the specfied layout. If optional ProbeID parmameter is set, it captures + just that probe from the layout. + API Status: internal + Args: + LayoutName:str = "" + ProbeID:int = 0 + Command Timeout: 30000 + Example:CaptureAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("CaptureAutomationProbeLayout",LayoutName,ProbeID) + + +def MoveToAutomationProbeLayout(LayoutName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move to the probes to specfied layout which are offsets from the trained + positions. + API Status: internal + Args: + LayoutName:str = "" + Command Timeout: 300000 + Example:MoveToAutomationProbeLayout "layout1" + """ + MessageServerInterface.sendSciCommand("MoveToAutomationProbeLayout",LayoutName) + + +def ResetAutomation(): + """ + Reset automation data back to trained values. + API Status: published + Command Timeout: 10000 + Example:ResetAutomation + """ + MessageServerInterface.sendSciCommand("ResetAutomation") + + +def GetWaferCenter(): + """ + GetWaferCenter returns the chuck location (zero based) of the wafer center. It + returns 0 0 if FindWaferCenter has not been executed for the current wafer. + API Status: published + Returns: + ChuckX:Decimal + ChuckY:Decimal + Command Timeout: 10000 + Example:GetWaferCenter + """ + rsp = MessageServerInterface.sendSciCommand("GetWaferCenter") + global GetWaferCenter_Response + if not "GetWaferCenter_Response" in globals(): GetWaferCenter_Response = namedtuple("GetWaferCenter_Response", "ChuckX,ChuckY") + return GetWaferCenter_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def InitEvueFocusStage(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initializes the eVue focus stage by finding the limit switches + API Status: internal + Command Timeout: 30000 + Example:InitEvueFocusStage + """ + MessageServerInterface.sendSciCommand("InitEvueFocusStage") + + +def EvueSetNumTraceEntriesPreTrigger(NumTraceEntriesPreTrigger:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Args: + NumTraceEntriesPreTrigger:int = 0 + Command Timeout: 30000 + Example:EvueSetNumTraceEntriesPreTrigger 14 + """ + MessageServerInterface.sendSciCommand("EvueSetNumTraceEntriesPreTrigger",NumTraceEntriesPreTrigger) + + +def EvueGetNumTraceEntriesPreTrigger(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the number of trace log items to preserve prior to the trigger event. With + the continuous event capture log in Bluestone, up to {X} events are captured and + kept after the trigger event is sensed. Then, events are captured after the + trigger event until the trace log is full and then trace capture is halted. + API Status: internal + Returns: + NumTraceEntriesPreTrigger:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntriesPreTrigger + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntriesPreTrigger") + return int(rsp[0]) + +def EvueStartCaptureServoTrace(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts capturing events in the eVue motion capture log. Capture continues until + the log is full. However, log entries will overwrite the oldest entry until the + trigger event is encountered. Then, {X} events are preserved prior to the + trigger event and the oldest events are only overwritten if they are not part of + that preserved set. + API Status: internal + Command Timeout: 30000 + Example:EvueStartCaptureServoTrace + """ + MessageServerInterface.sendSciCommand("EvueStartCaptureServoTrace") + + +def EvueGetTraceMachineStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the current status of the trace machine. Bit fields - bit0 is 1 and bit4 is + 16, etc. bit0 - active and in pre-trigger state bit1 - active and in post- + trigger state bit2 - stopped by servo error, lens crash or lens removal bit3 - + stopped on requested server state entry bit4 - stopped by immediate command + bit5..31 - reserved + API Status: internal + Returns: + TraceMachineStatus:int + Command Timeout: 30000 + Example:EvueGetTraceMachineStatus + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceMachineStatus") + return int(rsp[0]) + +def EvueSetTraceCaptureStopBits(TraceCaptureStopBits:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets condition bits to trigger servo trace capture. Bit fields - bit0 is 1 and + bit4 is 16, etc. bit0 - immediate stop bit1 - stop on servo error, lens crash or + lens removal bit2 - stop on requested server state (defined by bits 4..7) bit3 - + stop on motor move finish bit4..7 - servo state that triggers a trace stop (not + an index but the 4-bit state that, if seen, is the trigger for trace capture) + bit8..31 - reserved + API Status: internal + Args: + TraceCaptureStopBits:int = 0 + Command Timeout: 30000 + Example:EvueSetTraceCaptureStopBits + """ + MessageServerInterface.sendSciCommand("EvueSetTraceCaptureStopBits",TraceCaptureStopBits) + + +def EvueGetNumTraceEntries(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the current status of the trace machine. + API Status: internal + Returns: + TraceEntries:int + Command Timeout: 30000 + Example:EvueGetNumTraceEntries + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetNumTraceEntries") + return int(rsp[0]) + +def EvueGetTraceEntry(EntryIdx:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the N'th trace entry in the log. + API Status: internal + Args: + EntryIdx:int = 0 + Returns: + CommandedPositionMotorCounts:int + CommandedPositionMicrons:Decimal + MeasuredPositionMotorCounts:int + MeasuredPositionMicrons:Decimal + TimestampMicroseconds:int + ServoStatus:int + PwmVal:int + Command Timeout: 30000 + Example:EvueGetTraceEntry 32 + """ + rsp = MessageServerInterface.sendSciCommand("EvueGetTraceEntry",EntryIdx) + global EvueGetTraceEntry_Response + if not "EvueGetTraceEntry_Response" in globals(): EvueGetTraceEntry_Response = namedtuple("EvueGetTraceEntry_Response", "CommandedPositionMotorCounts,CommandedPositionMicrons,MeasuredPositionMotorCounts,MeasuredPositionMicrons,TimestampMicroseconds,ServoStatus,PwmVal") + return EvueGetTraceEntry_Response(int(rsp[0]),Decimal(rsp[1]),int(rsp[2]),Decimal(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6])) + +def AutomationRFProbeSearch(ImageFilename:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the distance in X,Y between the center tips of the RF probes. + API Status: internal + Args: + ImageFilename:str = "" + Returns: + X:Decimal + Y:Decimal + Command Timeout: 5000 + Example:AutomationRFProbeSearch + """ + rsp = MessageServerInterface.sendSciCommand("AutomationRFProbeSearch",ImageFilename) + global AutomationRFProbeSearch_Response + if not "AutomationRFProbeSearch_Response" in globals(): AutomationRFProbeSearch_Response = namedtuple("AutomationRFProbeSearch_Response", "X,Y") + return AutomationRFProbeSearch_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def StartAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the AutoRF calibration sequence. + API Status: internal + Command Timeout: 3000 + Example:StartAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StartAutoRFCalibration") + + +def StopAutoRFCalibration(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the currently running AutoRF calibraiton. + API Status: internal + Command Timeout: 10000 + Example:StopAutoRFCalibration + """ + MessageServerInterface.sendSciCommand("StopAutoRFCalibration") + + +def GetAutoRFCalibrationStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the status of the AutoRF calibration sequence. + API Status: internal + Returns: + StatusId:int + StatusStr:str + Command Timeout: 1000 + Example:GetAutoRFCalibrationStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetAutoRFCalibrationStatus") + global GetAutoRFCalibrationStatus_Response + if not "GetAutoRFCalibrationStatus_Response" in globals(): GetAutoRFCalibrationStatus_Response = namedtuple("GetAutoRFCalibrationStatus_Response", "StatusId,StatusStr") + return GetAutoRFCalibrationStatus_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetAutomationLastStepDiagnostics(Index:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the diagnostic state information for the provided index. + API Status: internal + Args: + Index:int = 0 + Returns: + DiagnosticInfo:str + Command Timeout: 5000 + Example:GetAutomationLastStepDiagnostics + """ + rsp = MessageServerInterface.sendSciCommand("GetAutomationLastStepDiagnostics",Index) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMNanoChamberState(State:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the WLEM Nano Chamber State. + API Status: internal + Args: + State:str = "Free" + Command Timeout: 5000 + Example:SetWLEMNanoChamberState Free + """ + MessageServerInterface.sendSciCommand("SetWLEMNanoChamberState",State) + + +def GetWLEMNanoChamberState(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the WLEM Nano Chamber State. + API Status: internal + Returns: + State:str + Command Timeout: 5000 + Example:GetWLEMNanoChamberState + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMNanoChamberState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetWLEMState(State:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMState NCSeal 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMState",State,Value) + + +def GetWLEMState(State:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the state of a WLEM pneumatic control (valve). + API Status: internal + Args: + State:str = "NCSeal" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMState NCSeal + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMState",State) + return int(rsp[0]) + +def GetWLEMSensorValue(Sensor:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets the value of a WLEM Sensor. + API Status: internal + Args: + Sensor:str = "O2Concentration" + Returns: + Value:Decimal + Command Timeout: 5000 + Example:GetWLEMSensorValue O2Concentration + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMSensorValue",Sensor) + return Decimal(rsp[0]) + +def SetWLEMOption(Option:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Value:int = 0 + Command Timeout: 5000 + Example:SetWLEMOption MinimizeToTray 1 + """ + MessageServerInterface.sendSciCommand("SetWLEMOption",Option,Value) + + +def GetWLEMOption(Option:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets a WLEM Control program option. + API Status: internal + Args: + Option:str = "MinimizeToTray" + Returns: + Value:int + Command Timeout: 5000 + Example:GetWLEMOption MinimizeToTray + """ + rsp = MessageServerInterface.sendSciCommand("GetWLEMOption",Option) + return int(rsp[0]) + +def NewTesterProject(LotID:str="", TileID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a new Lot/Tile is to be tested. The tester + responds with the correct project name for the test. This is needed because the + prober needs to verify that the correct project is loaded. In case no valid + project is available, the command is returned with an error. + API Status: internal + Args: + LotID:str = "" + TileID:str = "" + Returns: + ProjectName:str + Command Timeout: 30000 + Example:NewTesterProject Lot01 Tile01 + """ + rsp = MessageServerInterface.sendSciCommand("NewTesterProject",LotID,TileID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def StartMeasurement(DieColumn:int="", DieRow:int="", ActiveDies:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester to begin measuring (Needles are in correct + position and in contact). The command is responded when the measurement has + finished. The response string holds the binning information separated by comma. + For deactivated dies, a bin value of '0' should be responded. + API Status: internal + Args: + DieColumn:int = 0 + DieRow:int = 0 + ActiveDies:str = "" + Returns: + BinNumbers:str + Command Timeout: 100000 + Example:StartMeasurement 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("StartMeasurement",DieColumn,DieRow,ActiveDies) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def EndOfWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current substrate has + finished. It enables the tester application to save measurement data and/or + prepare for the next substrate. + API Status: internal + Command Timeout: 30000 + Example:EndOfWafer + """ + MessageServerInterface.sendSciCommand("EndOfWafer") + + +def EndOfLot(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command tells the tester, that the test of the current lot has finished. It + enables the tester application to save measurement data and/or prepare for the + next lot. + API Status: internal + Command Timeout: 30000 + Example:EndOfLot + """ + MessageServerInterface.sendSciCommand("EndOfLot") + + +def VerifyProductID(ProductID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProductID that is to be tested. The + tester can respond with an error in case the ProductID is not allowed for + testing. + API Status: internal + Args: + ProductID:str = "" + Command Timeout: 30000 + Example:VerifyProductID Product123 + """ + MessageServerInterface.sendSciCommand("VerifyProductID",ProductID) + + +def VerifyLotID(LotID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the LotID that is to be tested. The tester + can respond with an error in case the LotID is not allowed for testing. + API Status: internal + Args: + LotID:str = "" + Command Timeout: 30000 + Example:VerifyLotID Lot123 + """ + MessageServerInterface.sendSciCommand("VerifyLotID",LotID) + + +def VerifySubstrateID(SubstrateID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the SubstrateID that is to be tested. The + tester can respond with an error in case the SubstrateID is not allowed for + testing. + API Status: internal + Args: + SubstrateID:str = "" + Command Timeout: 30000 + Example:VerifySubstrateID Substrate123 + """ + MessageServerInterface.sendSciCommand("VerifySubstrateID",SubstrateID) + + +def VerifyProbecard(ProbeCard:str="", Touchdowns:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the ProbecardID and touchdowns that is + used for testing. The tester can respond with an error in case the Probecard is + not allowed for testing. + API Status: internal + Args: + ProbeCard:str = "" + Touchdowns:int = 0 + Command Timeout: 30000 + Example:VerifyProbecard Probecard123 10596 + """ + MessageServerInterface.sendSciCommand("VerifyProbecard",ProbeCard,Touchdowns) + + +def VerifyUserID(User:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester about the User ID. The tester can respond with + an error in case the User ID is not allowed for testing. + API Status: internal + Args: + User:str = "" + Command Timeout: 30000 + Example:VerifyUserID User123 + """ + MessageServerInterface.sendSciCommand("VerifyUserID",User) + + +def TesterAbort(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the job was aborted and no more test will + happen. + API Status: internal + Command Timeout: 30000 + Example:TesterAbort + """ + MessageServerInterface.sendSciCommand("TesterAbort") + + +def VerifySOTReady(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that a wafer is ready for testing which will + immediately start. This command is sent in the recipe sequence "Verify + SOTReady". + API Status: internal + Command Timeout: 30000 + Example:VerifySOTReady + """ + MessageServerInterface.sendSciCommand("VerifySOTReady") + + +def VerifyWaferStart(SubstrateID:str="", CassettePlace:str="", LotID:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent in the VeloxPro recipe sequence "Verify Wafer Start" and + informs the tester about the current wafer on the chuck. + API Status: internal + Args: + SubstrateID:str = "" + CassettePlace:str = "" + LotID:str = "" + Command Timeout: 30000 + Example:VerifyWaferStart Wafer01 1 Lot01 + """ + MessageServerInterface.sendSciCommand("VerifyWaferStart",SubstrateID,CassettePlace,LotID) + + +def TesterCassetteInfo(CassetteCmd:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command will be sent after the user selected which wafers are to be tested. + It contains a string which represents the state of each wafer: 0 = empty, 1 = + full (and selected), 2 = error (e.g. double slotted), 3 = unknown, 4 = + deselected + API Status: internal + Args: + CassetteCmd:str = "" + Returns: + CassetteRsp:str + Command Timeout: 30000 + Example:TesterCassetteInfo 0000001110000000010010111 + """ + rsp = MessageServerInterface.sendSciCommand("TesterCassetteInfo",CassetteCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def VerifyProject(ProjectName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is sent after selecting a project file in the VeloxPro product + setup page. The command sends the name of the project to tester for + verification. + API Status: internal + Args: + ProjectName:str = "" + Command Timeout: 30000 + Example:VerifyProject C:/Users/Public/Documents/Velox/Projects/Test.spp + """ + MessageServerInterface.sendSciCommand("VerifyProject",ProjectName) + + +def TesterAbortWafer(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command informs the tester that the test for the current wafer was aborted + and no more tests will happen with the current wafer. The job will continue + though. + API Status: internal + Command Timeout: 30000 + Example:TesterAbortWafer + """ + MessageServerInterface.sendSciCommand("TesterAbortWafer") + + +def DoTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts execution of one test. It returns a bin number or multple bin numbers + when clusters are enabled in the WaferMap (one number for each die in a + cluster). The command starts execution of one test. It returns a bin number or + multple bin numbers when clusters are enabled in the WaferMap (one number for + each die in a cluster). + API Status: internal + Returns: + BitNumber:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("DoTTLTest") + return int(rsp[0]) + +def StartTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Starts the test of a wafer. Depending on the cluster definitions queried from + the WaferMap, all clusters or all dies will be tested. The command starts the + test of a wafer. Depending on the cluster definitions queried from the WaferMap + all clusters or all dies will be tested. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("StartTTLTest") + + +def CancelTTLTest(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops the wafer test. + API Status: internal + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("CancelTTLTest") + + +def SetTTLLine(Line:int="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the selected line of PA port. + API Status: internal + Args: + Line:int = 0 + Value:int = 0 + Command Timeout: 10000 + Example:SetTTLLine 2 0 + """ + MessageServerInterface.sendSciCommand("SetTTLLine",Line,Value) + + +def GetTTLLines(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the I/O lines as bit array. + API Status: internal + Returns: + LineA:int + LineB:int + LineC:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLLines") + global GetTTLLines_Response + if not "GetTTLLines_Response" in globals(): GetTTLLines_Response = namedtuple("GetTTLLines_Response", "LineA,LineB,LineC") + return GetTTLLines_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def GetTTLStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns returns the error 914 if the test is in progress. + API Status: internal + Returns: + ErrCode:int + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTTLStatus") + return int(rsp[0]) + +def StartScript(ScriptName:str=""): + """ + Starts the script and returns the response immediately. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000 + Example:StartScript myscript + """ + MessageServerInterface.sendSciCommand("StartScript",ScriptName) + + +def GetRunStatus(ScriptName:str=""): + """ + Command returns information about Communicator status. + API Status: published + Args: + ScriptName:str = "" + Returns: + Running:int + LastError:int + Title:str + Command Timeout: 5000 + Example:GetRunStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetRunStatus",ScriptName) + global GetRunStatus_Response + if not "GetRunStatus_Response" in globals(): GetRunStatus_Response = namedtuple("GetRunStatus_Response", "Running,LastError,Title") + return GetRunStatus_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def CloseCommunicator(): + """ + Command closes the program. Used during ProjectFile handling. + API Status: published + Command Timeout: 10000 + Example:CloseCommunicator + """ + MessageServerInterface.sendSciCommand("CloseCommunicator") + + +def DoScript(ScriptName:str=""): + """ + Executes the script and returns the response afterwards. + API Status: published + Args: + ScriptName:str = "" + Command Timeout: 10000000 + Example:DoScript myscript + """ + MessageServerInterface.sendSciCommand("DoScript",ScriptName) + + +def ReadKernelData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Reads Kernel Data to KernelSetup (Left Program pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReadKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReadKernelData",SilentMode) + + +def SaveKernelDataAs(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves Kernel Data (Left Program pane) to File. An existing File will be + overwritten. If the Folder does not exist, it will be created + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveKernelDataAs C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("SaveKernelDataAs",FileName) + + +def LoadConfigFile(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Loads File Data to KernelSetup (Right Program pane). + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:LoadConfigFile C:/Temp/RCConfigSample1.xml + """ + MessageServerInterface.sendSciCommand("LoadConfigFile",FileName) + + +def ReplaceKernelDataByFileData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces Kernel Data (Left pane) by File Data (Right pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceKernelDataByFileData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceKernelDataByFileData",SilentMode) + + +def ReplaceFileTreeByKernelData(SilentMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Replaces File Tree (Right pane) by Kernel Data (Left pane). + API Status: internal + Args: + SilentMode:int = 0 + Command Timeout: 300000 + Example:ReplaceFileTreeByKernelData 0 + """ + MessageServerInterface.sendSciCommand("ReplaceFileTreeByKernelData",SilentMode) + + +def SaveFileTreeAs(FileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Saves File Tree (Right pane) to File. An existing File will be overwritten. If + the Folder does not exist, it will be created. + API Status: internal + Args: + FileName:str = "" + Command Timeout: 10000 + Example:SaveFileTreeAs C:/Temp/RCConfigSample2.xml + """ + MessageServerInterface.sendSciCommand("SaveFileTreeAs",FileName) + + +def HeatChuck(Temperature:Decimal="", Unit:str="", ReduceContact:int=""): + """ + Sets a new target temperature and starts the heating or cooling of the chuck. An + answer to the command will be returned after reaching the given temperature and + waiting the soak time or an unexpected interrupt of the process. Given back is + the already reached temperature. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + ReduceContact:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 36000000 + Example:HeatChuck 61.3 C + """ + rsp = MessageServerInterface.sendSciCommand("HeatChuck",Temperature,Unit,ReduceContact) + global HeatChuck_Response + if not "HeatChuck_Response" in globals(): HeatChuck_Response = namedtuple("HeatChuck_Response", "RespTemperature,RespUnit") + return HeatChuck_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetHeaterTemp(Temperature:Decimal="", Unit:str="", UseContactSafety:int=""): + """ + Sets a new target temperature and starts the heating or cooling of the + temperature chuck. The new target temperature is returned immediately as the + command does not wait until heating is complete. + API Status: published + Args: + Temperature:Decimal = 25 + Unit:str = "Celsius" + UseContactSafety:int = 1 + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:SetHeaterTemp 55.5 C + """ + rsp = MessageServerInterface.sendSciCommand("SetHeaterTemp",Temperature,Unit,UseContactSafety) + global SetHeaterTemp_Response + if not "SetHeaterTemp_Response" in globals(): SetHeaterTemp_Response = namedtuple("SetHeaterTemp_Response", "RespTemperature,RespUnit") + return SetHeaterTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetHeaterTemp(Unit:str="", ExternalHeaterID:int=""): + """ + Reads the current temperature of the chuck and determines the status of the + thermal system. + API Status: published + Args: + Unit:str = "Celsius" + ExternalHeaterID:int = 0 + Returns: + RespTemperature:Decimal + RespUnit:str + Status:str + Command Timeout: 60000 + Example:GetHeaterTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterTemp",Unit,ExternalHeaterID) + global GetHeaterTemp_Response + if not "GetHeaterTemp_Response" in globals(): GetHeaterTemp_Response = namedtuple("GetHeaterTemp_Response", "RespTemperature,RespUnit,Status") + return GetHeaterTemp_Response(Decimal(rsp[0]),str(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def EnableHeaterHoldMode(HoldMode:int=""): + """ + Switches the Temperature Chuck devices hold mode on or off. In hold mode the + chuck is heated with a constant current to avoid noise from the temperature + control. The hold mode can be enabled only in HoldReady state. + API Status: published + Args: + HoldMode:int = 1 + Returns: + RespHoldMode:int + Command Timeout: 60000 + Example:EnableHeaterHoldMode 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterHoldMode",HoldMode) + return int(rsp[0]) + +def StopHeatChuck(): + """ + Stops a pending heating or cooling process. If the device is not at temperature, + the actual temperature is set as target temperature. + API Status: published + Command Timeout: 60000 + Example:StopHeatChuck + """ + MessageServerInterface.sendSciCommand("StopHeatChuck") + + +def GetDewPointTemp(Unit:str=""): + """ + Returns the current dew point temperature, if a dew point sensor is connected. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetDewPointTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetDewPointTemp",Unit) + global GetDewPointTemp_Response + if not "GetDewPointTemp_Response" in globals(): GetDewPointTemp_Response = namedtuple("GetDewPointTemp_Response", "RespTemperature,RespUnit") + return GetDewPointTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def GetTemperatureChuckOptions(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the currently set temperature chuck options. + API Status: internal + Returns: + UseSoakTime:int + SyncTemp:int + CurrConnection:int + MinTemperature:Decimal + MaxTemperature:Decimal + UsePurge:int + UseDynamicSoakTime:int + UseFixedDieSoakTime:int + UseDynamicDieSoakTime:int + UseEcoMode:int + PurgeOnChamberDoor:int + ForceBypassPurge:int + DoorClosedTime:int + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("GetTemperatureChuckOptions") + global GetTemperatureChuckOptions_Response + if not "GetTemperatureChuckOptions_Response" in globals(): GetTemperatureChuckOptions_Response = namedtuple("GetTemperatureChuckOptions_Response", "UseSoakTime,SyncTemp,CurrConnection,MinTemperature,MaxTemperature,UsePurge,UseDynamicSoakTime,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime") + return GetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12])) + +def SetTemperatureChuckOptions(UseFixedWaferSoak:int="", SyncTemp:int="", CurrConnection:int="", UsePurge:int="", UseDynamicWaferSoak:int="", UseFixedDieSoakTime:int="", UseDynamicDieSoakTime:int="", UseEcoMode:int="", PurgeOnChamberDoor:int="", ForceBypassPurge:int="", DoorClosedTime:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command is used to change the currently set temperature chuck options. + API Status: internal + Args: + UseFixedWaferSoak:int = -1 + SyncTemp:int = -1 + CurrConnection:int = -1 + UsePurge:int = -1 + UseDynamicWaferSoak:int = -1 + UseFixedDieSoakTime:int = -1 + UseDynamicDieSoakTime:int = -1 + UseEcoMode:int = -1 + PurgeOnChamberDoor:int = -1 + ForceBypassPurge:int = -1 + DoorClosedTime:int = -1 + Returns: + UseFixedWaferSoakRsp:int + SyncTempRsp:int + CurrConnectionRsp:int + UsePurgeRsp:int + UseDynamicWaferSoakRsp:int + UseFixedDieSoakTimeRsp:int + UseDynamicDieSoakTimeRsp:int + UseEcoModeRsp:int + PurgeOnChamberDoorRsp:int + ForceBypassPurgeRsp:int + DoorClosedTimeRsp:int + Command Timeout: 300000 + Example:SetTemperatureChuckOptions 1 0 1 1 1 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetTemperatureChuckOptions",UseFixedWaferSoak,SyncTemp,CurrConnection,UsePurge,UseDynamicWaferSoak,UseFixedDieSoakTime,UseDynamicDieSoakTime,UseEcoMode,PurgeOnChamberDoor,ForceBypassPurge,DoorClosedTime) + global SetTemperatureChuckOptions_Response + if not "SetTemperatureChuckOptions_Response" in globals(): SetTemperatureChuckOptions_Response = namedtuple("SetTemperatureChuckOptions_Response", "UseFixedWaferSoakRsp,SyncTempRsp,CurrConnectionRsp,UsePurgeRsp,UseDynamicWaferSoakRsp,UseFixedDieSoakTimeRsp,UseDynamicDieSoakTimeRsp,UseEcoModeRsp,PurgeOnChamberDoorRsp,ForceBypassPurgeRsp,DoorClosedTimeRsp") + return SetTemperatureChuckOptions_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10])) + +def GetHeaterSoak(): + """ + Returns the current soak time values in seconds and the soaking status. + API Status: published + Returns: + FixedWaferSoakTime:int + FixedWaferSoakStatus:int + DynamicWaferSoakTime:Decimal + DynamicWaferSoakStatus:int + FixedDieSoakTime:Decimal + DynamicDieSoakTime:Decimal + FixedDieSoakStatus:int + DynamicDieSoakStatus:int + Command Timeout: 60000 + Example:GetHeaterSoak + """ + rsp = MessageServerInterface.sendSciCommand("GetHeaterSoak") + global GetHeaterSoak_Response + if not "GetHeaterSoak_Response" in globals(): GetHeaterSoak_Response = namedtuple("GetHeaterSoak_Response", "FixedWaferSoakTime,FixedWaferSoakStatus,DynamicWaferSoakTime,DynamicWaferSoakStatus,FixedDieSoakTime,DynamicDieSoakTime,FixedDieSoakStatus,DynamicDieSoakStatus") + return GetHeaterSoak_Response(int(rsp[0]),int(rsp[1]),Decimal(rsp[2]),int(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),int(rsp[6]),int(rsp[7])) + +def SetHeaterSoak(FixedWaferSoakTime:int="", DynamicWaferSoakTime:Decimal="", FixedDieSoakTime:Decimal="", DynamicDieSoakTime:Decimal=""): + """ + Sets the new soak time values. The unit of the values is seconds. If soak time + is actually running, it may be affected by the change. + API Status: published + Args: + FixedWaferSoakTime:int = 60 + DynamicWaferSoakTime:Decimal = -1 + FixedDieSoakTime:Decimal = -1 + DynamicDieSoakTime:Decimal = -1 + Command Timeout: 60000 + Example:SetHeaterSoak 60 + """ + MessageServerInterface.sendSciCommand("SetHeaterSoak",FixedWaferSoakTime,DynamicWaferSoakTime,FixedDieSoakTime,DynamicDieSoakTime) + + +def EnableHeaterStandby(Standby:int=""): + """ + Switches the power save (standby) mode of the device on or off. If the device is + in power save mode, setting and reading temperatures switches off the power save + mode automatically. + API Status: published + Args: + Standby:int = 1 + Returns: + RespStandby:int + Command Timeout: 60000 + Example:EnableHeaterStandby 1 + """ + rsp = MessageServerInterface.sendSciCommand("EnableHeaterStandby",Standby) + return int(rsp[0]) + +def ReadTemperatureChuckStatus(): + """ + Returns values of the temperature chuck status. The status byte gives + information about the current controller's action. The dew point sensor status + encapsulates information, if such a sensor is connected, and if the actual dew + point difference temperature is readable (active). It can be used for purge + control. Soak time left (in seconds) is used when soak time is actually running. + API Status: published + Returns: + Status:str + DPSensor:int + SoakTimeLeft:int + HasEcoMode:int + Command Timeout: 60000 + Example:ReadTemperatureChuckStatus + """ + rsp = MessageServerInterface.sendSciCommand("ReadTemperatureChuckStatus") + global ReadTemperatureChuckStatus_Response + if not "ReadTemperatureChuckStatus_Response" in globals(): ReadTemperatureChuckStatus_Response = namedtuple("ReadTemperatureChuckStatus_Response", "Status,DPSensor,SoakTimeLeft,HasEcoMode") + return ReadTemperatureChuckStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def GetTargetTemp(Unit:str=""): + """ + Reads the target temperature of the chuck. + API Status: published + Args: + Unit:str = "Celsius" + Returns: + RespTemperature:Decimal + RespUnit:str + Command Timeout: 60000 + Example:GetTargetTemp C + """ + rsp = MessageServerInterface.sendSciCommand("GetTargetTemp",Unit) + global GetTargetTemp_Response + if not "GetTargetTemp_Response" in globals(): GetTargetTemp_Response = namedtuple("GetTargetTemp_Response", "RespTemperature,RespUnit") + return GetTargetTemp_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def SetThermoWindow(Window:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command sets the window for the target temperture which is the window in which a + station is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Args: + Window:Decimal = 1 + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:SetThermoWindow 2.0 + """ + rsp = MessageServerInterface.sendSciCommand("SetThermoWindow",Window) + return Decimal(rsp[0]) + +def GetThermoWindow(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command returns the current thermo window which is the window in which a station + is assumed to be at temp. Only supported on Nucleus stations. + API Status: internal + Returns: + RespWindow:Decimal + Command Timeout: 60000 + Example:GetThermoWindow + """ + rsp = MessageServerInterface.sendSciCommand("GetThermoWindow") + return Decimal(rsp[0]) + +def SendThermoCommand(Command:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sends a command string to the thermal chuck using the thermal chuck protocol and + returns the thermal chucks response as command response. This command can be + used to access thermal chuck features that are not exposed as standalone SCI + commands. Command is currently implemented for ERS and ATT chucks. + API Status: internal + Args: + Command:str = "" + Returns: + Response:str + Command Timeout: 5000 + Example:SendThermoCommand RH + """ + rsp = MessageServerInterface.sendSciCommand("SendThermoCommand",Command) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ReadAuxStatus(AuxID:int=""): + """ + Returns the status of a single AUX site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + FlagsMode:int + Comp:str + PresetHeight:str + AuxSiteType:str + Command Timeout: 10000 + Example:ReadAuxStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxStatus",AuxID) + global ReadAuxStatus_Response + if not "ReadAuxStatus_Response" in globals(): ReadAuxStatus_Response = namedtuple("ReadAuxStatus_Response", "AuxIDEcho,FlagsMode,Comp,PresetHeight,AuxSiteType") + return ReadAuxStatus_Response(int(rsp[0]),int(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ReadAuxPosition(AuxID:int="", Unit:str="", PosRef:str="", Comp:str=""): + """ + Returns the actual AUX sites position in X, Y and Z. With AUX ID set to 0, the + position is read for the chuck stage. If no AUX ID is given, it tries to read + the position from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + PosRef:str = "Home" + Comp:str = "Default" + Returns: + AuxIDEcho:int + X:Decimal + Y:Decimal + Z:Decimal + Command Timeout: 10000 + Example:ReadAuxPosition 1 Y Z + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxPosition",AuxID,Unit,PosRef,Comp) + global ReadAuxPosition_Response + if not "ReadAuxPosition_Response" in globals(): ReadAuxPosition_Response = namedtuple("ReadAuxPosition_Response", "AuxIDEcho,X,Y,Z") + return ReadAuxPosition_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def ReadAuxHeights(AuxID:int="", Unit:str=""): + """ + Returns the actual technology heights from an AUX site. If AUX ID is set to 0, + all response values are read from chuck stage. If no AUX ID is given, it tries + to read the heights from the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Contact:Decimal + Overtravel:Decimal + AlignDist:Decimal + SepDist:Decimal + Command Timeout: 10000 + Example:ReadAuxHeights 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxHeights",AuxID,Unit) + global ReadAuxHeights_Response + if not "ReadAuxHeights_Response" in globals(): ReadAuxHeights_Response = namedtuple("ReadAuxHeights_Response", "AuxIDEcho,Contact,Overtravel,AlignDist,SepDist") + return ReadAuxHeights_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4])) + +def SetAuxMode(AuxID:int="", Overtravel:int=""): + """ + Modes manage the way a stage behaves when it is in contact height. AUX site mode + holds only a single flag. Flags can be turned on by using the value 1 or turned + off by using the value 0. If you do not want to change the flag - use the value + of 2. If AUX ID is set to 0, all flags are set for chuck stage. AUX site will + move an additional overtravel on every contact move. + API Status: published + Args: + AuxID:int = -1 + Overtravel:int = 2 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxMode 1 2 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxMode",AuxID,Overtravel) + return int(rsp[0]) + +def SetAuxHome(AuxID:int="", Mode:str="", Unit:str="", XValue:Decimal="", YValue:Decimal=""): + """ + Sets the AUX sites Home position in X and Y. It defines the origin of the AUX + sites coordinate system for later movements. Usually this position is identical + to the die home position. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + XValue:Decimal = 0 + YValue:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHome 1 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHome",AuxID,Mode,Unit,XValue,YValue) + return int(rsp[0]) + +def SetAuxIndex(AuxID:int="", XValue:Decimal="", YValue:Decimal="", Unit:str=""): + """ + Sets the AUX sites index size. If AUX ID is set to 0, index size is set for + chuck stage. + API Status: published + Args: + AuxID:int = -1 + XValue:Decimal = 0 + YValue:Decimal = 0 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxIndex 1 1000. 1000. Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxIndex",AuxID,XValue,YValue,Unit) + return int(rsp[0]) + +def SetAuxHeight(AuxID:int="", PresetHeight:str="", Mode:str="", Unit:str="", Value:Decimal=""): + """ + Sets the AUX sites contact height and corresponding gaps for overtravel, + alignment and separation height. A contact height search gap for contact search + with edge sensor can also be set. This search gap is always identical for all + AUX sites. Without any optional parameters the command sets contact height to + the current position. + API Status: published + Args: + AuxID:int = -1 + PresetHeight:str = "Contact" + Mode:str = "0" + Unit:str = "Microns" + Value:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxHeight 1 C 0 Y + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxHeight",AuxID,PresetHeight,Mode,Unit,Value) + return int(rsp[0]) + +def ReadAuxIndex(AuxID:int="", Unit:str=""): + """ + Returns the actual AUX sites index values. If AUX ID is set to 0, the index size + is read from chuck stage. If no AUX ID is given, it tries to read the index from + the active site. + API Status: published + Args: + AuxID:int = -1 + Unit:str = "Microns" + Returns: + AuxIDEcho:int + IndexX:Decimal + IndexY:Decimal + Command Timeout: 10000 + Example:ReadAuxIndex 1 Y + """ + rsp = MessageServerInterface.sendSciCommand("ReadAuxIndex",AuxID,Unit) + global ReadAuxIndex_Response + if not "ReadAuxIndex_Response" in globals(): ReadAuxIndex_Response = namedtuple("ReadAuxIndex_Response", "AuxIDEcho,IndexX,IndexY") + return ReadAuxIndex_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetAuxThetaHome(AuxID:int="", Mode:str="", Unit:str="", Position:Decimal=""): + """ + Sets the AUX sites theta home position. It defines the origin of the AUX sites + theta coordinate system for later movements. If AUX ID is set to 0, theta home + position is set for chuck stage. + API Status: published + Args: + AuxID:int = -1 + Mode:str = "0" + Unit:str = "Microns" + Position:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxThetaHome 1 0 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxThetaHome",AuxID,Mode,Unit,Position) + return int(rsp[0]) + +def EnableOffset(Stage:str="", Enable:int="", Move:int=""): + """ + Enables or disables the Offset XY compensation for the selected stage. If the + compensation holds an offset different from zero, the chuck is automatically + moved the distance of the offset. The chuck also moves automatically to a safe + height. The move can be disabled by the third parameter. This may put the stage + outside the software fence. + API Status: published + Args: + Stage:str = "Chuck" + Enable:int = 1 + Move:int = 1 + Command Timeout: 60000 + Example:EnableOffset C 1 + """ + MessageServerInterface.sendSciCommand("EnableOffset",Stage,Enable,Move) + + +def SetOffset(Stage:str="", OffsetX:Decimal="", OffsetY:Decimal=""): + """ + Sets the offset values for the Offset XY compensation for the selected stage. + The changes take effect immediately. Note that the Offset XY compensation must + be enabled for the values to take effect. The compensation is enabled or + disabled using EnableOffset command. + API Status: published + Args: + Stage:str = "Chuck" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Command Timeout: 5000 + Example:SetOffset C 100000.0 0.0 + """ + MessageServerInterface.sendSciCommand("SetOffset",Stage,OffsetX,OffsetY) + + +def GetOffsetInfo(Stage:str=""): + """ + Gets information about the Offset XY compensation of the selected stage, + including the stored offset values and whether the compensation is enabled or + disabled. + API Status: published + Args: + Stage:str = "Chuck" + Returns: + Enable:int + OffsetX:Decimal + OffsetY:Decimal + Command Timeout: 5000 + Example:GetOffsetInfo C + """ + rsp = MessageServerInterface.sendSciCommand("GetOffsetInfo",Stage) + global GetOffsetInfo_Response + if not "GetOffsetInfo_Response" in globals(): GetOffsetInfo_Response = namedtuple("GetOffsetInfo_Response", "Enable,OffsetX,OffsetY") + return GetOffsetInfo_Response(int(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2])) + +def SetSwitchPosition(Stage:str="", AuxSite:int="", X:Decimal="", Y:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the switch position of a stage. This is the position to move to if an aux + site gets active. This is only supported for the chuck and it's aux sites. Aux + index 0 means wafer site, 1 means aux site 1 and so on. + API Status: internal + Args: + Stage:str = "Chuck" + AuxSite:int = 0 + X:Decimal = 0 + Y:Decimal = 0 + Command Timeout: 5000 + Example:SetSwitchPosition C 0 5000 5000 + """ + MessageServerInterface.sendSciCommand("SetSwitchPosition",Stage,AuxSite,X,Y) + + +def MoveAuxSite(AuxID:int=""): + """ + Moves the chuck to the position of a given AUX site. A safe height is used for + the move. If AUX ID is set to 0, the target of the move is the wafer site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Command Timeout: 60000 + Example:MoveAuxSite 1 + """ + rsp = MessageServerInterface.sendSciCommand("MoveAuxSite",AuxID) + return int(rsp[0]) + +def SetAuxSiteCount(AuxSiteCount:int=""): + """ + Sets the number of available AUX sites. For preparing for example two cal + chucks, the count must be set to 2. For the changes to take effect the system + needs to be restarted. + API Status: published + Args: + AuxSiteCount:int = 0 + Command Timeout: 10000 + Example:SetAuxSiteCount 2 + """ + MessageServerInterface.sendSciCommand("SetAuxSiteCount",AuxSiteCount) + + +def GetAuxSiteCount(): + """ + Reads the number of available AUX sites and the ID of the actual active AUX + site. If this is 0, the chuck stage is currently active. + API Status: published + Returns: + AuxSiteCount:int + ActualAuxSite:int + Command Timeout: 10000 + Example:GetAuxSiteCount + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteCount") + global GetAuxSiteCount_Response + if not "GetAuxSiteCount_Response" in globals(): GetAuxSiteCount_Response = namedtuple("GetAuxSiteCount_Response", "AuxSiteCount,ActualAuxSite") + return GetAuxSiteCount_Response(int(rsp[0]),int(rsp[1])) + +def SetAuxSiteName(AuxID:int="", AuxSiteName:str=""): + """ + Sets the description of an AUX site. With AUX ID zero, the description of the + wafer site can be set. + API Status: published + Args: + AuxID:int = -1 + AuxSiteName:str = "" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteName 1 Aux site 1 + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteName",AuxID,AuxSiteName) + return int(rsp[0]) + +def GetAuxSiteName(AuxID:int=""): + """ + This command reads the description of an AUX site. If AUX ID is set to 0, the + description of the chuck stage is given back. If no AUX ID is given, it tries to + read from the active site. + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + AuxSiteName:str + Command Timeout: 10000 + Example:GetAuxSiteName 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetAuxSiteName",AuxID) + global GetAuxSiteName_Response + if not "GetAuxSiteName_Response" in globals(): GetAuxSiteName_Response = namedtuple("GetAuxSiteName_Response", "AuxIDEcho,AuxSiteName") + return GetAuxSiteName_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def CleanProbeTip(AuxID:str=""): + """ + Starts a probe tip cleaning on the given AUX site. The cleaning algorithm is + dependent from the type of the AUX site and from the duration and the cleaning + count that is set in configuration. The cleaning algorithm includes both a move + to the pad site and a move back to the source site. + API Status: published + Args: + AuxID:str = "-1" + Returns: + AuxIDEcho:int + Command Timeout: 300000 + Example:CleanProbeTip 1 + """ + rsp = MessageServerInterface.sendSciCommand("CleanProbeTip",AuxID) + return int(rsp[0]) + +def SetAuxSiteType(AuxID:int="", AuxSiteType:str=""): + """ + Sets the type for a given AUX site. It depends on the type of the AUX site, if + there is a cleaning algorithm available. It is not possible to set the type of + the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + AuxSiteType:str = "AuxUnknown" + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetAuxSiteType 1 G + """ + rsp = MessageServerInterface.sendSciCommand("SetAuxSiteType",AuxID,AuxSiteType) + return int(rsp[0]) + +def SetCleaningParams(AuxID:int="", Count:int="", Time:int=""): + """ + Sets the cleaning parameters for a given AUX site. It is not possible to set the + cleaning parameters of the wafer site (AUX site 0). If no AUX ID is given, it + tries to set the parameters of the active site. The cleaning count defines, + how much times the cleaning is performed repeatedly. The cleaning time defines, + how much milliseconds the needles wait in cleaning position during each + cleaning cycle. + API Status: published + Args: + AuxID:int = -1 + Count:int = 1 + Time:int = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:SetCleaningParams 1 5 1000 + """ + rsp = MessageServerInterface.sendSciCommand("SetCleaningParams",AuxID,Count,Time) + return int(rsp[0]) + +def GetCleaningParams(AuxID:int=""): + """ + Reads the cleaning parameters of a given AUX site. It is not possible to read + cleaning parameters of the wafer site (AUX site 0). + API Status: published + Args: + AuxID:int = -1 + Returns: + AuxIDEcho:int + Count:int + Time:int + Remaining:int + Command Timeout: 30000 + Example:GetCleaningParams + """ + rsp = MessageServerInterface.sendSciCommand("GetCleaningParams",AuxID) + global GetCleaningParams_Response + if not "GetCleaningParams_Response" in globals(): GetCleaningParams_Response = namedtuple("GetCleaningParams_Response", "AuxIDEcho,Count,Time,Remaining") + return GetCleaningParams_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3])) + +def UpdateAuxSitePositions(AuxID:int="", XOffset:Decimal="", YOffset:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Rotate the switch, home, and fence positions to match the current chuck theta + angle and adjust Home/Switch by XY offset. Should only be used for Aux sites + that don't move theta. + API Status: internal + Args: + AuxID:int = -1 + XOffset:Decimal = 0 + YOffset:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 5000 + Example:UpdateAuxSitePositions 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateAuxSitePositions",AuxID,XOffset,YOffset) + return int(rsp[0]) + +def ResetCleaningPosition(AuxID:str="", OffsetX:Decimal="", OffsetY:Decimal=""): + """ + Resets the cleaning position to the beginning of the cleaning aux site (home). + API Status: published + Args: + AuxID:str = "-1" + OffsetX:Decimal = 0 + OffsetY:Decimal = 0 + Returns: + AuxIDEcho:int + Command Timeout: 10000 + Example:ResetCleaningPosition 5 + """ + rsp = MessageServerInterface.sendSciCommand("ResetCleaningPosition",AuxID,OffsetX,OffsetY) + return int(rsp[0]) + +def BnR_EchoData(ControllerID:int="", TestCmd:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Test Command for the Kernel Communication. It is like a ping command. The given + text string is returned unchanged. + API Status: internal + Args: + ControllerID:int = 1 + TestCmd:str = "Test" + Returns: + TestRsp:str + Command Timeout: 5000 + Example:BnR_EchoData 1 Hello World + """ + rsp = MessageServerInterface.sendSciCommand("BnR_EchoData",ControllerID,TestCmd) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_ReportKernelVersion(ControllerID:int="", Module:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the actual version information of the controller software. + The 'Version' value contains version number and revision level of the actual + implementation. The text string contains a + code description, version number and the revision date. + The 'Module' byte is optional (default is K). + API Status: internal + Args: + ControllerID:int = 1 + Module:str = "K" + Returns: + Version:Decimal + Description:str + Command Timeout: 5000 + Example:BnR_ReportKernelVersion 1 K + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReportKernelVersion",ControllerID,Module) + global BnR_ReportKernelVersion_Response + if not "BnR_ReportKernelVersion_Response" in globals(): BnR_ReportKernelVersion_Response = namedtuple("BnR_ReportKernelVersion_Response", "Version,Description") + return BnR_ReportKernelVersion_Response(Decimal(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetStationType(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns information about the connected station. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StationType:str + Type:str + Command Timeout: 5000 + Example:BnR_GetStationType 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStationType",ControllerID) + global BnR_GetStationType_Response + if not "BnR_GetStationType_Response" in globals(): BnR_GetStationType_Response = namedtuple("BnR_GetStationType_Response", "StationType,Type") + return BnR_GetStationType_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_ResetController(ControllerID:int="", Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Restarts the BnR controller. + API Status: internal + Args: + ControllerID:int = 1 + Mode:str = "X" + Command Timeout: 10000 + Example:BnR_ResetController 1 + """ + MessageServerInterface.sendSciCommand("BnR_ResetController",ControllerID,Mode) + + +def BnR_SetOutput(ControllerID:int="", Channel:str="", State:int="", CycleTime:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Controls the Velox output channel signals. It can be used to activate/deactivate + outputs. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + State:int = 0 + CycleTime:int = 0 + Command Timeout: 5000 + Example:BnR_SetOutput 1 1000 1 2000 + """ + MessageServerInterface.sendSciCommand("BnR_SetOutput",ControllerID,Channel,State,CycleTime) + + +def BnR_GetOutput(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an output channel. By using the string identifier DO_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DO_WaferVacuum" + Returns: + State:int + AllOutputs:str + Command Timeout: 5000 + Example:BnR_GetOutput 1 DO_WaferVacuum + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetOutput",ControllerID,Channel) + global BnR_GetOutput_Response + if not "BnR_GetOutput_Response" in globals(): BnR_GetOutput_Response = namedtuple("BnR_GetOutput_Response", "State,AllOutputs") + return BnR_GetOutput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetInput(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the state of an input channel. By using the string identifier DI_ALL, a + string list of all outputs is returned in addition + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "DI_MotorPower" + Returns: + State:int + AllInputs:str + Command Timeout: 5000 + Example:BnR_GetInput 1 DI_MotorPower + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInput",ControllerID,Channel) + global BnR_GetInput_Response + if not "BnR_GetInput_Response" in globals(): BnR_GetInput_Response = namedtuple("BnR_GetInput_Response", "State,AllInputs") + return BnR_GetInput_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_SetAnalogOutput(ControllerID:int="", Channel:str="", OutputPercent:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets an analog output channel to a given value. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + OutputPercent:Decimal = 50 + Command Timeout: 5000 + Example:BnR_SetAnalogOutput 1 AO_PurgeDewPoint 50 + """ + MessageServerInterface.sendSciCommand("BnR_SetAnalogOutput",ControllerID,Channel,OutputPercent) + + +def BnR_GetAnalogIO(ControllerID:int="", Channel:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current value of an analog output or input. + API Status: internal + Args: + ControllerID:int = 1 + Channel:str = "AO_PurgeDewPoint" + Returns: + Value:Decimal + UnderOverflow:int + Command Timeout: 5000 + Example:BnR_GetAnalogIO 1 AO_PurgeDewPoint + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAnalogIO",ControllerID,Channel) + global BnR_GetAnalogIO_Response + if not "BnR_GetAnalogIO_Response" in globals(): BnR_GetAnalogIO_Response = namedtuple("BnR_GetAnalogIO_Response", "Value,UnderOverflow") + return BnR_GetAnalogIO_Response(Decimal(rsp[0]),int(rsp[1])) + +def BnR_GetStartupStatus(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the startup status of the BnR controller to determine if the controller + is properly booted or still starting. + API Status: internal + Args: + ControllerID:int = 1 + Returns: + StartupStatus:str + AdditionalStatusInfo:str + Command Timeout: 5000 + Example:BnR_GetStartupStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetStartupStatus",ControllerID) + global BnR_GetStartupStatus_Response + if not "BnR_GetStartupStatus_Response" in globals(): BnR_GetStartupStatus_Response = namedtuple("BnR_GetStartupStatus_Response", "StartupStatus,AdditionalStatusInfo") + return BnR_GetStartupStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_CreateSdmSystemDump(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Creates a Sdm System Dump file on the B&R flash + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 60000 + Example:BnR_CreateSdmSystemDump + """ + MessageServerInterface.sendSciCommand("BnR_CreateSdmSystemDump",ControllerID) + + +def BnR_GetControllerData(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Gets controller data from the B&R controller. Currently used for init + information. + API Status: internal + Args: + ControllerID:int = 1 + Command Timeout: 10000 + Example:BnR_GetControllerData 1 + """ + MessageServerInterface.sendSciCommand("BnR_GetControllerData",ControllerID) + + +def BnR_WriteMessage(ControllerID:int="", MessageType:str="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to write a (native) message to Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Message:str = "" + Command Timeout: 5000 + Example:BnR_WriteMessage 1 mtCryoLoader SampleMessage + """ + MessageServerInterface.sendSciCommand("BnR_WriteMessage",ControllerID,MessageType,Message) + + +def BnR_ReadMessage(ControllerID:int="", MessageType:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to read a (native) message from Controller + API Status: internal + Args: + ControllerID:int = 1 + MessageType:str = "mtCryoLoader" + Returns: + Message:str + Command Timeout: 5000 + Example:BnR_ReadMessage 1 mtCryoLoader + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadMessage",ControllerID,MessageType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetDataIterator(ControllerID:int="", ShowAll:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a data stream handle which represents a data stream of setup parameters + and requires the BnR_GetNextDatum command. + API Status: internal + Args: + ControllerID:int = 1 + ShowAll:int = 0 + Returns: + IdentityToken:int + SizeNoAll:int + Command Timeout: 5000 + Example:BnR_GetDataIterator 1 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDataIterator",ControllerID,ShowAll) + global BnR_GetDataIterator_Response + if not "BnR_GetDataIterator_Response" in globals(): BnR_GetDataIterator_Response = namedtuple("BnR_GetDataIterator_Response", "IdentityToken,SizeNoAll") + return BnR_GetDataIterator_Response(int(rsp[0]),int(rsp[1])) + +def BnR_GetNextDatum(ControllerID:int="", IdentityToken:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the next parameter from the data stream. Fields are separated by a + colon. Structure of the response parameter Value: + Path_Path:Name:Description:Value + API Status: internal + Args: + ControllerID:int = 1 + IdentityToken:int = 0 + Returns: + IsLastDatum:int + DatumCode:int + PathNameDescrValue:str + Command Timeout: 10000 + Example:BnR_GetNextDatum 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetNextDatum",ControllerID,IdentityToken) + global BnR_GetNextDatum_Response + if not "BnR_GetNextDatum_Response" in globals(): BnR_GetNextDatum_Response = namedtuple("BnR_GetNextDatum_Response", "IsLastDatum,DatumCode,PathNameDescrValue") + return BnR_GetNextDatum_Response(int(rsp[0]),int(rsp[1]),str("" if len(rsp) < 3 else ' '.join(rsp[2:]))) + +def BnR_SetDatum(ControllerID:int="", PathNameAndValue:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the value of a parameter. An empty parameter string saves the whole + configuration to non-volatile memory. Fields are separated by a colon. + API Status: internal + Args: + ControllerID:int = 1 + PathNameAndValue:str = "" + Command Timeout: 20000 + Example:BnR_SetDatum 1 Chuck_XAxisData:CurrentMaximal:70 + """ + MessageServerInterface.sendSciCommand("BnR_SetDatum",ControllerID,PathNameAndValue) + + +def BnR_GetDatum(ControllerID:int="", PathName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a value string. The Value string consists of the value and the + description. The Locator only consists of the path and the name. All fields are + separated by a colon. Structure of the command parameter Locator: + Path_Path:Name Structure of the response parameter Value: Value:Description + API Status: internal + Args: + ControllerID:int = 1 + PathName:str = "" + Returns: + DatumCode:int + ValueDesc:str + Command Timeout: 5000 + Example:BnR_GetDatum 1 Chuck_XAxisData:CurrentMaximal + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetDatum",ControllerID,PathName) + global BnR_GetDatum_Response + if not "BnR_GetDatum_Response" in globals(): BnR_GetDatum_Response = namedtuple("BnR_GetDatum_Response", "DatumCode,ValueDesc") + return BnR_GetDatum_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_DoInternalTask(ControllerID:int="", Task:str="", PCmdInt1:int="", PCmdInt2:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes an internal BnR Task + API Status: internal + Args: + ControllerID:int = 1 + Task:str = "" + PCmdInt1:int = 0 + PCmdInt2:int = 0 + Returns: + RspInt:int + RspString:str + Command Timeout: 10000 + Example:BnR_DoInternalTask 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_DoInternalTask",ControllerID,Task,PCmdInt1,PCmdInt2) + global BnR_DoInternalTask_Response + if not "BnR_DoInternalTask_Response" in globals(): BnR_DoInternalTask_Response = namedtuple("BnR_DoInternalTask_Response", "RspInt,RspString") + return BnR_DoInternalTask_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetPosition(Stage:str="", Unit:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current positions for the X,Y,Z (or T) axis for the specified stage + as well as the commanded positions. + API Status: internal + Args: + Stage:str = "Chuck" + Unit:str = "Microns" + Returns: + XorT:Decimal + Y:Decimal + Z:Decimal + CommandedXorT:Decimal + CommandedY:Decimal + CommandedZ:Decimal + Command Timeout: 5000 + Example:BnR_GetPosition 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetPosition",Stage,Unit) + global BnR_GetPosition_Response + if not "BnR_GetPosition_Response" in globals(): BnR_GetPosition_Response = namedtuple("BnR_GetPosition_Response", "XorT,Y,Z,CommandedXorT,CommandedY,CommandedZ") + return BnR_GetPosition_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5])) + +def BnR_Move(Stage:str="", XValue:Decimal="", YValue:Decimal="", VelX:Decimal="", VelY:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a XY movement for a specified stage. This can be either a + blocking or non blocking move. + API Status: internal + Args: + Stage:str = "Chuck" + XValue:Decimal = 0 + YValue:Decimal = 0 + VelX:Decimal = 0 + VelY:Decimal = 0 + WaitFinished:int = 1 + Returns: + X:Decimal + Y:Decimal + Command Timeout: 60000 + Example:BnR_Move 1 C 5000 5000 Z 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_Move",Stage,XValue,YValue,VelX,VelY,WaitFinished) + global BnR_Move_Response + if not "BnR_Move_Response" in globals(): BnR_Move_Response = namedtuple("BnR_Move_Response", "X,Y") + return BnR_Move_Response(Decimal(rsp[0]),Decimal(rsp[1])) + +def BnR_MoveZ(Stage:str="", ZValue:Decimal="", Vel:Decimal="", Dec:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the stage Z axis to a new position. + API Status: internal + Args: + Stage:str = "Chuck" + ZValue:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + Z:Decimal + Command Timeout: 600000 + Example:BnR_MoveZ 1 C 12000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZ",Stage,ZValue,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_ScanMoveZ(ControllerID:int="", Stage:str="", ZDistance:Decimal="", TriggerEveryNthCycle:int="", Vel:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command executes a scan movement of the Z axis that sets a digital output + every couple microns to trigger e.g. a camera. After the move is finished, the + command returns a list of Z heights at which the digital output was set. + API Status: internal + Args: + ControllerID:int = 1 + Stage:str = "Chuck" + ZDistance:Decimal = 1000 + TriggerEveryNthCycle:int = 2 + Vel:Decimal = 10 + Command Timeout: 300000 + Example:BnR_ScanMoveZ 1 C 1000 6 10 + """ + MessageServerInterface.sendSciCommand("BnR_ScanMoveZ",ControllerID,Stage,ZDistance,TriggerEveryNthCycle,Vel) + + +def BnR_MoveT(TValue:Decimal="", Vel:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Executes a movement of the theta axis, either blocking or non blocking + API Status: internal + Args: + TValue:Decimal = 0 + Vel:Decimal = 0 + WaitFinished:int = 1 + Returns: + T:Decimal + Command Timeout: 60000 + Example:BnR_MoveT 1 1.003 10 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveT",TValue,Vel,WaitFinished) + return Decimal(rsp[0]) + +def BnR_StopAxis(Stage:str="", FlagsStop:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Stops 1... all axes of a stage + API Status: internal + Args: + Stage:str = "Chuck" + FlagsStop:int = 15 + Command Timeout: 5000 + Example:BnR_StopAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_StopAxis",Stage,FlagsStop) + + +def BnR_InitAxis(Stage:str="", FlagsInit:int="", FlagsDirection:int="", FlagsInitInPlace:int="", LowLimitX:Decimal="", LowLimitY:Decimal="", LowLimitZ:Decimal="", LowLimitTh:Decimal="", InitInPlaceMoveRangeX:Decimal="", InitInPlaceMoveRangeY:Decimal="", InitInPlaceMoveRangeZ:Decimal="", InitInPlaceMoveRangeTh:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Machine Coordinate System: X Y Z Theta - _FlagsInit_: X, Y, Z, Theta - + _FlagsDirection_: X, Y, Z, Theta (true means plus direction) - + _FlagsInitInPlace_: X, Y, Z, Theta All flags can be accessed by indirect + members. Initializes the stage and resets current coordinate system. Should be + used only in cases when the reported coordinates do not correspond to real + position of mechanics. Init in Place performs the initialization without any + movements. + API Status: internal + Args: + Stage:str = "Chuck" + FlagsInit:int = 0 + FlagsDirection:int = 0 + FlagsInitInPlace:int = 0 + LowLimitX:Decimal = 0 + LowLimitY:Decimal = 0 + LowLimitZ:Decimal = 0 + LowLimitTh:Decimal = 0 + InitInPlaceMoveRangeX:Decimal = 0 + InitInPlaceMoveRangeY:Decimal = 0 + InitInPlaceMoveRangeZ:Decimal = 0 + InitInPlaceMoveRangeTh:Decimal = 0 + Command Timeout: 300000 + Example:BnR_InitAxis 1 C 7 + """ + MessageServerInterface.sendSciCommand("BnR_InitAxis",Stage,FlagsInit,FlagsDirection,FlagsInitInPlace,LowLimitX,LowLimitY,LowLimitZ,LowLimitTh,InitInPlaceMoveRangeX,InitInPlaceMoveRangeY,InitInPlaceMoveRangeZ,InitInPlaceMoveRangeTh) + + +def BnR_GetAxisState(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns the state of an axis (disabled/standstill/errorstop/stoppin + g/homing/continuousmotion/discretemotion/synchronizedmotion) + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + State:str + AdditionalStateInfo:str + Command Timeout: 5000 + Example:BnR_GetAxisState 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisState",Stage,Axis) + global BnR_GetAxisState_Response + if not "BnR_GetAxisState_Response" in globals(): BnR_GetAxisState_Response = namedtuple("BnR_GetAxisState_Response", "State,AdditionalStateInfo") + return BnR_GetAxisState_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def BnR_GetAxisStatus(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns some axis status information + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + Initialized:int + PositiveEndlimit:int + NegativeEndlimit:int + Command Timeout: 5000 + Example:BnR_GetAxisStatus 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetAxisStatus",Stage,Axis) + global BnR_GetAxisStatus_Response + if not "BnR_GetAxisStatus_Response" in globals(): BnR_GetAxisStatus_Response = namedtuple("BnR_GetAxisStatus_Response", "Initialized,PositiveEndlimit,NegativeEndlimit") + return BnR_GetAxisStatus_Response(int(rsp[0]),int(rsp[1]),int(rsp[2])) + +def BnR_SetQuietMode(Stage:str="", QuietMode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to enable the quiet mode for a stage (quiet turns motors powerless) + API Status: internal + Args: + Stage:str = "Chuck" + QuietMode:int = 0 + Command Timeout: 5000 + Example:BnR_SetQuietMode 1 C 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetQuietMode",Stage,QuietMode) + + +def BnR_GetQuietMode(Stage:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to query the quiet mode for a stage + API Status: internal + Args: + Stage:str = "Chuck" + Returns: + QuietMode:int + Command Timeout: 5000 + Example:BnR_GetQuietMode 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetQuietMode",Stage) + return int(rsp[0]) + +def BnR_GetInternalAxisInfo(Stage:str="", Axis:str="", InfoType:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command returns various axis information, dependent on the InfoType + parameter + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + InfoType:str = "StallInfo" + Returns: + RspString:str + Command Timeout: 5000 + Example:BnR_GetInternalAxisInfo 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetInternalAxisInfo",Stage,Axis,InfoType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_GetWiringTesterData(Stage:str="", Axis:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command to get various information required for the BnR wiring tester tool. + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Returns: + STIn_ModuleOK:int + STIn_LifeCnt:int + STIn_DrvOK:int + STIn_OvertemperatureError:int + STIn_CurrentError:int + STIn_OvercurrentError:int + STIn_RefPulsePos:int + STIn_RefPulseCnt:int + STIn_ModulePowerSupplyError:int + STOut_SetTime:int + STOut_MotorStep0:int + STOut_DriveEnable:int + STOut_BoostCurrent:int + STOut_StandStillCurrent:int + STOut_ClearError:int + CMIn_ModuleOK:int + CMIn_SDCLifeCount:int + CMIn_Encoder:int + CMIn_EncoderTimeValid:int + CMIn_DigitalInput1:int + CMIn_DigitalInput2:int + CMIn_BWChannelA:int + CMIn_BWChannelB:int + CMIn_PowerSupply2:int + CMOut_QuitChannelA:int + CMOut_QuitChannelB:int + SWAxisErrorID:int + SWAxisErrorDesc:str + Command Timeout: 5000 + Example:BnR_GetWiringTesterData 1 C X + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetWiringTesterData",Stage,Axis) + global BnR_GetWiringTesterData_Response + if not "BnR_GetWiringTesterData_Response" in globals(): BnR_GetWiringTesterData_Response = namedtuple("BnR_GetWiringTesterData_Response", "STIn_ModuleOK,STIn_LifeCnt,STIn_DrvOK,STIn_OvertemperatureError,STIn_CurrentError,STIn_OvercurrentError,STIn_RefPulsePos,STIn_RefPulseCnt,STIn_ModulePowerSupplyError,STOut_SetTime,STOut_MotorStep0,STOut_DriveEnable,STOut_BoostCurrent,STOut_StandStillCurrent,STOut_ClearError,CMIn_ModuleOK,CMIn_SDCLifeCount,CMIn_Encoder,CMIn_EncoderTimeValid,CMIn_DigitalInput1,CMIn_DigitalInput2,CMIn_BWChannelA,CMIn_BWChannelB,CMIn_PowerSupply2,CMOut_QuitChannelA,CMOut_QuitChannelB,SWAxisErrorID,SWAxisErrorDesc") + return BnR_GetWiringTesterData_Response(int(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),int(rsp[4]),int(rsp[5]),int(rsp[6]),int(rsp[7]),int(rsp[8]),int(rsp[9]),int(rsp[10]),int(rsp[11]),int(rsp[12]),int(rsp[13]),int(rsp[14]),int(rsp[15]),int(rsp[16]),int(rsp[17]),int(rsp[18]),int(rsp[19]),int(rsp[20]),int(rsp[21]),int(rsp[22]),int(rsp[23]),int(rsp[24]),int(rsp[25]),int(rsp[26]),str("" if len(rsp) < 28 else ' '.join(rsp[27:]))) + +def BnR_MoveAxis(Stage:str="", Axis:str="", Value:Decimal="", Vel:Decimal="", Dec:Decimal="", WaitFinished:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command allows moving a single axis to and e.g. in case of X does not + trigger a Y movement + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + Value:Decimal = 0 + Vel:Decimal = 0 + Dec:Decimal = 0 + WaitFinished:int = 1 + Returns: + PositionAfterMove:Decimal + Command Timeout: 60000 + Example:BnR_MoveAxis 1 C X 20000 100 100 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveAxis",Stage,Axis,Value,Vel,Dec,WaitFinished) + return Decimal(rsp[0]) + +def BnR_MoveZCombined(ChuckTargetZ:Decimal="", WaitFinished:int="", ForcedAbsVelocity:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move Chuck-Z and (by fixed factor) Scope X, Y and Z + API Status: internal + Args: + ChuckTargetZ:Decimal = 0 + WaitFinished:int = 1 + ForcedAbsVelocity:int = 0 + Returns: + ChuckZ:Decimal + ScopeX:Decimal + ScopeY:Decimal + ScopeZ:Decimal + Command Timeout: 600000 + Example:BnR_MoveZCombined 1 17592.5 1 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_MoveZCombined",ChuckTargetZ,WaitFinished,ForcedAbsVelocity) + global BnR_MoveZCombined_Response + if not "BnR_MoveZCombined_Response" in globals(): BnR_MoveZCombined_Response = namedtuple("BnR_MoveZCombined_Response", "ChuckZ,ScopeX,ScopeY,ScopeZ") + return BnR_MoveZCombined_Response(Decimal(rsp[0]),Decimal(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3])) + +def BnR_StepMove(Stage:str="", ZDown:Decimal="", XValue:Decimal="", YValue:Decimal="", ZUp:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + This command does a combined Z-XY-Z- move completely on the BnR-controller + without WinKernel interaction. This is a part of an ongoing optimization. + API Status: internal + Args: + Stage:str = "Chuck" + ZDown:Decimal = 0 + XValue:Decimal = 0 + YValue:Decimal = 0 + ZUp:Decimal = 0 + Command Timeout: 60000 + Example:BnR_StepMove 1 C 250 1000 1000 250 + """ + MessageServerInterface.sendSciCommand("BnR_StepMove",Stage,ZDown,XValue,YValue,ZUp) + + +def BnR_SearchEdgeSensor(SearchEndPos:Decimal="", Velocity:Decimal=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Performs a search move until the search end position is reached or the edge + sensor triggers. If the edge sensor triggers during the move, the trigger + position is returned.Otherwise, an edge sensor not found error is returned. + API Status: internal + Args: + SearchEndPos:Decimal = 0 + Velocity:Decimal = 0 + Returns: + EdgeSensorTriggerPos:Decimal + Command Timeout: 300000 + Example:BnR_SearchEdgeSensor 3000 10 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_SearchEdgeSensor",SearchEndPos,Velocity) + return Decimal(rsp[0]) + +def BnR_GetTraceData(ControllerID:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns a collection of trace data + API Status: internal + Args: + ControllerID:int = 1 + Returns: + Data:str + Command Timeout: 5000 + Example:BnR_GetTraceData 1 C + """ + rsp = MessageServerInterface.sendSciCommand("BnR_GetTraceData",ControllerID) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def BnR_SetTraceMode(ControllerID:int="", Mode:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Commands sets the trace mode + API Status: internal + Args: + ControllerID:int = 1 + Mode:int = 0 + Command Timeout: 5000 + Example:BnR_SetTraceMode 1 1 + """ + MessageServerInterface.sendSciCommand("BnR_SetTraceMode",ControllerID,Mode) + + +def BnR_WriteAxisModuleRegister(Stage:str="", Axis:str="", MotorModule:int="", RegisterName:str="", Value:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to change a module register value without controller restart + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Value:int = 0 + Command Timeout: 5000 + Example:BnR_WriteAxisModuleRegister 1 C X 1 ConfigOutput03 70 + """ + MessageServerInterface.sendSciCommand("BnR_WriteAxisModuleRegister",Stage,Axis,MotorModule,RegisterName,Value) + + +def BnR_ReadAxisModuleRegister(Stage:str="", Axis:str="", MotorModule:int="", RegisterName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Development command to get any desired module register value + API Status: internal + Args: + Stage:str = "Chuck" + Axis:str = "XAxis" + MotorModule:int = 0 + RegisterName:str = "" + Returns: + Value:int + Command Timeout: 5000 + Example:BnR_ReadAxisModuleRegister 1 C X 1 ConfigOutput03 + """ + rsp = MessageServerInterface.sendSciCommand("BnR_ReadAxisModuleRegister",Stage,Axis,MotorModule,RegisterName) + return int(rsp[0]) + +def ProcessStationGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns process station status (UNKNOWN, IDLE, BUSY, ERROR, PAUSED, Not + Initialized) and error code with error message when error. + API Status: internal + Returns: + Status:str + SubstratePresent:int + LastError:int + UseLoaderModule:int + WaferSizes:str + StatusMessage:str + IsLoaderJobRunning:int + Command Timeout: 25000 + Example:ProcessStationGetStatus + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetStatus") + global ProcessStationGetStatus_Response + if not "ProcessStationGetStatus_Response" in globals(): ProcessStationGetStatus_Response = namedtuple("ProcessStationGetStatus_Response", "Status,SubstratePresent,LastError,UseLoaderModule,WaferSizes,StatusMessage,IsLoaderJobRunning") + return ProcessStationGetStatus_Response(str(rsp[0]),int(rsp[1]),int(rsp[2]),int(rsp[3]),str(rsp[4]),str(rsp[5]),int(rsp[6])) + +def ProcessStationInit(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Initialize process station machine. This is not the prober init it is a fast + program initialization. Only applies to fully auto systems. + API Status: internal + Command Timeout: 2400000 + Example:ProcessStationInit + """ + MessageServerInterface.sendSciCommand("ProcessStationInit") + + +def ProcessStationFinish(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Finishes a process station process. This resets some internal test information + for the probe station. Some data is only reset in case this command is sent + after the last wafer in the job was tested. Only applies to fully auto systems. + API Status: internal + Command Timeout: 7500000 + Example:ProcessStationFinish + """ + MessageServerInterface.sendSciCommand("ProcessStationFinish") + + +def ProcessStationPrepareForLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Command moves the chuck of the probe station to the secondary load position and + if available also checks the table level sensor. Only applies to fully auto + systems. + API Status: internal + Command Timeout: 120000 + Example:ProcessStationPrepareForLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForLoad") + + +def ProcessStationLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Moves the chuck out of the load position and checks if a wafer is placed. Only + applies to fully auto systems. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadComplete") + + +def ProcessStationPrepareForUnLoad(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should do whatever is necessary to prepare the current wafer for + unload. Typically this includes things such as moving lift pins and opening + doors. + API Status: internal + Command Timeout: 1000000 + Example:ProcessStationPrepareForUnLoad + """ + MessageServerInterface.sendSciCommand("ProcessStationPrepareForUnLoad") + + +def ProcessStationUnLoadComplete(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The module should so whatever is necessary after a wafer is unloaded. This may + for example include closing doors. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationUnLoadComplete + """ + MessageServerInterface.sendSciCommand("ProcessStationUnLoadComplete") + + +def ProcessStationLoadRecipe(ForceReOpenProject:int="", ProjectFileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + The recipe is a zipped archive that includes all project data. This command + tells the device to load the recipe. + API Status: internal + Args: + ForceReOpenProject:int = 0 + ProjectFileName:str = "" + Command Timeout: 60000 + Example:ProcessStationLoadRecipe 1 SampleProject.spp + """ + MessageServerInterface.sendSciCommand("ProcessStationLoadRecipe",ForceReOpenProject,ProjectFileName) + + +def ProcessStationVerifyRecipe(ProjectFileName:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Requests that the device verify that the recipe given can be executed on the + device. It should check that the recipe is correctly formed and conforms to the + hardware of the device. It should not check for transient things such as whether + there is sufficient media or facilities available. those kinds of checks should + be done in PrepareForProcess + API Status: internal + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 60000 + Example:ProcessStationVerifyRecipe SampleProject.spp + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationVerifyRecipe",ProjectFileName) + global ProcessStationVerifyRecipe_Response + if not "ProcessStationVerifyRecipe_Response" in globals(): ProcessStationVerifyRecipe_Response = namedtuple("ProcessStationVerifyRecipe_Response", "Verified,ErrorDescription") + return ProcessStationVerifyRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def ProcessStationStartRecipe(CurrentWaferInJob:int="", TotalWafersInJob:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells VeloxPro to start the current recipe. The station will switch to error if + an error occurs. If VeloxPro recipe execution is currently paused, this command + tells the system to continue execution. + API Status: internal + Args: + CurrentWaferInJob:int = -1 + TotalWafersInJob:int = -1 + Command Timeout: 25000 + Example:ProcessStationStartRecipe 1 + """ + MessageServerInterface.sendSciCommand("ProcessStationStartRecipe",CurrentWaferInJob,TotalWafersInJob) + + +def ProcessStationStopRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the device to stop the current recipe. The station will switch to error if + an error occurs. + API Status: internal + Command Timeout: 25000 + Example:ProcessStationStopRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationStopRecipe") + + +def ProcessStationRecoverError(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Tells the module to do whatever is necessary to recover from an error condition. + API Status: internal + Command Timeout: 60000 + Example:ProcessStationRecoverError + """ + MessageServerInterface.sendSciCommand("ProcessStationRecoverError") + + +def ProcessStationGetWaferResult(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get substrate information from process station controller application. + API Status: internal + Returns: + Result:str + PercentDone:Decimal + AllowSkipWafer:int + TestInformation:str + Command Timeout: 25000 + Example:ProcessStationGetWaferResult + """ + rsp = MessageServerInterface.sendSciCommand("ProcessStationGetWaferResult") + global ProcessStationGetWaferResult_Response + if not "ProcessStationGetWaferResult_Response" in globals(): ProcessStationGetWaferResult_Response = namedtuple("ProcessStationGetWaferResult_Response", "Result,PercentDone,AllowSkipWafer,TestInformation") + return ProcessStationGetWaferResult_Response(str(rsp[0]),Decimal(rsp[1]),int(rsp[2]),str("" if len(rsp) < 4 else ' '.join(rsp[3:]))) + +def QueryWaferInfo(): + """ + Returns information about the wafer that is currently on the probe station. It + will return an error when there is no wafer currently on the chuck. + API Status: published + Returns: + Size:int + Angle:Decimal + ID:str + LotID:str + ProductID:str + Command Timeout: 25000 + Example:QueryWaferInfo + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferInfo") + global QueryWaferInfo_Response + if not "QueryWaferInfo_Response" in globals(): QueryWaferInfo_Response = namedtuple("QueryWaferInfo_Response", "Size,Angle,ID,LotID,ProductID") + return QueryWaferInfo_Response(int(rsp[0]),Decimal(rsp[1]),str(rsp[2]),str(rsp[3]),str("" if len(rsp) < 5 else ' '.join(rsp[4:]))) + +def ProcessStationPauseRecipe(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Sets the process station to PAUSE mode + API Status: internal + Command Timeout: 25000 + Example:ProcessStationPauseRecipe + """ + MessageServerInterface.sendSciCommand("ProcessStationPauseRecipe") + + +def GetProbingStatus(): + """ + Retrieves the current status of the prober. If probing status is AtFirstDie the + tester can take control. + API Status: published + Returns: + Status:str + Command Timeout: 25000 + Example:GetProbingStatus + """ + rsp = MessageServerInterface.sendSciCommand("GetProbingStatus") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedProbing(): + """ + Tells the prober to proceed the recipe when current status is AtFirstDie. + API Status: published + Command Timeout: 25000 + Example:ProceedProbing + """ + MessageServerInterface.sendSciCommand("ProceedProbing") + + +def GetCassetteStatus(Cassette:int=""): + """ + Provides all available wafer information. It returns a set of data for each + wafer in either cassette. The data contains the cassette and the slot number + where the wafer is located, the status of the wafer, and identification + information. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 25000 + Example:GetCassetteStatus 0 + """ + rsp = MessageServerInterface.sendSciCommand("GetCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def QueryWaferID(Module:str="", Slot:int=""): + """ + Queries the wafer ID of a given module and slot. + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryWaferID Cassette1 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryWaferID",Module,Slot) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def UpdateWaferID(Module:str="", Slot:int="", ID:str=""): + """ + Overrides the wafer ID of the given module and slot. If the wafer id is empty + and the module is a Loadport, the id will be read by the idreader if possible. + This process behaves as follows: - the current wafer id is reset - if the read- + wafer-process would be delayed (e.g. there is already a wafer on the idreader) + the process will be aborted and an error will be returned - if the id- + reading fails, the process behaves like a normal inventory triggered by the UI: + skip (returns success), abort (returns error) or "ask user". It is + recomended to use either skip or abort for remote id reading. If the + module is a Loadport and the slot is set to -1, a regular inventory will be + triggered. This behaves similar to an inventory triggered by the UI: The ID + won't be reset and already scanned wafers won't be reset. Setting an ID + explicitly with slot -1 is an error: - Okay, read id of wafer in slot 3 even if + it is already set: UpdateWaferID Cassette1 3 - Okay, set id of wafer in slot 3 + to XYZ123: UpdateWaferID Cassette1 3 XYZ123 - Okay, start full inventory: + UpdateWaferID Cassette1 -1 - Error: UpdateWaferID Cassette1 -1 XYZ123 + API Status: published + Args: + Module:str = "Robot" + Slot:int = 0 + ID:str = "" + Command Timeout: 1500000 + Example:UpdateWaferID Cassette1 1 Wafer01 + """ + MessageServerInterface.sendSciCommand("UpdateWaferID",Module,Slot,ID) + + +def ConfirmRecipe(ProjectFileName:str=""): + """ + Queries whether the given project/flow name is a valid project/flow at the probe + station. Using file and folder names without white spaces is recommended. For + folders and files whith white spaces use quotation marks for the path. Example + for using white spaces: ConfirmRecipe + "C:/Users/Public/Documents/Velox/Projects/White Spaces.spp" + API Status: published + Args: + ProjectFileName:str = "" + Returns: + Verified:int + ErrorDescription:str + Command Timeout: 25000 + Example:ConfirmRecipe C:/Temp/Test.spp + """ + rsp = MessageServerInterface.sendSciCommand("ConfirmRecipe",ProjectFileName) + global ConfirmRecipe_Response + if not "ConfirmRecipe_Response" in globals(): ConfirmRecipe_Response = namedtuple("ConfirmRecipe_Response", "Verified,ErrorDescription") + return ConfirmRecipe_Response(int(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def StartWaferJob(RecipeName:str="", WaferIDs:str=""): + """ + Creates and starts a new job by specifying the flow/spp file and the wafers to + be included in the job. + API Status: published + Args: + RecipeName:str = "" + WaferIDs:str = "" + Returns: + JobID:str + Command Timeout: 25000 + Example:StartWaferJob C:/Users/Public/Documents/Velox/Test.flow 1;1 2;1 + """ + rsp = MessageServerInterface.sendSciCommand("StartWaferJob",RecipeName,WaferIDs) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def GetJobParams(JobID:str=""): + """ + Get job information for a specific job ID including the flow file and the list + of wafers. + API Status: published + Args: + JobID:str = "" + Returns: + RecipeName:str + WaferIDs:str + Command Timeout: 25000 + Example:GetJobParams 1 + """ + rsp = MessageServerInterface.sendSciCommand("GetJobParams",JobID) + global GetJobParams_Response + if not "GetJobParams_Response" in globals(): GetJobParams_Response = namedtuple("GetJobParams_Response", "RecipeName,WaferIDs") + return GetJobParams_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def JobStatus(JobID:str=""): + """ + Retrieves the status of a specific job by its ID. If the status is ErrorWaiting, + an error string is returned. + API Status: published + Args: + JobID:str = "" + Returns: + Status:str + JobStatusInfo:str + Command Timeout: 25000 + Example:JobStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("JobStatus",JobID) + global JobStatus_Response + if not "JobStatus_Response" in globals(): JobStatus_Response = namedtuple("JobStatus_Response", "Status,JobStatusInfo") + return JobStatus_Response(str(rsp[0]),str("" if len(rsp) < 2 else ' '.join(rsp[1:]))) + +def AbortJob(JobID:str="", Unload:int=""): + """ + Aborts the job given by the job ID. The status of the job will be set to + "Aborted". The "Unload" parameter defines whether the wafer remains on the chuck + or not. + API Status: published + Args: + JobID:str = "" + Unload:int = 0 + Command Timeout: 25000 + Example:AbortJob 2 1 + """ + MessageServerInterface.sendSciCommand("AbortJob",JobID,Unload) + + +def ProcessStationCloseApplication(NoUserPrompt:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Closes the VeloxPro application. + API Status: internal + Args: + NoUserPrompt:int = 0 + Command Timeout: 25000 + Example:ProcessStationCloseApplication + """ + MessageServerInterface.sendSciCommand("ProcessStationCloseApplication",NoUserPrompt) + + +def UnloadWafer(): + """ + Unolads a Wafer from the chuck to its origin. If no origin is known, the first + free Slot of a loadport will be chosen. A Wafer should be on the chuck. + API Status: published + Command Timeout: 600000 + Example:UnloadWafer + """ + MessageServerInterface.sendSciCommand("UnloadWafer") + + +def GetJobList(JobType:str=""): + """ + Returns a string for the relevant JobIDs. + API Status: published + Args: + JobType:str = "Probing" + Returns: + GetJobList:str + Command Timeout: 25000 + Example:GetJobList + """ + rsp = MessageServerInterface.sendSciCommand("GetJobList",JobType) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def ProceedJob(ProceedJob:str=""): + """ + Continues a job that is waiting on an error (Job Status ErrorWaiting). The mode + determines how the job continues. + API Status: published + Args: + ProceedJob:str = "AbortJob" + Command Timeout: 25000 + Example:ProceedJob AbortJob + """ + MessageServerInterface.sendSciCommand("ProceedJob",ProceedJob) + + +def QueryCassetteID(Cassette:int=""): + """ + Returns the ID of a cassette that is placed on the load port. The loadport and + the cassette must support RFID reading (additional hardware needed). + API Status: published + Args: + Cassette:int = 1 + Returns: + ID:str + Command Timeout: 25000 + Example:QueryCassetteID 1 + """ + rsp = MessageServerInterface.sendSciCommand("QueryCassetteID",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def DockCassette(LoadPortId:int="", DockUndock:int=""): + """ + Docks or undocks a cassette which is placed on a LoadPort (CM300 only). It will + return an error if no cassette is placed: the LoadPort is not ready/available or + the docking failed. The command will do the docking/undocking and return when + this is done. + API Status: published + Args: + LoadPortId:int = 0 + DockUndock:int = 0 + Command Timeout: 60000 + Example:DockCassette 1 1 + """ + MessageServerInterface.sendSciCommand("DockCassette",LoadPortId,DockUndock) + + +def LoadWafer(LoadportID:int="", SlotID:int="", AlignmentAngle:Decimal=""): + """ + Load a wafer from a given loadport onto the prober. If no slot id is defined, + the first available wafer with the lowest slot id will be loaded. If no loadport + is defined, it will try to use the first loadport. If there is no suitable + wafer, it will try the second. Returns an error if the loading process fails or + no suitable wafer is found. To define an alignment angle and still use the + "autoselect" behaviour, use -1 for loadport and slot. + API Status: published + Args: + LoadportID:int = -1 + SlotID:int = -1 + AlignmentAngle:Decimal = 0 + Command Timeout: 600000 + Example:LoadWafer 1 1 + """ + MessageServerInterface.sendSciCommand("LoadWafer",LoadportID,SlotID,AlignmentAngle) + + +def UpdateCassetteStatus(Cassette:int=""): + """ + Updates the cassette status with a simple scan. + API Status: published + Args: + Cassette:int = 0 + Returns: + CassetteStatus:str + Command Timeout: 1200000 + Example:UpdateCassetteStatus 1 + """ + rsp = MessageServerInterface.sendSciCommand("UpdateCassetteStatus",Cassette) + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def TransportWafer(SourceLocation:str="", SourceSlot:int="", DestinationLocation:str="", DestinationSlot:int=""): + """ + Transport a wafer from one location to another. This command behaves like the + wafer-transport inside the LoaderModule. The Slot must always be set. + API Status: published + Args: + SourceLocation:str = "Cassette1" + SourceSlot:int = 1 + DestinationLocation:str = "Cassette1" + DestinationSlot:int = 1 + Command Timeout: 600000 + Example:TransportWafer Cassette1 1 PreAligner 1 + """ + MessageServerInterface.sendSciCommand("TransportWafer",SourceLocation,SourceSlot,DestinationLocation,DestinationSlot) + + +def ProcessWafer(Module:str="", ProcessParam:str=""): + """ + "Process" a wafer on a given location. What is done depends on the current + station: - IDReader: read ID - PreAligner: align wafer (alignment angle + mandatory) - Prober: Perform current recipe + API Status: published + Args: + Module:str = "Cassette1" + ProcessParam:str = "" + Command Timeout: 100000 + Example:ProcessWafer PreAligner 90.0 + """ + MessageServerInterface.sendSciCommand("ProcessWafer",Module,ProcessParam) + + +def GetIDReaderPos(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Returns the current position of the IDReader + API Status: internal + Returns: + IDReaderPos:str + Command Timeout: 2000 + """ + rsp = MessageServerInterface.sendSciCommand("GetIDReaderPos") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def SetIDReaderPos(IDReaderPos:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the current position of the IDReader + API Status: internal + Args: + IDReaderPos:str = "Bottom" + Command Timeout: 10000 + """ + MessageServerInterface.sendSciCommand("SetIDReaderPos",IDReaderPos) + + +def CryoCommand(Process:str=""): + """ + CryoCommand controls automatic cooling and warm up. + API Status: published + Args: + Process:str = "CD" + Command Timeout: 60000 + Example:CryoCommand CD + """ + MessageServerInterface.sendSciCommand("CryoCommand",Process) + + +def CryoReadTemperature(Stage:str=""): + """ + Reads the current temperature from sensor chuck or shield. + API Status: published + Args: + Stage:str = "C" + Returns: + Temp:Decimal + Command Timeout: 10000 + Example:CryoReadTemperature C + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadTemperature",Stage) + return Decimal(rsp[0]) + +def CryoSetTemperature(Stage:str="", Temp:Decimal=""): + """ + Sets temperature value for TIC chuck or shield. (Only available in process state + 'Idle' or 'Cold'.) + API Status: published + Args: + Stage:str = "C" + Temp:Decimal = 320 + Command Timeout: 10000 + Example:CryoSetTemperature C 70.5 + """ + MessageServerInterface.sendSciCommand("CryoSetTemperature",Stage,Temp) + + +def CryoStartRefill(Stage:str=""): + """ + Enables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStartRefill C + """ + MessageServerInterface.sendSciCommand("CryoStartRefill",Stage) + + +def CryoStopRefill(Stage:str=""): + """ + Disables refill. (Only available in process state 'Idle'.) + API Status: published + Args: + Stage:str = "C" + Command Timeout: 10000 + Example:CryoStopRefill C + """ + MessageServerInterface.sendSciCommand("CryoStopRefill",Stage) + + +def CryoReadState(): + """ + Reads current state. + API Status: published + Returns: + State:str + Command Timeout: 10000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadState") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def CryoMoveBBPark(): + """ + Moves the black body to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBPark") + + +def CryoMoveBBWork(NbrPosition:int=""): + """ + Moves the black body to working position. + API Status: published + Args: + NbrPosition:int = 1 + Command Timeout: 60000 + Example:CryoMoveBBWork 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveBBWork",NbrPosition) + + +def CryoMoveShutter(Position:str="", Shutter:int=""): + """ + Moves one of the two shutters. + API Status: published + Args: + Position:str = "C" + Shutter:int = 1 + Command Timeout: 60000 + Example:CryoMoveShutter F 1 + """ + MessageServerInterface.sendSciCommand("CryoMoveShutter",Position,Shutter) + + +def CryoMoveScopeWork(): + """ + Moves the microscope to working position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopeWork") + + +def CryoMoveScopePark(): + """ + Moves the microscope to parking position. + API Status: published + Command Timeout: 60000 + """ + MessageServerInterface.sendSciCommand("CryoMoveScopePark") + + +def CryoReadPressure(): + """ + Reads the current pressure of the vacuum chamber. + API Status: published + Returns: + Pressure:Decimal + Command Timeout: 60000 + """ + rsp = MessageServerInterface.sendSciCommand("CryoReadPressure") + return Decimal(rsp[0]) + +def MoveZCombined(Height:Decimal="", Percent:Decimal="", Async:int=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Move both Chuck and Scope to a new absolute z-Height. The position must be + within 0 and a predefined maximum height (e.g. 3000um). Moves are performed with + maximum velocity for now + API Status: internal + Args: + Height:Decimal = 0 + Percent:Decimal = 0 + Async:int = 0 + Command Timeout: 15000 + """ + MessageServerInterface.sendSciCommand("MoveZCombined",Height,Percent,Async) + + +def GetSoftwareStop(): + """ + Get the state of the software stop. + API Status: published + Returns: + StopState:int + Command Timeout: 1000 + """ + rsp = MessageServerInterface.sendSciCommand("GetSoftwareStop") + return int(rsp[0]) + +def MoveZCombinedSetStatus(Status:str="", Message:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Used to set the system either in off, on, error or locked state. For lock, a + key is required. To unlock this key, doe a 'SetStatus' with the same key. So, + SetStatus without message means enable/ recover from error, with message it + means unlock. If the system wasn't enabled or in error state before an unlock, + it will remain in this state after the unlock. + API Status: internal + Args: + Status:str = "Off" + Message:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("MoveZCombinedSetStatus",Status,Message) + + +def GetScopeWorkingStage(): + """ + Get the currently active ScopeWorkingStage or -1 if unknown. Normally, this + should be the same as the currently active ScopeSilo + API Status: published + Returns: + ScopeWorkingStage:int + Command Timeout: 5000 + Example:GetScopeWorkingStage + """ + rsp = MessageServerInterface.sendSciCommand("GetScopeWorkingStage") + return int(rsp[0]) + +def SetPerformanceMode(Mode:str=""): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Set the performance mode in use by remote command. If this feature is not + supported and the mode is anything but Standard, an error is returned. + API Status: internal + Args: + Mode:str = "Standard" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("SetPerformanceMode",Mode) + + +def SetScopeWorkingStage(ScopeWorkingStage:int=""): + """ + Move to the target working stage + API Status: published + Args: + ScopeWorkingStage:int = -1 + Command Timeout: 30000 + Example:SetScopeWorkingStage 1 + """ + MessageServerInterface.sendSciCommand("SetScopeWorkingStage",ScopeWorkingStage) + + +def GetPerformanceMode(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the currently configured performance mode. If this feature is not supported + on a station, Standard will be returned + API Status: internal + Returns: + Mode:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("GetPerformanceMode") + return str("" if len(rsp) < 1 else ' '.join(rsp)) + +def MoveZCombinedGetStatus(): + """ + ***WARNING: internal command. Do not use without explicit instructions from FormFactor*** + Get the current status of the combined-z-move-system + API Status: internal + Returns: + Status:str + PlatenSafe:int + Height:Decimal + HeightMax:Decimal + HeightRelative:Decimal + SafeHeight:Decimal + Message:str + Command Timeout: 5000 + """ + rsp = MessageServerInterface.sendSciCommand("MoveZCombinedGetStatus") + global MoveZCombinedGetStatus_Response + if not "MoveZCombinedGetStatus_Response" in globals(): MoveZCombinedGetStatus_Response = namedtuple("MoveZCombinedGetStatus_Response", "Status,PlatenSafe,Height,HeightMax,HeightRelative,SafeHeight,Message") + return MoveZCombinedGetStatus_Response(str(rsp[0]),int(rsp[1]),Decimal(rsp[2]),Decimal(rsp[3]),Decimal(rsp[4]),Decimal(rsp[5]),str("" if len(rsp) < 7 else ' '.join(rsp[6:]))) + +def LoadScopeFenceConfiguration(Enable:int="", Path:str=""): + """ + Load a previously saved Scope-Fence-configuration or remove the current + configuration + API Status: published + Args: + Enable:int = 0 + Path:str = "" + Command Timeout: 5000 + """ + MessageServerInterface.sendSciCommand("LoadScopeFenceConfiguration",Enable,Path) + + +def SetSoftwareStop(StopState:int=""): + """ + Set the state of the software stop. + API Status: published + Args: + StopState:int = 0 + Command Timeout: 1000 + """ + MessageServerInterface.sendSciCommand("SetSoftwareStop",StopState) + + +#End of module diff --git a/src/FlexSensor/Prober/velox_api/velox/vxmessageserver.py b/src/FlexSensor/Prober/velox_api/velox/vxmessageserver.py new file mode 100644 index 0000000000000000000000000000000000000000..9eb3e3f0872d5edf3bcbafc9b910822342739310 --- /dev/null +++ b/src/FlexSensor/Prober/velox_api/velox/vxmessageserver.py @@ -0,0 +1,186 @@ +""" +Velox Message Server Interface +To simplify calls from the SCI commands, many of the class methods are +defined as static. Some class variables are required to support a +connection to the Message Server, but the individual SCI commands +do not maintain a reference to the MessageServer object. Several +class global variables are used to maintain state. +Registration with the Message Server is handled in the __init__. +""" +import re +import socket +import sys +from collections import namedtuple +from os.path import basename + +REGISTRATION_MESSAGE_TEMPLATE = "FCN=1:RegisterProberApp:{0} {0} 0\n" +GET_ALL_COMMANDS_MESSAGE = "FCN=1:GetCommands:\n" + +class SciException(Exception): + """ Contains fields for: + code : The Error Number as a string + description : The error description + __str__, __repr__ : A formatted description of the exception """ + def __init__(self, cmd, code, description): + self.command = cmd + self.code = str(code) + self.description = description + + def __repr__(self): + return 'Error # {0} "{1}"'.format(self.code, self.description) + + def __str__(self): + return 'Error # {0} "{1}"'.format(self.code, self.description) + + +class MessageServerInterface(object): + + def __init__(self, ipaddr = 'localhost', targetSocket = 1412): + """ Initialize a socket and register with the velox message server. + Uses the python script name as the application name to register. + """ + global mySocket, myBytesReceived, myResponse, myCurrentCommand + + try: + appName = basename(sys.argv[0]) # get the script name being executed + appName = appName.replace(' ', '_') # make sure there are no spaces in the name + registrationMessage = REGISTRATION_MESSAGE_TEMPLATE.format(appName) + + myCurrentCommand = 1 + mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + mySocket.connect((ipaddr, targetSocket)) + + #register with message server + mySocket.send(registrationMessage.encode()) + myBytesReceived = 0 + myResponse = mySocket.recv(200) + except ConnectionRefusedError: + errormessage = ('Error: The connection to the Velox Message Server was refused.' + ' It probably is not running on IP [' + + str(ipaddr) + '] on Socket [' + str(targetSocket) + '].' + ' Start Velox or examine IP Address and Socket parameters.') + + raise Exception(errormessage) + pass + + def __enter__(self): + return self + pass + + def __exit__(self, type, value, traceback): + """ Close the socket connected to the message server """ + global mySocket + mySocket.close() + pass + + def _getcommands(self): + ''' Return a list of all commands known to the Velox Message Server ''' + global mySocket, myBytesReceived, myResponse + mySocket.send(GET_ALL_COMMANDS_MESSAGE.encode()) + myBytesReceived = 0 + myResponse = mySocket.recv(60000) + message = str(myResponse.decode('utf-8')) + # parse the list + commands = message.split(':')[2].split(';') + + # split the list into parsed tuples + SimpleCommandTuple = namedtuple('SimpleCommandTuple', 'section, name, number, timeout') + scilist = [] + for x in commands: + parts = x.split(' ') + scilist.append(SimpleCommandTuple(parts[0], parts[1], int(parts[2]),int(parts[3]))) + return scilist + pass + + @staticmethod + def __parseReturnValues(valueString): + """ The values come back from the SCI command as a string separated by spaces, + but with embedded strings as well. Separate the values. """ + + results = [] # the values parsed to be returned + remainingValues = valueString # holds all values still to be parsed + while remainingValues: + if remainingValues.startswith('"'): # we have a string + parts = remainingValues.split('"', 2) + parts.pop(0) + results.append(parts.pop(0).strip()) # get the string + parts.pop(0) + else: # get value separated by a space + parts = remainingValues.split(' ', 1) + results.append(parts.pop(0)) + + if len(parts) > 0: + remainingValues = parts[0].strip() # get the rest of the values + else: + remainingValues = None + + return results + pass + + @staticmethod + def __convertReturnValues(responses): + """ The responses are all strings. Use the hints from the SCI Command definition + to convert them to the proper types """ + pass + + @staticmethod + def __parseSciCommandResponse(response): + """ The response from Message Server has the form + Rsp=<ID>:<Return Code>:<Return Value> + Split the response on the : character, then split up the return values """ + + message = str(response.decode('utf-8')[:-2]) + + # we may have 0 or more values + partsCount = message.count(':')+1 + if partsCount == 2: + command, code = re.split(":", message) + values = ''; + else: + command, code, values = re.split(":", message) + values = values.strip() + + if message.startswith('Rsp='): + values = MessageServerInterface.__parseReturnValues(values) + + commandNumber = command.split('=')[1] + return int(commandNumber), int(code), values + + @staticmethod + def __sendSynchronousCommand(commandName, message=''): + global mySocket, myBytesReceived, myResponse, myCurrentCommand + + try: + myCurrentCommand += 1 # increment the commend number + if myCurrentCommand == 0 or myCurrentCommand > 999: + myCurrentCommand = 1 + messageToSend = 'Cmd={}:{}:{}\n'.format(myCurrentCommand,commandName,message) + mySocket.send(messageToSend.encode()) + myBytesReceived = 0 + myResponse = mySocket.recv(500) + + except Exception as e: + raise Exception('Unable to communicate with Velox Message Server. Start Velox. %s', e) + + cmd, code, values = MessageServerInterface.__parseSciCommandResponse(myResponse) + + # if the response code is not 0, raise an exception + if code: + parameters = ' '.join(values) + raise SciException(cmd, code, parameters) + + return values + pass + + @staticmethod + def sendSciCommand(commandName, *args, **kwargs): + """ If the parameter rparams is passed, it is the full command parameter string and should be used. + Otherwise, join the other arguments into a string separated by spaces and send that. + The rparams is used for legacy scripts converted from Pascal or Basic or other cases + where you want to send the command parameters as a single string. """ + + if 'rparams' in kwargs: # use the raw parameter string if provided + commandParameters = kwargs['rparams'] + else: # use the positional arguments and build the parameter string + commandParameters = ' '.join(str(x) for x in args) + return MessageServerInterface.__sendSynchronousCommand(commandName, commandParameters) diff --git a/src/FlexSensor/Prober/view/ProberControlWindow.py b/src/FlexSensor/Prober/view/ProberControlWindow.py new file mode 100644 index 0000000000000000000000000000000000000000..2bb990de5bd0b25cafff5f0994a6e6196b01218d --- /dev/null +++ b/src/FlexSensor/Prober/view/ProberControlWindow.py @@ -0,0 +1,66 @@ +import logging +import sys + +from PySide6.QtGui import QWindow +from PySide6.QtWidgets import QGridLayout, QApplication, QMainWindow, QWidget, QGroupBox, QVBoxLayout + +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from Prober.controller.MapFileParser import MapFileParser +from Prober.controller.ProberController import ProberController +from Prober.model.ProberModel import ProberModel +from Prober.view.widgets.DieGridWidget import DieGridWidget +from Prober.view.widgets.ProberPositionWidget import ProberPositionWidget +from Prober.view.widgets.ProberStatusWidget import ProberStatusWidget +from generics.logger import setup_logging + + +class ProberControlWindow(QMainWindow): + + def __init__(self, model: ProberModel, controller: ProberController): + super().__init__() + self.controller = controller + self.model = model + + #self.parsed_map = MapFileParser(self.controller.wafer_map) + + # Add a GridLayout to the main window + self._widget = QWidget() + self._grid_layout = QGridLayout() + # Add the DieGridWidget to the main window + # Add the prober status widget to the a group box + groupbox_status_widget = QGroupBox("Prober Status") + groupbox_status_widget_layout = QVBoxLayout() + groupbox_status_widget_layout.addWidget(ProberStatusWidget(self.model)) + groupbox_status_widget.setLayout(groupbox_status_widget_layout) + + + groupbox_position_widget = QGroupBox("Prober Status") + groupbox_position_widget_layout = QVBoxLayout() + groupbox_position_widget_layout.addWidget(ProberPositionWidget(self.model)) + groupbox_position_widget.setLayout(groupbox_position_widget_layout) + + self._grid_layout.addWidget(groupbox_status_widget, 0, 0, 1, 1) + self._grid_layout.addWidget(groupbox_position_widget, 1, 0, 1, 1) + self._grid_layout.addWidget(DieGridWidget(self.model), 0, 1, 2, 1) + # set the layout of the main window + self._widget.setLayout(self._grid_layout) + self.setCentralWidget(self._widget) + + + + +if __name__ == "__main__": + setup_logging() + logging.warning("ProberControlWindow.py is not meant to be run as a script.") + + app = QApplication() + + vaut_config = VAutomatorConfig.load_config("../configs/init_config.yaml") + + prober_model = ProberModel() + prober_controller = ProberController(prober_model, vaut_config) + main_window = ProberControlWindow(prober_controller, prober_model) + # test_win = StructureSelector() + + main_window.show() + sys.exit(app.exec()) diff --git a/src/FlexSensor/Prober/view/__init__.py b/src/FlexSensor/Prober/view/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/Prober/view/widgets/DieGridWidget.py b/src/FlexSensor/Prober/view/widgets/DieGridWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..b1e365e4dbebf20a048955440605885261ef55c4 --- /dev/null +++ b/src/FlexSensor/Prober/view/widgets/DieGridWidget.py @@ -0,0 +1,225 @@ +import pandas as pd +from PySide6.QtCore import Qt +from PySide6.QtGui import QColor, QPainter, QPen +from PySide6.QtWidgets import QWidget, QGridLayout, QPushButton, QApplication, QLabel + +from Prober.controller.MapFileParser import MapFileParser +from Prober.model.ProberModel import ProberModel + + +class FlatButton(QPushButton): + def __init__(self, text, top_left="", top_right="", bottom_left="", bottom_right="", parent=None): + super().__init__(parent, text) + + # Set flat appearance + + self.setFlat(True) + + self.color_default = QColor(192, 192, 192)#QColor(0, 58, 98) # + self.color_die_selected = QColor(49, 61, 102) + self.color_probe_active = QColor(62, 120, 52) + self.color_disabled = QColor(0, 0, 0) + self.border_color = self.color_default + + self.setStyleSheet(self.get_stylesheet(self.color_default)) + + # Set quadratic aspect ratio + self.setMaximumSize(50, 50) + self.setMinimumSize(50, 50) + self.setFixedSize(50, 50) + + self.setContentsMargins(0, 0, 0, 0) # Set margins to zero + # Create label widgets + #self.top_left_label = QLabel(top_left, parent=self) + self.top_right_label = QLabel(top_right, parent=self) + self.bottom_left_label = QLabel(bottom_left, parent=self) + self.bottom_right_label = QLabel(bottom_right, parent=self) + + # Set label positions + #self.top_left_label.setAlignment(Qt.AlignTop | Qt.AlignLeft) + self.top_right_label.setAlignment(Qt.AlignTop | Qt.AlignRight) + self.bottom_left_label.setAlignment(Qt.AlignBottom | Qt.AlignLeft) + self.bottom_right_label.setAlignment(Qt.AlignBottom | Qt.AlignRight) + + # Border colo + + + # Border flag + self.draw_border = False + # Border width + self.border_width = 3 + + def get_stylesheet(self, qcolor): + return f"background-color: rgb({qcolor.red()}, {qcolor.green()}, {qcolor.blue()});" + def setTopLeftLabel(self, text): + self.top_left_label.setText(text) + + def setTopRightLabel(self, text): + self.top_right_label.setText(text) + + def setBottomLeftLabel(self, text): + self.bottom_left_label.setText(text) + + def setBottomRightLabel(self, text): + self.bottom_right_label.setText(text) + + def setEnabled(self, arg__1: bool) -> None: + super().setEnabled(arg__1) + if not arg__1: + self.setStyleSheet(self.get_stylesheet(self.color_disabled)) + self.border_color = self.color_disabled # Black + self.update() + + def set_die_selected(self, checked: bool) -> None: + if not self.isEnabled(): + return + + if checked: + self.setStyleSheet(self.get_stylesheet(self.color_die_selected)) + self.border_color = self.color_die_selected + else: + self.setStyleSheet(self.get_stylesheet(self.color_default)) + self.border_color = self.color_default + self.update() + + def set_probe_active(self, active: bool) -> None: + if not self.isEnabled(): + return + + if active: + #self.setStyleSheet(self.get_stylesheet(self.color_default)) + self.border_color = self.color_probe_active + else: + #self.setStyleSheet(self.get_stylesheet(self.color_default)) + self.border_color = self.color_default + self.update() + + def paintEvent(self, event): + super().paintEvent(event) + + #if self.draw_border: + painter = QPainter(self) + pen = QPen(self.border_color, self.border_width) + painter.setPen(pen) + painter.setBrush(Qt.NoBrush) + painter.drawRect( + self.border_width // 2, + self.border_width // 2, + self.width() - self.border_width, + self.height() - self.border_width + ) + + def resizeEvent(self, event): + super().resizeEvent(event) + + # Calculate label sizes based on button size + button_size = self.size() + border_offset = self.border_width // 2 + label_width = (button_size.width() - self.border_width) + label_height = (button_size.height()) // 2 + + # Set label sizes and positions + + + self.top_right_label.setGeometry(self.border_width, self.border_width, + label_width-self.border_width, label_height) + + self.bottom_left_label.setGeometry(self.border_width, label_height - self.border_width, + label_width//2, label_height) + + self.bottom_right_label.setGeometry(label_width//2, label_height - self.border_width, + label_width//2+1, label_height) + + + +class DieGridWidget(QWidget): + def __init__(self, model: ProberModel): + super(DieGridWidget, self).__init__() + self._model = model + + parsed_map = MapFileParser(str(self._model.wafer_map)) + self.setWindowTitle("Die Grid Widget") + self._dies = {} + + self.grid_layout = QGridLayout() + self.grid_layout.setSpacing(0) + self.grid_layout.setHorizontalSpacing(0) + self.grid_layout.setVerticalSpacing(0) + #self.grid_layout.setContentsMargins(0, 0, 0, 0) # Set margins to zero + + self.setLayout(self.grid_layout) + + self._die = parsed_map.result['Die'] + + self._prof_dies = parsed_map.result['ProfDies'] + self.create_die_grid() + self.setFixedSize(9*60, 9*60) + + + self._model.signals.die_changed.connect(self.update_die_grid) + + self.update_die_grid(self._model.die) + + def create_die_grid(self): + table = pd.DataFrame([[int(die), *self._die[die].split(",")] for die in self._die], + columns=['die_number', 'col', 'row', 'status']) + table['col'] = table['col'].astype(int) + table['row'] = table['row'].astype(int) + table['status'] = table['status'].astype(str) + + table['col_os'] = table.apply([lambda row: row['col'] - table['col'].min()], axis=1) + table['row_os'] = table.apply([lambda row: row['row'] - table['row'].min()], axis=1) + + + #print(table) + # pd.DataFrame([die.split(",").strip for die in die_info], columns=['col', 'row', 'status']) + for entry in self._prof_dies: + col, row, value = self._prof_dies[entry].split(",") + df = table.loc[(table['col'] == int(col)) & (table['row'] == int(row))] + if df.empty: + continue + else: + table.loc[(table['col'] == int(col)) & (table['row'] == int(row)), 'prof_die_number'] = entry + + + for index, die in table.iterrows(): + button = FlatButton("1", "2", f"{die['col']}, {die['row']}", str(die['die_number']), str(die['status']))#, + if die['status'] == "X": + button.setEnabled(False) + elif die['status'] == "V": + button.set_die_selected(False) + elif die['status'] == "P": + button.set_die_selected(True) + #button.setText(f"{die['col']}, {die['row']} - {die['die_number']}") + self._dies[f"{die['row']}, {die['col']}"] = button + + button.clicked.connect(self.on_button_clicked) + + self.grid_layout.addWidget(button, die['col_os'], die['row_os']) + + #print(table) + + def on_button_clicked(self): + button: FlatButton = self.sender() + button.set_probe_active(True) + + def update_die_grid(self, die): + for die in self._dies: + self._dies[die].set_probe_active(False) + + die_x = self._model.die_row + die_y = self._model.die_col + print(f"Die {die}: {die_x}, {die_y} was probed") + #print(self._dies) + self._dies[f"{die_x}, {die_y}"].set_probe_active(True) + + +if __name__ == "__main__": + app = QApplication([]) + + parsed_map = MapFileParser("../Wafermapary1_48dies.map") + + widget = DieGridWidget(parsed_map) + widget.show() + + app.exec_() \ No newline at end of file diff --git a/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py b/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..9db1dfde64d455f62e7574d9407525a5099f26e9 --- /dev/null +++ b/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py @@ -0,0 +1,105 @@ +from PySide6.QtWidgets import QWidget, QGroupBox, QGridLayout, QLabel, QProgressBar + +from Prober.model.ProberModel import ProberModel + + +class ProberPositionWidget(QWidget): + + def __init__(self, model: ProberModel, chuck_position="Vertical"): + super().__init__() + self.model = model + self.layout = QGridLayout() + self.chuck_position = chuck_position + + self.lbl_chuck_x = QLabel() + self.lbl_chuck_y = QLabel() + self.lbl_chuck_z = QLabel() + + self.lbl_die_no = QLabel() + self.lbl_structure = QLabel() + self.lbl_die_col = QLabel() + self.lbl_die_row = QLabel() + + self.lbl_die_no.setText(str(self.model.die)) + self.lbl_structure.setText("<b>Stopped</b>") + self.lbl_die_col.setText(str(self.model.die_col)) + self.lbl_die_row.setText(str(self.model.die_row)) + self.lbl_chuck_x.setText(str(self.model.chuck_x)) + self.lbl_chuck_y.setText(str(self.model.chuck_y)) + self.lbl_chuck_z.setText(str(self.model.chuck_z)) + + # self.progress = QProgressBar(self) + # self.progress.setStyleSheet( + # "#GreenProgressBar { min-height: 12px; max-height: 12px; border-radius: 6px;}") + # self.layout.addWidget(self.progress, 2, 0, 1, 4) + # self.progress.setFixedHeight(self.progress.sizeHint().height() / 2) + + self._init_ui_wafer_position() + self._init_ui_chuck_position() + self.setLayout(self.layout) + + self.model.signals.chuck_x_changed.connect(self._on_chuck_x_changed) + self.model.signals.chuck_y_changed.connect(self._on_chuck_y_changed) + self.model.signals.chuck_z_changed.connect(self._on_chuck_z_changed) + self.model.signals.die_changed.connect(self._on_die_no_changed) + #self.model.signals.st.connect(self._on_structure_changed) + self.model.signals.curr_die_col_changed.connect(self._on_die_col_changed) + self.model.signals.curr_die_row_changed.connect(self._on_die_row_changed) + + + def _init_ui_wafer_position(self): + self.layout.addWidget(QLabel("Die No:"), 0, 0) + self.layout.addWidget(self.lbl_die_no, 0, 1) + + self.layout.addWidget(QLabel("Structure"), 0, 2) + self.layout.addWidget(self.lbl_structure, 0, 3) + + self.layout.addWidget(QLabel("Die col:"), 1, 0) + self.layout.addWidget(self.lbl_die_col, 1, 1) + + self.layout.addWidget(QLabel("Die row:"), 1, 2) + self.layout.addWidget(self.lbl_die_row, 1, 3) + + def _init_ui_chuck_position(self): + if self.chuck_position == "Vertical": + self.layout.addWidget(QLabel("X"), 2, 0) + self.layout.addWidget(self.lbl_chuck_x, 2, 1) + + self.layout.addWidget(QLabel("Y"), 3, 0) + self.layout.addWidget(self.lbl_chuck_y, 3, 1) + + self.layout.addWidget(QLabel("Z"), 4, 0) + self.layout.addWidget(self.lbl_chuck_z, 4, 1) + + elif self.chuck_position == "Horizontal": + self.layout.addWidget(QLabel("X"), 2, 0) + self.layout.addWidget(self.lbl_chuck_x, 2, 1) + + self.layout.addWidget(QLabel("Y"), 2, 2) + self.layout.addWidget(self.lbl_chuck_y, 2, 3) + + self.layout.addWidget(QLabel("Z"), 2, 4) + self.layout.addWidget(self.lbl_chuck_z, 2, 5) + + + def _on_chuck_x_changed(self, value: int): + self.lbl_chuck_x.setText(str(value)) + + def _on_chuck_y_changed(self, value: int): + self.lbl_chuck_y.setText(str(value)) + + def _on_chuck_z_changed(self, value: int): + self.lbl_chuck_z.setText(str(value)) + + def _on_die_no_changed(self, value: int): + self.lbl_die_no.setText(str(value)) + + def _on_structure_changed(self, value: int): + self.lbl_structure.setText(str(value)) + + def _on_die_col_changed(self, value: int): + self.lbl_die_col.setText(str(value)) + + def _on_die_row_changed(self, value: int): + self.lbl_die_row.setText(str(value)) + diff --git a/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py b/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py new file mode 100644 index 0000000000000000000000000000000000000000..00e2073375bd698281f6887da38514385df74376 --- /dev/null +++ b/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py @@ -0,0 +1,74 @@ +from PySide6.QtCore import Qt +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QWidget, QLabel, QGridLayout, QStyle, QFrame, QProgressBar, QGroupBox + +from Prober.model.ProberModel import ProberModel + + +class ProberStatusWidget(QWidget): + + def __init__(self, model: ProberModel): + super().__init__() + self.setFixedSize(300, 200) + self.model = model + self._grid_layout = QGridLayout() + self.prober_status = self._add_status(self._get_std_icon("SP_ComputerIcon"), "", 0) + self.version_status = self._add_status(self._get_std_icon("SP_MessageBoxInformation"), str(self.model.version), 1) + self._add_line(2) + self.errors = self._add_status(self._get_std_icon("SP_MessageBoxCritical"), "0", 3) + self.warnings = self._add_status(self._get_std_icon("SP_MessageBoxWarning"), "0", 4) + + self._on_connected_changed(self.model.connected) + + self.model.signals.connected_changed.connect(self._on_connected_changed) + self.model.signals.version_changed.connect(self._on_version_changed) + self.model.signals.errors_changed.connect(self._on_errors_changed) + self.model.signals.warnings_changed.connect(self._on_warnings_changed) + + + self.setLayout(self._grid_layout) + + + def _get_std_icon(self, icon_name) -> QIcon: + return self.style().standardIcon(getattr(QStyle, icon_name)) + + def _add_status(self, icon, text, pos=0): + icon_label = QLabel() + icon_label.setPixmap(icon.pixmap(50, 50)) + icon_label.setAlignment(Qt.AlignCenter) + icon_label.setContentsMargins(0, 0, 0, 0) + # icon_label.setStyleSheet("background-color: rgb(192, 192, 192);") + icon_label.setFixedSize(24, 24) + icon_label.setScaledContents(True) + + text_label = QLabel(text) + #text_label.setAlignment(Qt.AlignCenter) + #text_label.setContentsMargins(0, 0, 0, 0) + # text_label.setStyleSheet("background-color: rgb(192, 192, 192);") + # text_label.setFixedSize(32, 50) + #text_label.setScaledContents(True) + + self._grid_layout.addWidget(icon_label, pos, 0) + self._grid_layout.addWidget(text_label, pos, 1) + return text_label + + def _add_line(self, pos=0): + line = QFrame() + line.setFrameShape(QFrame.HLine) + line.setFrameShadow(QFrame.Sunken) + self._grid_layout.addWidget(line, pos, 0, 1, 2) + + def _on_connected_changed(self, connected): + if connected: + self.prober_status.setText("Connected") + else: + self.prober_status.setText("Disconnected") + + def _on_version_changed(self, version): + self.version_status.setText(version) + + def _on_errors_changed(self, errors): + self.errors.setText(str(len(errors))) + + def _on_warnings_changed(self, warnings): + self.warnings.setText(str(len(warnings))) \ No newline at end of file diff --git a/src/FlexSensor/__init__.py b/src/FlexSensor/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..81dab0e1c8728d9d20fda311be5ccfd69e7324e7 --- /dev/null +++ b/src/FlexSensor/__init__.py @@ -0,0 +1,7 @@ +import os +import pathlib +import sys + +from flexsensorpy.__version__ import __version__ + +__all__ = [] diff --git a/src/FlexSensor/__version__.py b/src/FlexSensor/__version__.py new file mode 100644 index 0000000000000000000000000000000000000000..36b6d4f16487f4a4b4b68a1913dedc60d22080d3 --- /dev/null +++ b/src/FlexSensor/__version__.py @@ -0,0 +1,2 @@ +__version__ = "6.0.0 beta" +__changelog__ = "New UI Version and better measurement routine implemented." \ No newline at end of file diff --git a/src/FlexSensor/constants/Enumerate.py b/src/FlexSensor/constants/Enumerate.py new file mode 100644 index 0000000000000000000000000000000000000000..08721dce289f2ba27e2647add2dd9e3294e5ba57 --- /dev/null +++ b/src/FlexSensor/constants/Enumerate.py @@ -0,0 +1,119 @@ +""" + DWF Python Example + Author: Digilent, Inc. + Revision: 2019-07-24 + + Requires: + Python 2.7, 3 + Description: + Device detection troubleshooting. +""" + +from ctypes import * +import sys +import time + +if sys.platform.startswith("win"): + dwf = cdll.dwf + dmgr = cdll.dmgr + ftd = windll.ftd2xx +elif sys.platform.startswith("darwin"): + dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf") + dmgr = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libdmgr.dylib") + ftd = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libftd2xx.dylib") + dftd = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/Frameworks/libdftd2xx.dylib") +else: + dwf = cdll.LoadLibrary("libdwf.so") + dmgr = cdll.LoadLibrary("libdmgr.so") + ftd = cdll.LoadLibrary("libftd2xx.so") + +version = create_string_buffer(32) +cDev = c_int(); +dvc = (c_char*1024)() +pdid = c_int() +flags = c_int() +locid = c_int() +type = c_int() + +name = create_string_buffer(64) +sn = create_string_buffer(64) + +if sys.platform.startswith("darwin"): + print("") + if dftd.DFT_Init() == 0 : + print("DFT_INIT failed") + quit() + + print("Digilent FTDI Enumeration library loaded") + + if dftd.DFT_CreateDeviceInfoList(byref(cDev)) != 0 : + print("DFT_CreateDeviceInfoList failed") + dftd.DFT_Term() + quit() + + print("Devices: "+str(cDev.value)) + + for i in range(0, cDev.value): + if dftd.DFT_GetDeviceInfoDetail(c_int(i), byref(flags), byref(type), byref(pdid), byref(locid), sn, name, None) != 0 : + print("Failed DFT_GetDeviceInfoDetail") + dftd.DFT_Term() + quit() + print(" "+str(i+1)+". SN:"+str(sn.value)+" '"+str(name.value)+"'"+" flags: "+hex(flags.value)+" type: "+hex(type.value)+" id: "+hex(pdid.value)+" locid: "+hex(locid.value)) + + +print("") +ftd.FT_GetLibraryVersion(byref(pdid)) +print("FTDI Version: "+hex(pdid.value)) + +if ftd.FT_CreateDeviceInfoList(byref(cDev)) != 0 : + print("FT_CreateDeviceInfoList failed") + quit() + +print("Devices: "+str(cDev.value)) + +for i in range(cDev.value): + if ftd.FT_GetDeviceInfoDetail(c_int(i), byref(flags), byref(type), byref(pdid), byref(locid), sn, name, None) != 0 : + print("Failed FT_GetDeviceInfoDetail") + print(" "+str(i+1)+". SN:"+str(sn.value)+" "+str(name.value)+""+" flags: "+hex(flags.value)+" type: "+hex(type.value)+" id: "+hex(pdid.value)+" locid: "+hex(locid.value)) + + +print("") +dmgr.DmgrGetVersion(version) +print("DMGR Version: "+str(version.value)) + +if dmgr.DmgrEnumDevices(byref(cDev)) == 0 : + print("DmgrEnumDevices failed") + quit() + +print("Devices: "+str(cDev.value)) + +for i in range(cDev.value): + dmgr.DmgrGetDvc(c_int(i), dvc); + + if dmgr.DmgrGetInfo(dvc, 3, name) == 0 : #dinfoProdName + print("Failed DmgrGetInfo dinfoProdName") + if dmgr.DmgrGetInfo(dvc, 4, byref(pdid)) == 0 : #dinfoPDID + print("Failed DmgrGetInfo dinfoPDID") + if dmgr.DmgrGetInfo(dvc, 5, sn) == 0 : #dinfoSN + print("Failed DmgrGetInfo dinfoSN") + print(" "+str(i+1)+". "+str(sn.value)+" "+str(name.value)+""+" PDID: "+hex(pdid.value)) + + +print("") +dwf.FDwfGetVersion(version) +print("DWF Version: "+str(version.value)) + +if dwf.FDwfEnum(c_int(0), byref(cDev)) == 0 : + print("DmgrEnumDevices failed") + quit() + +print("Devices: "+str(cDev.value)) + +for i in range(cDev.value): + dwf.FDwfEnumDeviceName(c_int(i), name) + dwf.FDwfEnumSN(c_int(i), sn) + print(" "+str(i+1)+". "+str(sn.value)+" "+str(name.value)+"") + +dmgr.DmgrFreeDvcEnum() +if sys.platform.startswith("darwin"): + dftd.DFT_Term() \ No newline at end of file diff --git a/src/FlexSensor/constants/FlexsensorConstants.py b/src/FlexSensor/constants/FlexsensorConstants.py new file mode 100644 index 0000000000000000000000000000000000000000..37913cb0695cc5479cd7e98967eb5386e46743e0 --- /dev/null +++ b/src/FlexSensor/constants/FlexsensorConstants.py @@ -0,0 +1,3 @@ +class Probe: + INPUT = 0 + OUTPUT = 1 diff --git a/src/FlexSensor/constants/__init__.py b/src/FlexSensor/constants/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/constants/css_stylesheet.py b/src/FlexSensor/constants/css_stylesheet.py new file mode 100644 index 0000000000000000000000000000000000000000..75924a64c8211e5cfb5d822bb65471ca8092c0ae --- /dev/null +++ b/src/FlexSensor/constants/css_stylesheet.py @@ -0,0 +1,44 @@ +styleData=""" +QWidget +{ + color: #b1b1b1; + background-color: #323232; +} +QWidget:disabled +{ + border-color: #404040; + background-color: #323232; +} +QProgressBar +{ + border: 2px solid grey; + border-radius: 5px; + text-align: center; +} +QProgressBar::chunk +{ + background-color: #d7801a; + width: 2.15px; + margin: 0.5px; +} +QPushButton:pressed +{ + background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525); +} +QComboBox:hover,QPushButton:hover +{ + border: 2px solid QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffa02f, stop: 1 #d7801a); +} +QPushButton +{ + color: #b1b1b1; + background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646); + border-width: 1px; + border-color: #1e1e1e; + border-style: solid; + border-radius: 6; + padding: 3px; + font-size: 12px; + padding-left: 5px; + padding-right: 5px; +}""" \ No newline at end of file diff --git a/src/FlexSensor/constants/dwfconstants.py b/src/FlexSensor/constants/dwfconstants.py new file mode 100644 index 0000000000000000000000000000000000000000..b7b445e1a4ae7056f6a09354164915c5def3572b --- /dev/null +++ b/src/FlexSensor/constants/dwfconstants.py @@ -0,0 +1,252 @@ +""" + DWFConstants (definitions file for DWF library) + Author: Digilent, Inc. + Revision: 2019-10-15 + + Must install: + Python 2.7 or 3 +""" + + +from ctypes import * + +# device handle +#HDWF +hdwfNone = c_int(0) + +# device enumeration filters +enumfilterAll = c_int(0) + +enumfilterType = c_int(0x8000000) +enumfilterUSB = c_int(0x0000001) +enumfilterNetwork = c_int(0x0000002) +enumfilterAXI = c_int(0x0000004) +enumfilterRemote = c_int(0x1000000) +enumfilterAudio = c_int(0x2000000) +enumfilterDemo = c_int(0x4000000) + +# device ID +devidEExplorer = c_int(1) +devidDiscovery = c_int(2) +devidDiscovery2 = c_int(3) +devidDDiscovery = c_int(4) +devidADP3X50 = c_int(6) + +# device version +devverEExplorerC = c_int(2) +devverEExplorerE = c_int(4) +devverEExplorerF = c_int(5) +devverDiscoveryA = c_int(1) +devverDiscoveryB = c_int(2) +devverDiscoveryC = c_int(3) + +# trigger source +trigsrcNone = c_ubyte(0) +trigsrcPC = c_ubyte(1) +trigsrcDetectorAnalogIn = c_ubyte(2) +trigsrcDetectorDigitalIn = c_ubyte(3) +trigsrcAnalogIn = c_ubyte(4) +trigsrcDigitalIn = c_ubyte(5) +trigsrcDigitalOut = c_ubyte(6) +trigsrcAnalogOut1 = c_ubyte(7) +trigsrcAnalogOut2 = c_ubyte(8) +trigsrcAnalogOut3 = c_ubyte(9) +trigsrcAnalogOut4 = c_ubyte(10) +trigsrcExternal1 = c_ubyte(11) +trigsrcExternal2 = c_ubyte(12) +trigsrcExternal3 = c_ubyte(13) +trigsrcExternal4 = c_ubyte(14) +trigsrcHigh = c_ubyte(15) +trigsrcLow = c_ubyte(16) +trigsrcClock = c_ubyte(17) + +# instrument states +DwfStateReady = c_ubyte(0) +DwfStateConfig = c_ubyte(4) +DwfStatePrefill = c_ubyte(5) +DwfStateArmed = c_ubyte(1) +DwfStateWait = c_ubyte(7) +DwfStateTriggered = c_ubyte(3) +DwfStateRunning = c_ubyte(3) +DwfStateDone = c_ubyte(2) + +# DwfEnumConfigInfo +DECIAnalogInChannelCount = c_int(1) +DECIAnalogOutChannelCount = c_int(2) +DECIAnalogIOChannelCount = c_int(3) +DECIDigitalInChannelCount = c_int(4) +DECIDigitalOutChannelCount = c_int(5) +DECIDigitalIOChannelCount = c_int(6) +DECIAnalogInBufferSize = c_int(7) +DECIAnalogOutBufferSize = c_int(8) +DECIDigitalInBufferSize = c_int(9) +DECIDigitalOutBufferSize = c_int(10) + +# acquisition modes: +acqmodeSingle = c_int(0) +acqmodeScanShift = c_int(1) +acqmodeScanScreen = c_int(2) +acqmodeRecord = c_int(3) +acqmodeOvers = c_int(4) +acqmodeSingle1 = c_int(5) + +# analog acquisition filter: +filterDecimate = c_int(0) +filterAverage = c_int(1) +filterMinMax = c_int(2) + +# analog in trigger mode: +trigtypeEdge = c_int(0) +trigtypePulse = c_int(1) +trigtypeTransition = c_int(2) +trigtypeWindow = c_int(3) + +# trigger slope: +DwfTriggerSlopeRise = c_int(0) +DwfTriggerSlopeFall = c_int(1) +DwfTriggerSlopeEither = c_int(2) + +# trigger length condition +triglenLess = c_int(0) +triglenTimeout = c_int(1) +triglenMore = c_int(2) + +# error codes for the functions: +dwfercNoErc = c_int(0) # No error occurred +dwfercUnknownError = c_int(1) # API waiting on pending API timed out +dwfercApiLockTimeout = c_int(2) # API waiting on pending API timed out +dwfercAlreadyOpened = c_int(3) # Device already opened +dwfercNotSupported = c_int(4) # Device not supported +dwfercInvalidParameter0 = c_int(16) # Invalid parameter sent in API call +dwfercInvalidParameter1 = c_int(17) # Invalid parameter sent in API call +dwfercInvalidParameter2 = c_int(18) # Invalid parameter sent in API call +dwfercInvalidParameter3 = c_int(19) # Invalid parameter sent in API call +dwfercInvalidParameter4 = c_int(20) # Invalid parameter sent in API call + +# analog out signal types +funcDC = c_ubyte(0) +funcSine = c_ubyte(1) +funcSquare = c_ubyte(2) +funcTriangle = c_ubyte(3) +funcRampUp = c_ubyte(4) +funcRampDown = c_ubyte(5) +funcNoise = c_ubyte(6) +funcPulse = c_ubyte(7) +funcTrapezium= c_ubyte(8) +funcSinePower= c_ubyte(9) +funcCustom = c_ubyte(30) +funcPlay = c_ubyte(31) + +# analog io channel node types +analogioEnable = c_ubyte(1) +analogioVoltage = c_ubyte(2) +analogioCurrent = c_ubyte(3) +analogioPower = c_ubyte(4) +analogioTemperature = c_ubyte(5) +analogioDmm = c_ubyte(6) +analogioRange = c_ubyte(7) +analogioMeasure = c_ubyte(8) +analogioTime = c_ubyte(9) +analogioFrequency = c_ubyte(10) +analogioResistance = c_ubyte(11) + +DwfDmmResistance = c_double(1) +DwfDmmContinuity = c_double(2) +DwfDmmDiode = c_double(3) +DwfDmmDCVoltage = c_double(4) +DwfDmmACVoltage = c_double(5) +DwfDmmDCCurrent = c_double(6) +DwfDmmACCurrent = c_double(7) +DwfDmmDCLowCurrent = c_double(8) +DwfDmmACLowCurrent = c_double(9) +DwfDmmTemperature = c_double(10) + +AnalogOutNodeCarrier = c_int(0) +AnalogOutNodeFM = c_int(1) +AnalogOutNodeAM = c_int(2) + +DwfAnalogOutIdleDisable = c_int(0) +DwfAnalogOutIdleOffset = c_int(1) +DwfAnalogOutIdleInitial = c_int(2) + +DwfDigitalInClockSourceInternal = c_int(0) +DwfDigitalInClockSourceExternal = c_int(1) + +DwfDigitalInSampleModeSimple = c_int(0) +# alternate samples: noise|sample|noise|sample|... +# where noise is more than 1 transition between 2 samples +DwfDigitalInSampleModeNoise = c_int(1) + +DwfDigitalOutOutputPushPull = c_int(0) +DwfDigitalOutOutputOpenDrain = c_int(1) +DwfDigitalOutOutputOpenSource = c_int(2) +DwfDigitalOutOutputThreeState = c_int(3) + +DwfDigitalOutTypePulse = c_int(0) +DwfDigitalOutTypeCustom = c_int(1) +DwfDigitalOutTypeRandom = c_int(2) +DwfDigitalOutTypeROM = c_int(3) +DwfDigitalOutTypeState = c_int(4) +DwfDigitalOutTypePlay = c_int(5) + +DwfDigitalOutIdleInit = c_int(0) +DwfDigitalOutIdleLow = c_int(1) +DwfDigitalOutIdleHigh = c_int(2) +DwfDigitalOutIdleZet = c_int(3) + +DwfAnalogImpedanceImpedance = c_int(0) +DwfAnalogImpedanceImpedancePhase = c_int(1) +DwfAnalogImpedanceResistance = c_int(2) +DwfAnalogImpedanceReactance = c_int(3) +DwfAnalogImpedanceAdmittance = c_int(4) +DwfAnalogImpedanceAdmittancePhase = c_int(5) +DwfAnalogImpedanceConductance = c_int(6) +DwfAnalogImpedanceSusceptance = c_int(7) +DwfAnalogImpedanceSeriesCapacitance = c_int(8) +DwfAnalogImpedanceParallelCapacitance = c_int(9) +DwfAnalogImpedanceSeriesInductance = c_int(10) +DwfAnalogImpedanceParallelInductance = c_int(11) +DwfAnalogImpedanceDissipation = c_int(12) +DwfAnalogImpedanceQuality = c_int(13) +DwfAnalogImpedanceVrms = c_int(14) +DwfAnalogImpedanceVreal = c_int(15) +DwfAnalogImpedanceVimag = c_int(16) +DwfAnalogImpedanceIrms = c_int(17) +DwfAnalogImpedanceIreal = c_int(18) +DwfAnalogImpedanceIimag = c_int(19) + +DwfParamUsbPower = c_int(2) # 1 keep the USB power enabled even when AUX is connected, Analog Discovery 2 +DwfParamLedBrightness = c_int(3) # LED brightness 0 ... 100%, Digital Discovery +DwfParamOnClose = c_int(4) # 0 continue, 1 stop, 2 shutdown +DwfParamAudioOut = c_int(5) # 0 disable / 1 enable audio output, Analog Discovery 1, 2 +DwfParamUsbLimit = c_int(6) # 0..1000 mA USB power limit, -1 no limit, Analog Discovery 1, 2 +DwfParamAnalogOut = c_int(7) # 0 disable / 1 enable +DwfParamFrequency = c_int(8) # Hz +DwfParamExtFreq = c_int(9) # Hz +DwfParamClockMode = c_int(10) # 0 internal, 1 output, 2 input, 3 IO + +# obsolate +#STS +stsRdy = c_ubyte(0) +stsArm = c_ubyte(1) +stsDone = c_ubyte(2) +stsTrig = c_ubyte(3) +stsCfg = c_ubyte(4) +stsPrefill = c_ubyte(5) +stsNotDone = c_ubyte(6) +stsTrigDly = c_ubyte(7) +stsError = c_ubyte(8) +stsBusy = c_ubyte(9) +stsStop = c_ubyte(10) + +#TRIGCOND +trigcondRisingPositive = c_int(0) +trigcondFallingNegative = c_int(1) + +#use deiceid +enumfilterEExplorer = c_int(1) +enumfilterDiscovery = c_int(2) +enumfilterDiscovery2 = c_int(3) +enumfilterDDiscovery = c_int(4) + + diff --git a/src/FlexSensor/constants/qs_style_sheets.py b/src/FlexSensor/constants/qs_style_sheets.py new file mode 100644 index 0000000000000000000000000000000000000000..cd361c799927e8c976f0cec6c14dbc3562c54b25 --- /dev/null +++ b/src/FlexSensor/constants/qs_style_sheets.py @@ -0,0 +1,91 @@ +class CSSPlayPushButton: + @staticmethod + def style_play(): + return """ + QPushButton { + background-color: rgb(36, 209, 21); + background-position: left center; + background-repeat: no-repeat; + border: none; + border-radius: 0px; + border-left: 22px solid transparent; + text-align: left; + padding-left: 44px; + background-image: url(:/icons/images/icons/cil-media-play.png); + } + + QPushButton:hover { + background-color: rgb(26, 153, 16); + } + + QPushButton:pressed { + background-color: rgb(20, 120, 12); + color: rgb(255, 255, 255); + } + + QPushButton:disabled { + background-color: rgb(153, 153, 153); + color: rgb(255, 255, 255); + } + + """ + + @staticmethod + def style_pause(): + return """ + QPushButton { + background-color: rgb(255, 200,11); + background-position: left center; + background-repeat: no-repeat; + border: none; + border-radius: 0px; + border-left: 22px solid transparent; + text-align: left; + padding-left: 44px; + background-image: url(:/icons/images/icons/cil-media-pause.png) + } + + QPushButton:hover { + background-color: rgb(255, 182, 44); + } + + QPushButton:pressed { + background-color: rgb(255, 146, 12); + color: rgb(255, 255, 255); + } + + QPushButton:disabled { + background-color: rgb(153, 153, 153); + color: rgb(255, 255, 255); + } + """ + + @staticmethod + def style_stop(): + return """ + QPushButton { + background-color: rgb(242, 41, 41); + background-position: left center; + background-repeat: no-repeat; + border: none; + border-radius: 0px; + border-left: 22px solid transparent; + text-align: left; + padding-left: 44px; + background-image: url(:/icons/images/icons/cil-media-stop.png) + } + + QPushButton:hover { + background-color: rgb(235, 64, 52); + } + + QPushButton:pressed { + background-color: rgb(201, 17, 4); + color: rgb(255, 255, 255); + } + + QPushButton:disabled { + background-color: rgb(153, 153, 153); + color: rgb(255, 255, 255); + } + """ diff --git a/src/FlexSensor/generics/ConsoleWindow.py b/src/FlexSensor/generics/ConsoleWindow.py new file mode 100644 index 0000000000000000000000000000000000000000..b60abbcddd6cd4ccb81ff3de6a3eac48c20e29ed --- /dev/null +++ b/src/FlexSensor/generics/ConsoleWindow.py @@ -0,0 +1,201 @@ +import logging +import random +import time +import os + +from PySide6.QtCore import QObject, QThread, Signal, Slot +from PySide6.QtGui import QFont, Qt +from PySide6.QtWidgets import QWidget, QPlainTextEdit, QPushButton, QVBoxLayout + +#Signal = Signal +#Slot = Slot +logger = logging.getLogger(__name__) + + +# +# Signals need to be contained in a QObject or subclass in order to be correctly +# initialized. +# +class Signaller(QObject): + signal = Signal(str, logging.LogRecord) + +# +# Output to a Qt GUI is only supposed to happen on the main thread. So, this +# handler is designed to take a slot function which is set up to run in the main +# thread. In this example, the function takes a string argument which is a +# formatted log message, and the log record which generated it. The formatted +# string is just a convenience - you could format a string for output any way +# you like in the slot function itself. +# +# You specify the slot function to do whatever GUI updates you want. The handler +# doesn't know or care about specific UI elements. +# + + +class QtHandler(logging.Handler): + def __init__(self, slotfunc, *args, **kwargs): + super(QtHandler, self).__init__(*args, **kwargs) + self.signaller = Signaller() + self.signaller.signal.connect(slotfunc) + + def emit(self, record): + s = self.format(record) + self.signaller.signal.emit(s, record) + +# +# This example uses QThreads, which means that the threads at the Python level +# are named something like "Dummy-1". The function below gets the Qt name of the +# current thread. +# + + +def ctname(): + return "" + # QtCore.QThread.currentThread().objectName() + + +# +# Used to generate random levels for logging. +# +LEVELS = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, + logging.CRITICAL) + +# +# This worker class represents work that is done in a thread separate to the +# main thread. The way the thread is kicked off to do work is via a button press +# that connects to a slot in the worker. +# +# Because the default threadName value in the LogRecord isn't much use, we add +# a qThreadName which contains the QThread name as computed above, and pass that +# value in an "extra" dictionary which is used to update the LogRecord with the +# QThread name. +# +# This example worker just outputs messages sequentially, interspersed with +# random delays of the order of a few seconds. +# + + +class Worker(QObject): + @Slot() + def start(self): + extra = {'qThreadName': ctname()} + logger.debug('Started work', extra=extra) + i = 1 + # Let the thread run until interrupted. This allows reasonably clean + # thread termination. + while not QThread.currentThread().isInterruptionRequested(): + delay = 0.5 + random.random() * 2 + time.sleep(delay) + level = random.choice(LEVELS) + logger.log(level, 'Message after delay of %3.1f: %d', + delay, i, extra=extra) + i += 1 + +# +# Implement a simple UI for this cookbook example. This contains: +# +# * A read-only text edit window which holds formatted log messages +# * A button to start work and log stuff in a separate thread +# * A button to log something from the main thread +# * A button to clear the log window +# + + +class ConsoleWindow(QWidget): + + COLORS = { + logging.DEBUG: 'blue', + logging.INFO: 'black', + logging.WARNING: 'orange', + logging.ERROR: 'red', + logging.CRITICAL: 'purple', + } + + def __init__(self, app): + super().__init__() + self.app = app + self.textedit = te = QPlainTextEdit(self) + # set the window, so it alwys stays in front + self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) + # Set whatever the default monospace font is for the platform + #f = QFont('nosuchfont') + #f.setStyleHint(f.Monospace) + #te.setFont(f) + te.setReadOnly(True) + PB = QPushButton + #self.work_button = PB('Start background work', self) + + self.clear_button = PB('Clear log window', self) + self.handler = h = QtHandler(self.update_status) + # Remember to use qThreadName rather than threadName in the format string. + fs = '%(asctime)s %(levelname)-8s %(message)s' + formatter = logging.Formatter(fs) + h.setFormatter(formatter) + logger.addHandler(h) + # Set up to terminate the QThread when we exit + app.aboutToQuit.connect(self.force_quit) + + # Lay out all the widgets + layout = QVBoxLayout(self) + layout.addWidget(te) + # layout.addWidget(self.work_button) + + layout.addWidget(self.clear_button) + self.setFixedSize(1200, 400) + + # Connect the non-worker slots and signals + + self.clear_button.clicked.connect(self.clear_display) + + # Start a new worker thread and connect the slots for the worker + # self.start_thread() + # self.work_button.clicked.connect(self.worker.start) + # Once started, the button should be disabled + #self.work_button.clicked.connect(lambda : self.work_button.setEnabled(False)) + + def start_thread(self): + self.worker = Worker() + self.worker_thread = QThread() + self.worker.setObjectName('Worker') + self.worker_thread.setObjectName('WorkerThread') # for qThreadName + self.worker.moveToThread(self.worker_thread) + # This will start an event loop in the worker thread + self.worker_thread.start() + + def kill_thread(self): + # Just tell the worker to stop, then tell it to quit and wait for that + # to happen + self.worker_thread.requestInterruption() + if self.worker_thread.isRunning(): + self.worker_thread.quit() + self.worker_thread.wait() + else: + print('worker has already exited.') + + def force_quit(self): + pass + # For use when the window is closed + # if self.worker_thread.isRunning(): + # self.kill_thread() + + # The functions below update the UI and run in the main thread because + # that's where the slots are set up + + @Slot(str, logging.LogRecord) + def update_status(self, status, record): + color = self.COLORS.get(record.levelno, 'black') + s = '<pre><font color="%s">%s</font></pre>' % (color, status) + self.textedit.appendHtml(s) + + @Slot() + def manual_update(self): + # This function uses the formatted message passed in, but also uses + # information from the record to format the message in an appropriate + # color according to its severity (level). + level = random.choice(LEVELS) + extra = {'qThreadName': ctname()} + logger.log(level, 'Manually logged!', extra=extra) + + @Slot() + def clear_display(self): + self.textedit.clear() diff --git a/src/FlexSensor/generics/FolderHandler.py b/src/FlexSensor/generics/FolderHandler.py new file mode 100644 index 0000000000000000000000000000000000000000..ce9dd9fd0e0a8a61a29ef053342df29bb3db6a57 --- /dev/null +++ b/src/FlexSensor/generics/FolderHandler.py @@ -0,0 +1,47 @@ +import logging +import os + +from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +from ConfigHandler.controller.VFSObject import VFSObject + + +class FolderHandler(object): + + @staticmethod + def create_output_folder(): + VAutomatorConfig.output_dir = FolderHandler.create_folder(VAutomatorConfig.output_dir) + + return VAutomatorConfig.output_dir + + @staticmethod + def create_folder(vfs_obj: VFSObject): + ''' + Check if the folder exists, if not create it + ''' + # Check if the given argument is a file + if os.path.isfile(vfs_obj.absolute): + folder = os.path.dirname(vfs_obj.absolute) + + # Try creating the output directory + if not os.path.exists(folder): + try: + os.makedirs(folder) + except Exception as exc: + logging.error("Could not create folder {folder}. Exception: {exc}") + raise exc + return folder + + @staticmethod + def set_and_create_file(filename): + ''' + Check if the folder for file exists, if not create it + ''' + logging.info("Setting file: %s" % filename) + # Try creating the output directory + if not os.path.exists(os.path.dirname(filename)): + try: + os.makedirs(os.path.dirname(filename)) + except OSError as exc: + raise Exception("Could not create folder %s/%s for path." % (os.path.dirname(filename), filename)) + # create the file + return filename \ No newline at end of file diff --git a/src/FlexSensor/generics/GenericProperties.py b/src/FlexSensor/generics/GenericProperties.py new file mode 100644 index 0000000000000000000000000000000000000000..eaa5bed4fc76759d4815d959976aa59fa6f90c3c --- /dev/null +++ b/src/FlexSensor/generics/GenericProperties.py @@ -0,0 +1,34 @@ +from PySide6.QtCore import QObject +from numpy import ndarray + + +class GenericProperties(QObject): + def __init__(self): + super().__init__() + + def to_str(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return str(value[0]) + else: + return str(value) + + def to_int(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return int(value[0]) + else: + return int(value) + + def to_float(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return float(value[0]) + else: + return float(value) + + def to_tuple(self, value): + if (isinstance(value, list) or isinstance(value, ndarray)) and len(value) == 1: + return tuple(value[0]) + else: + return tuple(value) + + def fields(self) -> dict: + raise NotImplementedError diff --git a/src/FlexSensor/generics/PandasTableModel.py b/src/FlexSensor/generics/PandasTableModel.py new file mode 100644 index 0000000000000000000000000000000000000000..5c199832356abb7b39b9e08cf59a4ab742535720 --- /dev/null +++ b/src/FlexSensor/generics/PandasTableModel.py @@ -0,0 +1,30 @@ +from PySide6.QtCore import QAbstractTableModel, Qt +from PySide6.QtWidgets import QMenu + + +class PandasTableModel(QAbstractTableModel): + def __init__(self, df): + super().__init__() + self.df = df + + def rowCount(self, parent=None): + return self.df.shape[0] + + def columnCount(self, parent=None): + + return self.df.shape[1] + + def data(self, index, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + row = index.row() + col = index.column() + return str(self.df.iloc[row, col]) + return None + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + if orientation == Qt.Horizontal: + return str(self.df.columns[section]) + elif orientation == Qt.Vertical: + return str(self.df.index[section]) + return None diff --git a/src/FlexSensor/generics/__init__.py b/src/FlexSensor/generics/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/FlexSensor/generics/generics.py b/src/FlexSensor/generics/generics.py new file mode 100644 index 0000000000000000000000000000000000000000..3f2c679af1fbe343bb27995d794724e53ec17bf1 --- /dev/null +++ b/src/FlexSensor/generics/generics.py @@ -0,0 +1,4 @@ +def pch(c, num): + return ''.join([str(c) for i in range(0, num)]) + + diff --git a/src/FlexSensor/generics/logger.py b/src/FlexSensor/generics/logger.py new file mode 100644 index 0000000000000000000000000000000000000000..89c95c6eca27bb4d0b69a51b51e101f69dfe0cef --- /dev/null +++ b/src/FlexSensor/generics/logger.py @@ -0,0 +1,145 @@ +import logging + +from PySide6 import QtCore, QtWidgets +from PySide6.QtCore import Signal +from rich.logging import RichHandler +from scipy.signal import find_peaks#, find_peaks_cwt +import os +#from PySide6.QtNetwork import QAbstractSocket +from os import mkdir +from multiprocessing import Pool, Value +import os.path +from datetime import datetime +# Needed for Digilent Analog Discovery 2 data acquisition +from ctypes import * +try: + from generics.ConsoleWindow import ConsoleWindow +except: + pass + + +class QTextEditLogger(logging.Handler, QtCore.QObject): + appendPlainText = Signal(str) + + def __init__(self, parent): + super().__init__() + QtCore.QObject.__init__(self) + self.widget = QtWidgets.QPlainTextEdit(parent) + self.widget.setReadOnly(True) + self.appendPlainText.connect(self.widget.appendPlainText) + + def emit(self, record): + msg = self.format(record) + self.appendPlainText.emit(msg) + + +class Logger: + + log_file_full = None + @staticmethod + def set_output_file(logfile): + Logger.log_file_full = logfile + print("%s" % Logger.log_file_full) + + FORMAT="%Y-%m-%d %H-%M-%S.%f" + + @staticmethod + def check_or_create_log_file(): + if log_file_full is None: + raise ValueError("Log file can't be None") + if not os.path.exists(os.path.dirname(Logger.log_file_full)): + try: + os.makedirs(os.path.dirname(Logger.log_file_full)) + except OSError as exc: + raise Exception("Could not create log file.") + Logger.info("Log file created: %s" % Logger.log_file_full) + + @staticmethod + def debug(*args): + msg = datetime.now().strftime(Logger.FORMAT) + " [DEBUG] " + "".join(str(arg) for arg in args) + # check if folder exists + #logger.check_or_create_log_file() + + with open(Logger.log_file_full, "a+") as f: + f.write(msg+ "\n") + + #status_bar.showMessage("[DEBUG] " + "".join(str(arg) for arg in args)) + #status_bar.setStyleSheet('border: 0; color: blue;') + print(msg) + return msg + + @staticmethod + def info(*args): + msg = datetime.now().strftime(Logger.FORMAT) + " [INFO] " + "".join(str(arg) for arg in args) + # check if folder exists + #logger.check_or_create_log_file() + + with open(Logger.log_file_full, "a+") as f: + f.write(msg + "\n") + + #status_bar.showMessage("[INFO] " + "".join(str(arg) for arg in args)) + #status_bar.setStyleSheet('border: 0; color: black;') + print(msg) + return msg + + @staticmethod + def warning(*args): + msg = datetime.now().strftime(Logger.FORMAT) + " [WARN] " + "".join(str(arg) for arg in args) + # check if folder exists + #logger.check_or_create_log_file() + + with open(Logger.log_file_full, "a+") as f: + f.write(msg+ "\n") + + #status_bar.showMessage("[WARN] " + "".join(str(arg) for arg in args)) + #status_bar.setStyleSheet('border: 0; color: orange;') + print(msg) + return msg + + @staticmethod + def error(*args): + msg = datetime.now().strftime(Logger.FORMAT) + " [ERROR] " + "".join(str(arg) for arg in args) + # check if folder exists + #logger.check_or_create_log_file() + + with open(Logger.log_file_full, "a+") as f: + f.write(msg + "\n") + + #status_bar.showMessage("[ERROR] " + "".join(str(arg) for arg in args)) + #status_bar.setStyleSheet('border: 0; color: red;') + print(msg) + return msg + + @staticmethod + def fatal(*args): + msg = datetime.now().strftime(Logger.FORMAT) + " [FATAL] " + "".join(str(arg) for arg in args) + # check if folder exists + #logger.check_or_create_log_file() + + with open(Logger.log_file_full, "a+") as f: + f.write(msg + "\n") + + #status_bar.showMessage("[FATAL] " + "".join(str(arg) for arg in args)) + #status_bar.setStyleSheet('border: 0; color: red;') + print(msg) + return msg + + +def setup_logging(window: ConsoleWindow = None): + for log_name, log_obj in logging.Logger.manager.loggerDict.items(): + if log_name != '<module name>': + log_obj.disabled = True + # Format the Rich logger + FORMAT = "%(message)s" + if window is not None: + logging.basicConfig( + level="DEBUG", format=FORMAT, datefmt="[%X]", handlers=[ + RichHandler(rich_tracebacks=True), window.handler + ] + ) + else: + logging.basicConfig( + level="DEBUG", format=FORMAT, datefmt="[%X]", handlers=[ + RichHandler(rich_tracebacks=True) + ] + ) \ No newline at end of file diff --git a/src/FlexSensor/generics/widgets.py b/src/FlexSensor/generics/widgets.py new file mode 100644 index 0000000000000000000000000000000000000000..b61e4714c47be8efeba0e3b813d883a6db9fd96b --- /dev/null +++ b/src/FlexSensor/generics/widgets.py @@ -0,0 +1,24 @@ +from PySide6.QtWidgets import QLabel + + +class LEDIndicatorWidget(QLabel): + def __init__(self, color="yellow"): + super().__init__() + self.size = 8 + self._create_led(color) + + def _create_led(self, color): + self.set_color(color) + + def set_color(self, color): + self.setStyleSheet( + "QLabel {background-color : " f"{color};" + "border-color : black; " + "border-width: 1px; " + "border-style: solid; " + f"border-radius: {int(self.size / 2)}px; " + f"min-height: {self.size}px; " + f"min-width: {self.size}px; " + f"max-height: {self.size}px; " + f"max-width: {self.size}px" + "}")