diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3d1618659d3cb5274d1a74374f56e69f20496ee --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false"> + <serverData> + <paths name="root@rp-f02113.local:22 password"> + <serverdata> + <mappings> + <mapping local="$PROJECT_DIR$" web="/" /> + </mappings> + </serverdata> + </paths> + <paths name="root@rp-f02113.local:22 password (2)"> + <serverdata> + <mappings> + <mapping local="$PROJECT_DIR$" web="/" /> + </mappings> + </serverdata> + </paths> + <paths name="root@rp-f02113.local:22 password (3)"> + <serverdata> + <mappings> + <mapping local="$PROJECT_DIR$" web="/" /> + </mappings> + </serverdata> + </paths> + <paths name="root@rp-f02113.local:22 password (4)"> + <serverdata> + <mappings> + <mapping local="$PROJECT_DIR$" web="/" /> + </mappings> + </serverdata> + </paths> + </serverData> + </component> +</project> \ No newline at end of file diff --git a/.idea/flexsensor.iml b/.idea/flexsensor.iml index 8a05c6ed5f0c89c2998d9aee8978f53136f7649a..0597a8caa1273122db3fba2d0a49b28fd646fdbb 100644 --- a/.idea/flexsensor.iml +++ b/.idea/flexsensor.iml @@ -1,12 +1,32 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="PYTHON_MODULE" version="4"> <component name="NewModuleRootManager"> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="inheritedJdk" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + <excludeFolder url="file://$MODULE_DIR$/.venv" /> + <excludeFolder url="file://$MODULE_DIR$/src/FlexSensor/MeasurementEvaluation" /> + <excludeFolder url="file://$MODULE_DIR$/src/FlexSensor/MeasurementEvaluationTool" /> + </content> + <orderEntry type="jdk" jdkName="Python 3.12 (flexsensor)" jdkType="Python SDK" /> <orderEntry type="sourceFolder" forTests="false" /> </component> + <component name="PackageRequirementsSettings"> + <option name="versionSpecifier" value="Don't specify version" /> + <option name="removeUnused" value="true" /> + </component> <component name="PyDocumentationSettings"> <option name="format" value="GOOGLE" /> <option name="myDocStringFormat" value="Google" /> </component> + <component name="PyNamespacePackagesService"> + <option name="namespacePackageFolders"> + <list> + <option value="$MODULE_DIR$/src/FlexSensor" /> + <option value="$MODULE_DIR$/src/FlexSensor/Prober" /> + <option value="$MODULE_DIR$/src/FlexSensor/MainWindow" /> + <option value="$MODULE_DIR$/src/FlexSensor/MeasurementData" /> + <option value="$MODULE_DIR$/src/FlexSensor/MeasurementRoutines" /> + </list> + </option> + </component> </module> \ No newline at end of file diff --git a/.idea/jupyter-settings.xml b/.idea/jupyter-settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..15b238bc833397801088397fef0a6bb1fbd741c5 --- /dev/null +++ b/.idea/jupyter-settings.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="JupyterPersistentConnectionParameters"> + <option name="moduleParameters"> + <map> + <entry key="G:/Andere Computer/Arbeits-Laptop/Documents/2_mmWave/2_workspace/mmWaveProject/.idea/mmWaveProject.iml"> + <value> + <JupyterConnectionParameters> + <option name="managed" value="true" /> + </JupyterConnectionParameters> + </value> + </entry> + <entry key="G:/Meine Ablage/Dokumente/TU Graz/PhD Elektrotechnik/1_workspace/2d-to-3d/.idea/2d-to-3d.iml"> + <value> + <JupyterConnectionParameters> + <option name="managed" value="true" /> + </JupyterConnectionParameters> + </value> + </entry> + <entry key="G:/Meine Ablage/Dokumente/TU Graz/PhD Elektrotechnik/1_workspace/mmWave_lense_optimization/.idea/mmWaveProject.iml"> + <value> + <JupyterConnectionParameters> + <option name="managed" value="true" /> + </JupyterConnectionParameters> + </value> + </entry> + </map> + </option> + </component> +</project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 67388a2ac340ca6c17e649492b707758f6f04016..babd515fd6c4a4a8d5a564ea695c95bd3b4c4ee2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ <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" /> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (flexsensor)" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/examples/main.py b/examples/main.py new file mode 100644 index 0000000000000000000000000000000000000000..0dbe36dcc7aca47a2062bf66a9d8b4efc1be8d07 --- /dev/null +++ b/examples/main.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> +Created: 2023-10-19 12:35 +Package Version: +""" +import logging +import sys + +from PySide6.QtWidgets import QApplication + +sys.path.append('./src') +import FlexSensor + +def main(argv): + app = QApplication(sys.argv) + splash_screen = FlexSensor.SplashScreen._display_splash_screen() + + app.processEvents() + + # Disable loggers that are not needed (e. g. numpy, etc) + cw = FlexSensor.ConsoleWindow(app) + #cw.show() + + FlexSensor.ApplicationInit.setup_logging(cw) + FlexSensor.ApplicationInit.set_icon(app) + + # Read the inital config file + vaut_config = FlexSensor.ApplicationInit.load_config_file(f"{FlexSensor.configs_root}/init_config.yaml") + + logging.info(f"Starting Velox GUI Version {FlexSensor.__version__}") + main_model = FlexSensor.MainThreadModel(config=vaut_config) + main_controller = FlexSensor.MainThreadController(main_model) + main_window = FlexSensor.MainWindow(main_model, main_controller) + + # test_win = StructureSelector() + + main_window.show() + splash_screen.finish(main_window) + sys.exit(app.exec()) + +if __name__ == "__main__": + + main(sys.argv) + + diff --git a/src/FlexSensor/AppSettings.py b/src/FlexSensor/AppSettings.py new file mode 100644 index 0000000000000000000000000000000000000000..d93fb95048a4d1fe47899f335f368c36773b9034 --- /dev/null +++ b/src/FlexSensor/AppSettings.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" +Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> +Created: 2023-10-19 12:35 +Package Version: +""" +import confighandler as cfg + + +class AppSettings(cfg.ConfigNode): + + def __init__(self) -> None: + super().__init__() + # APP SETTINGS + # /////////////////////////////////////////////////////////////// + self.ENABLE_CUSTOM_TITLE_BAR = cfg.Field(True) + self.MENU_WIDTH = cfg.Field(240) + self.LEFT_BOX_WIDTH = cfg.Field(240) + self.RIGHT_BOX_WIDTH = cfg.Field(240) + self.TIME_ANIMATION = cfg.Field(500) + + # BTNS LEFT AND RIGHT BOX COLORS + self.BTN_LEFT_BOX_COLOR = cfg.Field("background-color: rgb(44, 49, 58);") + self.BTN_RIGHT_BOX_COLOR = cfg.Field("background-color: #ff79c6;") + + # MENU SELECTED STYLESHEET + self.MENU_SELECTED_STYLESHEET = cfg.Field(""" + border-left: 22px solid qlineargradient(spread:pad, x1:0.034, y1:0, x2:0.216, y2:0, stop:0.499 rgba(255, 121, 198, 255), stop:0.5 rgba(85, 170, 255, 0)); + background-color: rgb(40, 44, 52); + """) + + self.register() + diff --git a/src/FlexSensor/FlexSensorConfig.py b/src/FlexSensor/FlexSensorConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..802d0f8c7f3ac479634a1eeea89c286cda2069f2 --- /dev/null +++ b/src/FlexSensor/FlexSensorConfig.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" +Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> +Created: 2023-10-19 12:35 +Package Version: +""" +import confighandler as cfg + +from .AppSettings import AppSettings +from FlexSensor.WaferConfig import WaferConfig + +import LaserControl as Laser +import CaptDeviceControl as CaptDevice + +class FlexSensorConfig(cfg.ConfigNode): + + def __init__(self) -> None: + super().__init__() + self.wafer_version = cfg.Field("MaskARY1_Jakob_full", friendly_name="Wafer Version", + description="Wafer Version to be measured") + self.wafer_number = cfg.Field("T40741W177G0", friendly_name="Wafer Number", + description="Wafer Number to be measured") + + self.output_directory = cfg.Field("./", friendly_name="Output Directory", + description="Measurement output directory") + + self.wafer_config = WaferConfig() + self.app_config = AppSettings() + self.laser_config = Laser.Config() + self.captdev_config = CaptDevice.Config() + + self.register() + diff --git a/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py b/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py index d7ae53e34c048b54a25fe902a7093a87342bc401..3f77a096ca3c6a7e0b0858f15d05689c0720a4c6 100644 --- a/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py +++ b/src/FlexSensor/InitialSetupWizard/InitialSetupWizard.py @@ -8,7 +8,6 @@ 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): @@ -28,7 +27,6 @@ class InitialSetupWizard(QWizard): if __name__ == "__main__": - setup_logging() app = QApplication() prober = Prober.Controller() diff --git a/src/FlexSensor/MainWindow/__init__.py b/src/FlexSensor/MainWindow/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2930a2a4e4ce060c8c619c4e63186e106efbcfcd 100644 --- a/src/FlexSensor/MainWindow/__init__.py +++ b/src/FlexSensor/MainWindow/__init__.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../')) \ No newline at end of file diff --git a/src/FlexSensor/MainWindow/controller/MainThreadController.py b/src/FlexSensor/MainWindow/controller/MainThreadController.py index 47a94951948b33be77f76d7a86bf3829c8b509b7..8d08d08bc2aa55d2ae519027a501dba8458ff39e 100644 --- a/src/FlexSensor/MainWindow/controller/MainThreadController.py +++ b/src/FlexSensor/MainWindow/controller/MainThreadController.py @@ -2,14 +2,15 @@ import logging from PySide6.QtCore import QThread -import ConfigHandler as Config -import Laser as Laser -import AD2CaptDevice as AD2Dev +import confighandler +import LaserControl as Laser +import CaptDeviceControl as AD2Dev + import Prober as Prober import MeasurementEvaluationTool -from MainWindow.model.MainThreadModel import MainThreadModel -from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine +from ..model.MainThreadModel import MainThreadModel +from FlexSensor.MeasurementRoutines.MeasurementRoutine import MeasurementRoutine from Prober.controller.ProberController import ProberController @@ -52,7 +53,8 @@ class MainThreadController(object): def _create_working_folders(self): """Creates all working folders to store the measurement data. """ - self.model.vaut_config.setup_folders() + pass + #self.model.config.setup_folders() def _move_measurement_routine_thread(self, measurement_routine): measurement_routine.moveToThread(self.measurement_thread) @@ -77,7 +79,7 @@ class MainThreadController(object): self.model.laser_controller, self.model.ad2_controller, self.model.prober_controller, - self.model.vaut_config) + self.model.config) self.logger.debug("Initialized MeasurementRoutine.") return measurement_routine diff --git a/src/FlexSensor/MainWindow/model/MainThreadModel.py b/src/FlexSensor/MainWindow/model/MainThreadModel.py index 0c4a7c9aace1588fe6bd8d7dac3de035088606df..552f843259fe429794d3138b95b5b22757d36047 100644 --- a/src/FlexSensor/MainWindow/model/MainThreadModel.py +++ b/src/FlexSensor/MainWindow/model/MainThreadModel.py @@ -1,56 +1,51 @@ from PySide6.QtCore import QObject, Signal -import Laser as Laser -import AD2CaptDevice as AD2Dev -import Prober as Prober +import LaserControl as Laser +import CaptDeviceControl as AD2Dev +import FlexSensor.Prober as Prober +import confighandler as Config + import MeasurementEvaluationTool as met -import ConfigHandler as Config +#import ConfigHandler as Config from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine +from FlexSensor.FlexSensorConfig import FlexSensorConfig 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) + vaut_config_changed = Signal(Config.ConfigNode) + laser_changed = Signal(Laser.Model, Laser.Controller, Laser.View) + ad2_changed = Signal(AD2Dev.Model, AD2Dev.Controller, AD2Dev.View) prober_changed = Signal(Prober.Model, Prober.Controller, Prober.ControlWindow) measurement_routine_changed = Signal(MeasurementRoutine) class MainThreadModel(QObject): - def __init__(self, vaut_config: Config.VAutomatorConfig): + def __init__(self, config: FlexSensorConfig): super().__init__() self.signals = MainThreadSignals() - self._vaut_config: Config.VAutomatorConfig = vaut_config + self._config: FlexSensorConfig = 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) + self._ad2_model: AD2Dev.Model = AD2Dev.Model(self.config.captdev_config) + self._ad2_controller: AD2Dev.Controller = AD2Dev.Controller(self._ad2_model) + self._ad2_window: AD2Dev.View = AD2Dev.View(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_model: Laser.Model = Laser.Model(self.config.laser_config) + self._laser_controller: Laser.Controller = Laser.Controller(self._laser_model) - self._laser_window: Laser.ControlWindow = Laser.ControlWindow( - self._laser_model, - self._laser_controller) + self._laser_window: Laser.View = Laser.View(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) + self._prober_model: Prober.Model = Prober.Model(self.config) + self._prober_controller: Prober.Controller = Prober.Controller(self._prober_model) + self._prober_window: Prober.ControlWindow = Prober.ControlWindow(self._prober_model, self._prober_controller) # Widgets self.mea_eval_tool_model: met.Model = met.Model() @@ -62,13 +57,13 @@ class MainThreadModel(QObject): # Implement all getter and setter methods for the model here @property - def vaut_config(self) -> Config.VAutomatorConfig: - return self._vaut_config + def config(self) -> FlexSensorConfig: + return self._config - @vaut_config.setter - def vaut_config(self, value: Config.VAutomatorConfig): - self._vaut_config = value - self.signals.vaut_config_changed.emit(self.vaut_config) + @config.setter + def config(self, value: FlexSensorConfig): + self._config = value + self.signals.vaut_config_changed.emit(self.config) @property def laser_model(self) -> Laser.Model: @@ -90,11 +85,11 @@ class MainThreadModel(QObject): self.signals.laser_changed.emit(self.laser_model, self.laser_controller, self.laser_window) @property - def laser_window(self) -> Laser.ControlWindow: + def laser_window(self) -> Laser.View: return self._laser_window @laser_window.setter - def laser_window(self, value: Laser.ControlWindow): + def laser_window(self, value: Laser.View): self._laser_window = value self.signals.laser_changed.emit(self.laser_model, self.laser_controller, self.laser_window) @@ -118,11 +113,11 @@ class MainThreadModel(QObject): self.signals.ad2_changed.emit(self.ad2_model, self.ad2_controller, self.ad2_window) @property - def ad2_window(self) -> AD2Dev.ControlWindow: + def ad2_window(self) -> AD2Dev.View: return self._ad2_window @ad2_window.setter - def ad2_window(self, value: AD2Dev.ControlWindow): + def ad2_window(self, value: AD2Dev.View): self._ad2_window = value self.signals.ad2_changed.emit(self.ad2_model, self.ad2_controller, self.ad2_window) diff --git a/src/FlexSensor/MainWindow/view/BaseWindow.py b/src/FlexSensor/MainWindow/view/BaseWindow.py index ae6ca6e885ac46bf3737ce528c4428ce196ace1a..a0b53566ed4794fd0b09e8d8303b9c30f4317d63 100644 --- a/src/FlexSensor/MainWindow/view/BaseWindow.py +++ b/src/FlexSensor/MainWindow/view/BaseWindow.py @@ -3,21 +3,24 @@ 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 +from FlexSensor.FlexSensorConfig import FlexSensorConfig + class BaseWindow(QMainWindow): - def __init__(self, ui_main_window: Ui_MainWindow): + def __init__(self, ui_main_window: Ui_MainWindow, config: FlexSensorConfig): 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 + self.app_config = config.app_config + self.app_config.ENABLE_CUSTOM_TITLE_BAR.set(True) # APP NAME # /////////////////////////////////////////////////////////////// @@ -27,7 +30,7 @@ class BaseWindow(QMainWindow): self.setWindowTitle(title) self._ui.titleRight.setText(description) - if not Settings.ENABLE_CUSTOM_TITLE_BAR: + if not self.app_config.ENABLE_CUSTOM_TITLE_BAR.get(): self._ui.appMargins.setContentsMargins(0, 0, 0, 0) self._ui.minimizeAppBtn.hide() self._ui.maximizeRestoreAppBtn.hide() @@ -79,8 +82,8 @@ class BaseWindow(QMainWindow): # GET WIDTH width = self._ui.extraLeftBox.width() widthRightBox = self._ui.extraRightBox.width() - maxExtend = Settings.LEFT_BOX_WIDTH - color = Settings.BTN_LEFT_BOX_COLOR + maxExtend = self.app_config.LEFT_BOX_WIDTH.get() + color = self.app_config.BTN_LEFT_BOX_COLOR.get() standard = 0 # GET BTN STYLE @@ -109,8 +112,8 @@ class BaseWindow(QMainWindow): # GET WIDTH width = self._ui.extraRightBox.width() widthLeftBox = self._ui.extraLeftBox.width() - maxExtend = Settings.RIGHT_BOX_WIDTH - color = Settings.BTN_RIGHT_BOX_COLOR + maxExtend = self.app_config.RIGHT_BOX_WIDTH.get() + color = self.app_config.BTN_RIGHT_BOX_COLOR.get() standard = 0 # GET BTN STYLE @@ -137,7 +140,7 @@ class BaseWindow(QMainWindow): if enable: # GET WIDTH width = self._ui.leftMenuBg.width() - maxExtend = Settings.MENU_WIDTH + maxExtend = self.app_config.MENU_WIDTH.get() standard = 60 # SET MAX WIDTH @@ -178,7 +181,7 @@ class BaseWindow(QMainWindow): # ANIMATION RIGHT BOX self.right_box = QPropertyAnimation(self._ui.extraRightBox, b"minimumWidth") - self.right_box.setDuration(Settings.TIME_ANIMATION) + self.right_box.setDuration(self.app_config.TIME_ANIMATION) self.right_box.setStartValue(right_box_width) self.right_box.setEndValue(right_width) self.right_box.setEasingCurve(QEasingCurve.InOutQuart) @@ -190,11 +193,11 @@ class BaseWindow(QMainWindow): self.group.start() def selectMenu(self, getStyle): - select = getStyle + Settings.MENU_SELECTED_STYLESHEET + select = getStyle + self.app_config.MENU_SELECTED_STYLESHEET.get() return select def deselectMenu(self, getStyle): - deselect = getStyle.replace(Settings.MENU_SELECTED_STYLESHEET, "") + deselect = getStyle.replace(self.app_config.MENU_SELECTED_STYLESHEET.get(), "") return deselect # START SELECTION @@ -210,7 +213,7 @@ class BaseWindow(QMainWindow): w.setStyleSheet(self.deselectMenu(w.styleSheet())) def resize_grips(self): - if Settings.ENABLE_CUSTOM_TITLE_BAR: + if self.app_config.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) diff --git a/src/FlexSensor/MainWindow/view/MainThreadView.py b/src/FlexSensor/MainWindow/view/MainThreadView.py index 8a852bd475396d4f41c11fdb31f0671aea227472..5f0951a5bd57e53d2b56fc262aad10443b3155bb 100644 --- a/src/FlexSensor/MainWindow/view/MainThreadView.py +++ b/src/FlexSensor/MainWindow/view/MainThreadView.py @@ -11,42 +11,38 @@ 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, +import FlexSensor.__version__ as fsversion +import confighandler as Config +from FlexSensor.MainWindow.view.BaseWindow import BaseWindow +from FlexSensor.MainWindow.view.widgets.HomeStatusWidget import HomeStatusWidget +from FlexSensor.MainWindow.view.widgets.MenuBarDefinition import MenuBarDefinition +from FlexSensor.MainWindow.view.widgets.ScopeWidget import ScopeWidget + +from FlexSensor.MainWindow.view.MainView import Ui_MainWindow + +from FlexSensor.MainWindow.controller.MainThreadController import MainThreadController +from FlexSensor.MainWindow.model.MainThreadModel import MainThreadModel +from FlexSensor.MainWindow.view.StepThroughView import StepThroughView +from FlexSensor.InitialSetupWizard.InitialSetupWizard import InitialSetupWizard +from FlexSensor.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 +from FlexSensor.MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from FlexSensor.constants.qs_style_sheets import CSSPlayPushButton +from FlexSensor.generics.VASInputFileParser import VASInputFileParser class MainWindow(BaseWindow): def __init__(self, model: MainThreadModel, controller: MainThreadController): - super().__init__(Ui_MainWindow()) + super().__init__(Ui_MainWindow(), model.config) 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.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)) @@ -96,7 +92,7 @@ class MainWindow(BaseWindow): 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(HomeStatusWidget(self.model), 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) @@ -105,7 +101,7 @@ class MainWindow(BaseWindow): 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.setWindowTitle(f'FlexSensor Automator {fsversion}') self.setWindowIcon(QIcon('../images/FlexSensorIcon.png')) # self.init_menu_run() @@ -125,21 +121,20 @@ class MainWindow(BaseWindow): 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") - ) + self.configView = self.model.config.view + tab_input = tabwidget.addTab(WidgetSettingsInFilesFolders(self.model.config), "Input") + tab_folders = tabwidget.addTab(WidgetSettingsOutFilesFolders(self.model.config), "Folder Settings") + tab_ad2 = tabwidget.addTab(WidgetAD2Settings(self.model.config), "AD2 Settings") + tab_laser = tabwidget.addTab(WidgetLaserSettings(self.model.config.laser_config), "Laser Settings") + #tab_yaml = tabwidget.addTab(self.configView, "YAML Config") + #tabwidget.currentChanged.connect( + # lambda idx: self.configView.repopulate(self.model.config) if idx == tab_yaml else print("fg") + #) return tabwidget # def init_UI_device_control(self): @@ -234,9 +229,9 @@ class MainWindow(BaseWindow): 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 + input_file=self.model.config.wafer_config.get_structure_file().absolute ) - self.step_through_view = StepThroughView(grouped_structures) + self.step_through_view = StepThroughView(grouped_structures, self.model.prober_controller) self.step_through_view.show() def _on_open_initial_setup_wizard(self): @@ -340,13 +335,13 @@ class MainWindow(BaseWindow): 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>") + self._ui.lbl_die_no.setText("<b>" + str(version_info["die_no"]) + "</b>") + self._ui.lbl_structure.setText("<b>" + str(version_info["structure"]) + "</b>") + self._ui.lbl_die_col.setText("<b>" + str(version_info["chuck_col"]) + "</b>") + self._ui.lbl_die_row.setText("<b>" + str(version_info["chuck_row"]) + "</b>") def on_report_progress(self, progress): - self.progress.setValue(progress) + self._ui.progress.setValue(progress) def on_structure_select(self): pass diff --git a/src/FlexSensor/MainWindow/view/SplashScreen.py b/src/FlexSensor/MainWindow/view/SplashScreen.py new file mode 100644 index 0000000000000000000000000000000000000000..a642f92fd74c79472d93184c61443c744d57649a --- /dev/null +++ b/src/FlexSensor/MainWindow/view/SplashScreen.py @@ -0,0 +1,18 @@ +from PySide6.QtCore import QSize +from PySide6.QtGui import QPixmap +from PySide6.QtWidgets import QSplashScreen + +from FlexSensor.pathes import image_root + + +class SplashScreen: + + @staticmethod + def _display_splash_screen(): + pixmap = QPixmap(f"{image_root}/FlexSensorSplashScreen.png") + scale = 0.5 + pixmap = pixmap.scaled(QSize(int(1024 * scale), int(683 * scale))) + splash = QSplashScreen(pixmap) + # splash.setFixedHeight(300) + splash.show() + return splash \ No newline at end of file diff --git a/src/FlexSensor/MainWindow/view/StepThroughView.py b/src/FlexSensor/MainWindow/view/StepThroughView.py index 37e506f32435d5834af85a0cd03abbbdfa61b4c4..b33643dc2dca3fb5a14ecd69ec6142a84c6474a5 100644 --- a/src/FlexSensor/MainWindow/view/StepThroughView.py +++ b/src/FlexSensor/MainWindow/view/StepThroughView.py @@ -4,11 +4,10 @@ from PySide6.QtWidgets import ( ) from PySide6.QtGui import QIcon -import Prober as Prober +import FlexSensor.Prober as Prober -import ConfigHandler.controller.VASInputFileParser as input_file_parser -from Prober.controller.ProberController import ProberController -from constants.FlexsensorConstants import Probe +from FlexSensor.Prober.controller.ProberController import ProberController +from FlexSensor.constants.FlexsensorConstants import Probe class StepThroughView(QMainWindow): diff --git a/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py b/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py index cf4b98992cb76d348fc55ba5e0805b32ec10628d..5aa9974bdc0fae41f2d30b8f19989e9b7d64e21a 100644 --- a/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py +++ b/src/FlexSensor/MainWindow/view/widgets/HomeStatusWidget.py @@ -2,21 +2,21 @@ 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 +import FlexSensor.__version__ as fsversion +from FlexSensor.MainWindow.model.MainThreadModel import MainThreadModel +from FlexSensor.Prober.view.widgets.ProberPositionWidget import ProberPositionWidget class HomeStatusWidget(QWidget): - def __init__(self, view: MainView): + def __init__(self, model: MainThreadModel): super().__init__() self.velox_kernel_version = None self.python_version = None self.script_version = None - self.view: MainView = view + self.model: MainThreadModel = model layout = QGridLayout() layout.addWidget(self.init_UI_wafer_info(), 0, 0, 1, 1) layout.addWidget(self.init_UI_status_wdg(), 0, 1, 1, 1) @@ -29,12 +29,12 @@ class HomeStatusWidget(QWidget): 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 = QLineEdit(parent=self, text=str(self.model.config.wafer_version.get())) #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 = QLineEdit(parent=self, text=str(self.model.config.wafer_number.get())) #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) @@ -46,7 +46,7 @@ class HomeStatusWidget(QWidget): def init_UI_status_wdg(self): grid_group_box = QGroupBox() layout = QVBoxLayout() - layout.addWidget(ProberPositionWidget(self.view.model.prober_model, "Horizontal")) + layout.addWidget(ProberPositionWidget(self.model.prober_model, "Horizontal")) self.progress = QProgressBar(self) self.progress.setStyleSheet( @@ -64,7 +64,7 @@ class HomeStatusWidget(QWidget): layout = QGridLayout() try: self.velox_kernel_version = QLineEdit(parent=self, - text=self.view.model.prober_model.report_velox_kernel_version()) + text=self.model.prober_controller.report_kernel_version()) except Exception as e: print(e) @@ -82,7 +82,7 @@ class HomeStatusWidget(QWidget): 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 = QLineEdit(parent=self, text=fsversion) self.script_version.setReadOnly(True) self.script_version.setEnabled(False) layout.addWidget(QLabel("Script Version"), 2, 2) diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py b/src/FlexSensor/MainWindow/view/widgets/MenuBarDefinition.py similarity index 92% rename from src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py rename to src/FlexSensor/MainWindow/view/widgets/MenuBarDefinition.py index 7ff8638994e2b9b0ee4ac9880aed97c31014e2be..4c20f21d5def2fc49d240d5d2f63225642d6c370 100644 --- a/src/FlexSensor/MeasurementEvaluationTool/view/widgets/MenuBarDefinition.py +++ b/src/FlexSensor/MainWindow/view/widgets/MenuBarDefinition.py @@ -1,9 +1,8 @@ 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 +from FlexSensor.MainWindow.view import MainThreadView +from FlexSensor.pathes import image_root class MenuBarDefinition(QWidget): diff --git a/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py index 240ac93a1dc076903db0255eb560d5d92d0445f9..377cc3b3e202c6aaef69e78c41041378d5e6f222 100644 --- a/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py +++ b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py @@ -1,13 +1,14 @@ +import confighandler +from LaserControl.LaserConfig import LaserConfig from PySide6.QtWidgets import QWidget, QGridLayout, QGroupBox, QLineEdit, QPushButton, QLabel, QDoubleSpinBox -from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig -from ConfigHandler.view.ConfigView import ConfigView +from FlexSensor.FlexSensorConfig import FlexSensorConfig class WidgetSettingsInFilesFolders(QWidget): - def __init__(self, vaut_config: VAutomatorConfig): + def __init__(self, config: FlexSensorConfig): super().__init__() - self.vaut_config = vaut_config + self.config: FlexSensorConfig = config self.btn_select_list_of_structures = QPushButton(parent=self, text="...") self.btn_select_working_directory = QPushButton(parent=self, text="...") @@ -19,18 +20,19 @@ class WidgetSettingsInFilesFolders(QWidget): 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.tb_working_directory = QLineEdit(parent=self) 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 - + self.config.output_directory.view.add_new_view(self.tb_working_directory) # List of structures - self.tb_list_of_structures = QLineEdit(parent=self, text=str(self.vaut_config.wafer_config.get_structure_file().relative)) + self.tb_list_of_structures = QLineEdit(parent=self) 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 + self.config.wafer_config.structure_file.view.add_new_view(self.tb_list_of_structures) grid_group_box.setLayout(layout) self.layout.addWidget(grid_group_box) @@ -38,9 +40,9 @@ class WidgetSettingsInFilesFolders(QWidget): class WidgetSettingsOutFilesFolders(QWidget): - def __init__(self, vaut_config: VAutomatorConfig): + def __init__(self, config: FlexSensorConfig): super().__init__() - self.vaut_config = vaut_config + self.config: FlexSensorConfig = config self.tb_log_file = QLineEdit( text="self.vaut_config.wafer_config.get_log_file().filename") @@ -53,8 +55,6 @@ class WidgetSettingsOutFilesFolders(QWidget): self.tb_scope_image_file = QLineEdit( text="self.vaut_config.wafer_config.get_scope_image_file()._mat_filename") - - self.layout = QGridLayout() self.init_UI() @@ -63,11 +63,6 @@ class WidgetSettingsOutFilesFolders(QWidget): 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()) @@ -108,62 +103,65 @@ class WidgetSettingsOutFilesFolders(QWidget): 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) + return + # if value is not None: + # self.config.wafer_config.get_scope_image_file().set_obj(value) + # val = self.config.wafer_config.get_scope_image_file().relative.replace(self.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.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) + return + # if value is not None: + # self.config.wafer_config.measurement_output.set(value) + # val = self.config.wafer_config.measurement_output.get().replace(self.config.output_directory.get(), + # "<b>wd</b>") + # self.lbl_measurement_output.setText(val) + # # set label hover text + # self.lbl_measurement_output.setToolTip(self.config.wafer_config.scope_image_file.get()) 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 + return + # if value is not None: + # self.config.wafer_config.get_bookmark_file().set_obj(value) + # val = self.config.wafer_config.get_bookmark_file().relative.replace(self.config.get_output_directory().relative, + # "<b>wd</b>") + # self.lbl_bookmark_file.setText(val) + # # set label hover text + # self.lbl_bookmark_file.setToolTip(self.config.wafer_config.get_bookmark_file().absolute) + # + # config = self.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) + return + # if value is not None: + # self.config.wafer_config.measurement_mat_file.set(value) + # val = self.config.wafer_config.measurement_mat_file.get().replace( + # self.config.output_directory.get().relative,"<b>wd</b>") + # self.lbl_mat_files_output.setText(val) + # self.lbl_mat_files_output.setToolTip(self.config.wafer_config.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) + self.config.wafer_config.log_file.set(value) - val = self.vaut_config.wafer_config.get_log_file().relative.replace(self.vaut_config.get_output_directory().relative, "<b>wd</b>") + val = self.config.wafer_config.log_file.get().replace(self.config.output_directory.get(), "<b>wd</b>") self.lbl_log_file.setText(val) - self.lbl_log_file.setToolTip(self.vaut_config.wafer_config.get_log_file().absolute) + self.lbl_log_file.setToolTip(self.config.wafer_config.log_file.get()) + class WidgetAD2Settings(QWidget): - def __init__(self, vaut_config: VAutomatorConfig): + def __init__(self, config: FlexSensorConfig): super().__init__() - self.vaut_config = vaut_config - self.c = ConfigView(vaut_config) - + self.tb_ad2_raw_out_file = QLineEdit() + self.config = config + # self.c = #ConfigView(vaut_config) self.num_sample_rate = QDoubleSpinBox() self.num_total_samples = QDoubleSpinBox() @@ -175,10 +173,10 @@ class WidgetAD2Settings(QWidget): self.layout = QGridLayout() self.init_UI() - def show_config(self): - self.c = ConfigView(self.vaut_config) - self.c.show() + pass + # self.c = ConfigView(self.vaut_config) + # self.c.show() def init_UI(self): layout = QGridLayout() @@ -187,67 +185,72 @@ class WidgetAD2Settings(QWidget): 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.valueChanged.connect(lambda v: self.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.setValue(self.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) + self.config.captdev_config.sample_rate.view.add_new_view(self.num_sample_rate) 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.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.setValue(self.config.ad2_device_config.get_total_samples()) self.num_total_samples.setDecimals(3) self.num_total_samples.setKeyboardTracking(False) + self.config.captdev_config.total_samples.view.add_new_view(self.num_total_samples) 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.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.setValue(self.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) + self.config.captdev_config.sample_time.view.add_new_view(self.num_sample_time) 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) + #self.tb_ad2_raw_out_file = QLineEdit() + self.config.captdev_config.ad2_raw_out_file.view.add_new_view(self.tb_ad2_raw_out_file) + layout.addWidget(self.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): + def __init__(self, laser_config: LaserConfig): super().__init__() - self.vaut_config = vaut_config + self.config = laser_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 = QPushButton(parent=self, text="....") - - #self.btn_select_ad2_raw_out_file.clicked.connect(self.show_config) + # 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() + pass + #self.c = ConfigView(self.vaut_config) + #self.c.show() def init_UI(self): layout = QGridLayout() @@ -257,67 +260,68 @@ class WidgetLaserSettings(QWidget): 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.setValue(self.config.wa()[0]) self.num_wavelength_sweep_start.setSuffix(" nm") self.num_wavelength_sweep_start.setDecimals(3) self.num_wavelength_sweep_start.setKeyboardTracking(False) + self.config.wl_sweep_start.view.add_new_view(self.num_wavelength_sweep_start) 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_sweep_start.valueChanged.connect( + # lambda v: self.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.setValue(self.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) + self.config.wl_sweep_stop.view.add_new_view(self.num_wavelength_sweep_start) 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)] - )) + #self.num_wavelength_range_stop.valueChanged.connect( + # lambda v: self.wavelength_range.get()( + # [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.valueChanged.connect(lambda v: self.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.setValue(self.config.laser_config.get_velocity()) + self.num_velocity.setSuffix(" m/s") self.num_velocity.setDecimals(3) self.num_velocity.setKeyboardTracking(False) + self.config.velocity.view.add_new_view(self.num_velocity) 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.valueChanged.connect(lambda v: self.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.setValue(self.config.laser_config.get_acceleration()) self.num_acceleration.setSuffix(" m/s^2") self.num_acceleration.setDecimals(3) self.num_acceleration.setKeyboardTracking(False) + self.config.acceleration.view.add_new_view(self.num_acceleration) 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.valueChanged.connect(lambda v: self.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.setValue(self.config.laser_config.get_deceleration()) self.num_deceleration.setSuffix(" m/s^2") self.num_deceleration.setDecimals(3) self.num_deceleration.setKeyboardTracking(False) + self.config.deceleration.view.add_new_view(self.num_deceleration) 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 index 217bfe27e638dd16e05d1575c480ff76f60c1331..9f8c4d1a8ebce10b50d91808c4755d81e849635e 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py @@ -2,6 +2,7 @@ import logging import os from pathlib import Path +import LaserControl import numpy as np import pandas as pd import scipy @@ -29,13 +30,13 @@ class MeasuredData: # ============================================================================================================== # 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 + #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)) + #self._measurement_properties: MeasurementProperties = MeasurementProperties( + # MPropertiesFindPeaks(0.1, 10000, None)) # ============================================================================================================== # Dataframe with measured values diff --git a/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py index 77293227af0a117a1792590b8e355de068bf5d12..37c00a116e6c7f58140c5b7f795f41a5ae6e5b92 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py @@ -11,9 +11,6 @@ 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): diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py index e21abc0db0a958240a6bf1e0fdb270909a2d12ff..97877e5b59973d17780965608e26b9d84ba91835 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py @@ -27,11 +27,11 @@ from MeasurementData.Properties.MeasurementProperties import (WaveguidePropertie MeasurementProperties, WaveguidePropertiesMZI, MPropertiesFindPeaks) +from MeasurementData.Properties.WaferProperties import WaferProperties import mcpy -from MeasurementData.Properties.WaferProperties import WaferProperties -from generics.logger import setup_logging + class SingleMeasuredData(MeasuredData): diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py index 1a685ec39967f90049a0412301649b1e7482c589..5e17c947db7635503d1d3782b070a89883f6309b 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementDataLoader.py @@ -11,10 +11,7 @@ from PySide6.QtWidgets import QProgressDialog, QWidget import MeasurementEvaluationTool as met from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData - -from wrappers.QProgressBarWindow import QProgressBarWindow - - +from fswidgets import QProgressBarWindow class MeasurementDataLoader(QWidget): @staticmethod diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py index ac931f73649fc750400125673beb850275b87a58..452876197b02f6d8eacd48273305d0de355376ad 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/SupportClasses/MeasurementProperties.py @@ -1,8 +1,8 @@ import numpy as np from PySide6.QtCore import Signal -import mcpy -from mcpy import Uncertainty +#import mcpy +#from mcpy import Uncertainty from generics.GenericProperties import GenericProperties diff --git a/src/FlexSensor/MeasurementData/Properties/GenericProperties.py b/src/FlexSensor/MeasurementData/Properties/GenericProperties.py index a112641f7fc64c3c074917318df0c7cf0fb0e047..c04ac75603c07da3a2cefdd14bb1e824ca0f3687 100644 --- a/src/FlexSensor/MeasurementData/Properties/GenericProperties.py +++ b/src/FlexSensor/MeasurementData/Properties/GenericProperties.py @@ -1,4 +1,3 @@ -import pandas as pd from PySide6.QtCore import QObject from numpy import ndarray diff --git a/src/FlexSensor/MeasurementData/Properties/LaserProperties.py b/src/FlexSensor/MeasurementData/Properties/LaserProperties.py index 2b2947cbe02dac59c28b14a3e363be2686c51ab8..ce91215b5571c1584f8f9f4ab52d48a29aa07601 100644 --- a/src/FlexSensor/MeasurementData/Properties/LaserProperties.py +++ b/src/FlexSensor/MeasurementData/Properties/LaserProperties.py @@ -1,9 +1,9 @@ import sys from MeasurementData.Properties.GenericProperties import GenericProperties -import mcpy +#import mcpy -sys.path.append('../mcpy/mcpy') +#sys.path.append('../mcpy/mcpy') import mcpy diff --git a/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py index b5c0d6e66f07c7f3d6726c96d8125b8f50e8aac3..ad15f376dbc2f3e2ac8ecbf2a022bec090723e26 100644 --- a/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py +++ b/src/FlexSensor/MeasurementEvaluationTool/controller/MeasurementDatabase.py @@ -4,7 +4,6 @@ import sqlite3 from PySide6.QtWidgets import QApplication from MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData -from generics.logger import setup_logging class MeasurementDatabase: diff --git a/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py b/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py index 167996fda6b44efdc6e6879d1f0f82b028482aaa..abd2c797548e6d46cc67c637e8a82e4ef029fabd 100644 --- a/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py +++ b/src/FlexSensor/MeasurementEvaluationTool/view/MeasurementDataView.py @@ -12,8 +12,6 @@ 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): @@ -154,7 +152,7 @@ def convert_mat(mypath): 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') diff --git a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py index 5b7bba703a6d25f20070acad74b4ac0e9bf3ca1b..a471bcfd9e41841181ee5f55c6c9ff8dabf833e0 100644 --- a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py +++ b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py @@ -1,24 +1,30 @@ import logging +#from LaserControlOld.controller.BaseLaserController import BaseLaserController 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 +#from AD2CaptDevice.controller.AD2CaptDeviceController import AD2CaptDeviceController +#from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +#from Laser.LaserControl.controller import BaseLaserController + +import CaptDeviceControl as CaptDevice +import LaserControl as Laser +import confighandler as Config + +from FlexSensor.FlexSensorConfig import FlexSensorConfig +from FlexSensor.Prober.controller.ProberController import ProberController +from FlexSensor.MeasurementRoutines.WorkerSignals import WorkerSignals class BaseMeasurementRoutine(QObject): - def __init__(self, laser: BaseLaserController, ad2device: AD2CaptDeviceController, prober: ProberController, - vaut_config: VAutomatorConfig): + def __init__(self, laser: Laser, ad2device: CaptDevice, prober: ProberController, config: FlexSensorConfig): super().__init__() self.logger = logging.getLogger("Base Measurement Routine") - self.vaut_config = vaut_config + self.config = config - self.ad2device: AD2CaptDeviceController = ad2device - self.laser: BaseLaserController = laser + self.ad2device: CaptDevice = ad2device + self.laser: Laser = laser self.prober: ProberController = prober self.logger.debug(f"{self.prober.report_kernel_version()}") print(self.prober) diff --git a/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py index ea4d3d963f407a4cfdbccc1a2bc5004e284a6ac2..0fe9ce95e72c10eee3d0b7acbc6b545423034ff8 100644 --- a/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py +++ b/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py @@ -1,44 +1,43 @@ import logging -import time import traceback from datetime import datetime +import CaptDeviceControl as AD2Dev +import LaserControl as Laser +import mcpy 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 +import FlexSensor.Prober as Prober +from FlexSensor.FlexSensorConfig import FlexSensorConfig +from FlexSensor.MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +from FlexSensor.MeasurementData.Properties.MeasurementProperties import MPropertiesFindPeaks, \ + MeasurementProperties, WaveguidePropertiesMZI +from FlexSensor.MeasurementData.Properties.WaferProperties import WaferProperties +from FlexSensor.MeasurementRoutines.BasemeasurementRoutine import BaseMeasurementRoutine +from FlexSensor.generics.VASInputFileParser import VASInputFileParser, Structure + class MeasurementRoutine(BaseMeasurementRoutine): - def __init__(self, laser: BaseLaserController, ad2device: AD2CaptDeviceController, prober: ProberController, - vaut_config: VAutomatorConfig): - super().__init__(laser, ad2device, prober, vaut_config) + def __init__(self, laser: Laser, ad2device: AD2Dev, prober: Prober.Controller, + config: FlexSensorConfig): + super().__init__(laser, ad2device, prober, 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 + selected_file, self.grouped_structures, self.bookmarks = self.parsed_file.read_file( + input_file=self.config.wafer_config.structure_file.get() ) self.number_of_structures = self.parsed_file.num_of_structs self.number_of_runs = self.parsed_file.num_of_runs + self.config.wafer_config.structure_file.set(selected_file) # 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! @@ -57,19 +56,19 @@ class MeasurementRoutine(BaseMeasurementRoutine): 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}") + f"Init Prober Class. Number of runs per die: {self.number_of_runs}, dies {self.config.wafer_config.dies}\n" + f"Measurement CVS File = {self.config.wafer_config.measurement_output}\n" + f"Measurement Mat File = {self.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}") + self.logger.info(f"<< Input file {self.config.wafer_config.get_structure_file().relative}") + self.logger.info(f">> Working directory {self.config.get_output_directory().relative}") + self.logger.info(f">> Log File {self.config.wafer_config.get_log_file().relative}") + self.logger.info(f">> Measurments CVS File {self.config.wafer_config.get_measurement_output().relative}") + self.logger.info(f">> Measurments Mat File {self.config.wafer_config.get_measurement_mat_file().relative}") + self.logger.info(f">> KLayout Bookmark file {self.config.wafer_config.get_bookmark_file().relative}") + self.logger.info(f">> Scope Image File {self.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. @@ -96,7 +95,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): 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): + for die_idx, die_no in enumerate(self.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) @@ -185,7 +184,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): )) raise e - def _step_snap_image(self, scope_file: VFSObject, fmt): + def _step_snap_image(self, scope_file, 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}") @@ -322,7 +321,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): # 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( + self._step_snap_image(self.config.wafer_config.get_scope_image_file( keywords={"{die}": self.die_no, "{structure}": self.structure.name}), self.formatter) # Search for the light @@ -338,7 +337,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): # 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.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, @@ -347,20 +346,20 @@ class MeasurementRoutine(BaseMeasurementRoutine): 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_csv(str(self.config.wafer_config.get_measurement_output())) self.siph_data.to_excel( - str(self.vaut_config.wafer_config.get_measurement_output()).replace('csv', 'xlsx')) + str(self.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, + f"{self.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}", + f"{self.config.wafer_config.get_measurement_output()}: {e}", traceback.format_exc())) wafer_properties = WaferProperties( - wafer_number=self.vaut_config.wafer_nr, + wafer_number=self.config.wafer_nr, structure_name=self.structure.name, die_nr=self.die_no, chuck_col=self.chuck_col, @@ -375,7 +374,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): wafer_properties) cur_measured_signal._save_mat_file( - filename=self.vaut_config.wafer_config.get_measurement_mat_file(keywords={"{die}": self.die_no, + filename=self.config.wafer_config.get_measurement_mat_file(keywords={"{die}": self.die_no, "{structure}": self.structure.name, "{it}": f"rep_{rep + 1}"}).absolute ) diff --git a/src/FlexSensor/Prober/__init__.py b/src/FlexSensor/Prober/__init__.py index a9885c767677d0fc7299511b1dfe724dd43e186d..8dc2c303fdcfa863000d27b59aeecb7b3cdf4e14 100644 --- a/src/FlexSensor/Prober/__init__.py +++ b/src/FlexSensor/Prober/__init__.py @@ -1,20 +1,31 @@ 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, +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../')) + +from .model.ProberModel import ProberModel as Model +from .model.ProberModel import ProberSignals as Signals +from .view.ProberControlWindow import ProberControlWindow as ControlWindow +from .controller.ProberController import ProberController as Controller +from .controller.OpticalProbesPosition import OpticalProbesPosition as ProbePosition + +if os.getenv("VELOX_SIM") == "TRUE": + from .velox_api.simulator.VeloxSimulator import MessageServerInterface + from .velox_api.simulator.VeloxSimulator import (MessageServerInterface, SetChuckHome, SetMapHome, ReadChuckPosition, ReadChuckHeights, MoveChuck, - SnapImage, GetDieDataAsColRow, StepToDie, ReportKernelVersion) + 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 + try: + from .velox_api.velox.vxmessageserver import MessageServerInterface + from .velox_api.velox import (MessageServerInterface, SetChuckHome, SetMapHome, + ReadChuckPosition, ReadChuckHeights, MoveChuck, + SnapImage, GetDieDataAsColRow, StepToDie, ReportKernelVersion) + except Exception as e: + from .velox_api.simulator.VeloxSimulator import MessageServerInterface + from .velox_api.simulator.VeloxSimulator import (MessageServerInterface, SetChuckHome, SetMapHome, + ReadChuckPosition, ReadChuckHeights, MoveChuck, + SnapImage, GetDieDataAsColRow, StepToDie, + ReportKernelVersion) diff --git a/src/FlexSensor/Prober/controller/MapFileParser.py b/src/FlexSensor/Prober/controller/MapFileParser.py index 570944889faa3228452576403bfa3f93a8857ddf..1c788c8dc78096b00d9dccc8b4755de332ab7ffa 100644 --- a/src/FlexSensor/Prober/controller/MapFileParser.py +++ b/src/FlexSensor/Prober/controller/MapFileParser.py @@ -1,14 +1,35 @@ +import logging +import os +import pathlib from pathlib import Path +from PySide6.QtWidgets import QFileDialog + +from FlexSensor.FlexSensorConfig import FlexSensorConfig +from FlexSensor.Prober.model import ProberModel + class MapFileParser: - def __init__(self, path: str): - print(path) - self._map_path = Path(path) + def __init__(self, model: ProberModel): + self._map_path = self.open_map_file_dialog(Path(model.wafer_map)) + model.wafer_map = self._map_path with open(self._map_path, 'r') as file: self.result = self.parse_content(file.read()) + def open_map_file_dialog(self, file_path): + file_path = pathlib.PurePosixPath(pathlib.Path(file_path).absolute()) + if not os.path.isfile(file_path): + logging.info(f"Configuration file {file_path} not found") + file_dialog = QFileDialog() + file_dialog.setFileMode(QFileDialog.ExistingFile) + file_path, _ = file_dialog.getOpenFileName(None, "Select a Configuration File", filter="*.map") + if file_path != "": + pass + #vaut_config = FlexSensorConfig.load(file_path) + #logging.info(f"Loading configuration file {file_path}") + #logging.info(vaut_config) + return file_path def parse_content(self, content): result = {} current_section = None diff --git a/src/FlexSensor/Prober/controller/ProberController.py b/src/FlexSensor/Prober/controller/ProberController.py index 7486b757787535dd513f8cdd5fdc2d9c975cb130..70a2f9c5c9a512ea8b7ae147b52cd0dbec638383 100644 --- a/src/FlexSensor/Prober/controller/ProberController.py +++ b/src/FlexSensor/Prober/controller/ProberController.py @@ -1,21 +1,18 @@ 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 +import confighandler as Config +#from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig +import FlexSensor.Prober as Prober +from FlexSensor.Prober.controller.OpticalInterface import OpticalInterface +from FlexSensor.Prober.model.ProberModel import ProberModel +from FlexSensor.constants.FlexsensorConstants import Probe +from FlexSensor.generics.generics import pch class ProberController: - def __init__(self, model: ProberModel, vaut_config: VAutomatorConfig, *args, **kwargs): + def __init__(self, model: ProberModel, *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() diff --git a/src/FlexSensor/Prober/controller/__init__.py b/src/FlexSensor/Prober/controller/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2930a2a4e4ce060c8c619c4e63186e106efbcfcd --- /dev/null +++ b/src/FlexSensor/Prober/controller/__init__.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../')) \ No newline at end of file diff --git a/src/FlexSensor/Prober/model/ProberModel.py b/src/FlexSensor/Prober/model/ProberModel.py index 4552abbd0ae40a995bc1e89af7215d52dea2d836..ec97dcfd6cc8da82684eba9c4b907f2a8c4694c3 100644 --- a/src/FlexSensor/Prober/model/ProberModel.py +++ b/src/FlexSensor/Prober/model/ProberModel.py @@ -4,6 +4,8 @@ from PySide6.QtCore import QObject, Signal from MeasurementData.Properties.WaferProperties import WaferProperties +from FlexSensor.FlexSensorConfig import FlexSensorConfig + class ProberSignals(QObject): ''' @@ -39,9 +41,11 @@ class ProberSignals(QObject): class ProberModel: - def __init__(self): + def __init__(self, config: FlexSensorConfig): self.signals = ProberSignals() + self.config = config + self._connected: bool = False self._version: str = "Unknown Version" @@ -56,7 +60,7 @@ class ProberModel: self._errors: list = [] self._warnings: list = [] - self._wafer_map = None + #self._wafer_map = self.config. @property def laser_properties(self) -> WaferProperties: @@ -84,11 +88,11 @@ class ProberModel: @property def wafer_map(self) -> Path: - return self._wafer_map + return self.config.wafer_config.wafermap_file.get() @wafer_map.setter def wafer_map(self, value: Path): - self._wafer_map = value + self.config.wafer_config.wafermap_file.set(value) self.signals.wafer_map_changed.emit(value) @property diff --git a/src/FlexSensor/Prober/model/__init__.py b/src/FlexSensor/Prober/model/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a108a09e59cbfcc1d5cb268a72fa146464bd8fa7 --- /dev/null +++ b/src/FlexSensor/Prober/model/__init__.py @@ -0,0 +1,5 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../')) + diff --git a/src/FlexSensor/Prober/view/ProberControlWindow.py b/src/FlexSensor/Prober/view/ProberControlWindow.py index 2bb990de5bd0b25cafff5f0994a6e6196b01218d..7d88c5b1269d1def5090bc43e019b3eaac7de926 100644 --- a/src/FlexSensor/Prober/view/ProberControlWindow.py +++ b/src/FlexSensor/Prober/view/ProberControlWindow.py @@ -4,14 +4,14 @@ 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 +import confighandler as Config + +#from MapFileParser import MapFileParser +from FlexSensor.Prober.controller.ProberController import ProberController +from FlexSensor.Prober.model.ProberModel import ProberModel +from FlexSensor.Prober.view.widgets.DieGridWidget import DieGridWidget +from FlexSensor.Prober.view.widgets.ProberPositionWidget import ProberPositionWidget +from FlexSensor.Prober.view.widgets.ProberStatusWidget import ProberStatusWidget class ProberControlWindow(QMainWindow): diff --git a/src/FlexSensor/Prober/view/__init__.py b/src/FlexSensor/Prober/view/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2930a2a4e4ce060c8c619c4e63186e106efbcfcd 100644 --- a/src/FlexSensor/Prober/view/__init__.py +++ b/src/FlexSensor/Prober/view/__init__.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '../')) \ No newline at end of file diff --git a/src/FlexSensor/Prober/view/widgets/DieGridWidget.py b/src/FlexSensor/Prober/view/widgets/DieGridWidget.py index b1e365e4dbebf20a048955440605885261ef55c4..3ab5b6818cecd585d697ef85b245d25e744c9419 100644 --- a/src/FlexSensor/Prober/view/widgets/DieGridWidget.py +++ b/src/FlexSensor/Prober/view/widgets/DieGridWidget.py @@ -3,8 +3,8 @@ 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 +from FlexSensor.Prober.controller.MapFileParser import MapFileParser +from FlexSensor.Prober.model.ProberModel import ProberModel class FlatButton(QPushButton): @@ -137,7 +137,7 @@ class DieGridWidget(QWidget): super(DieGridWidget, self).__init__() self._model = model - parsed_map = MapFileParser(str(self._model.wafer_map)) + parsed_map = MapFileParser(model) self.setWindowTitle("Die Grid Widget") self._dies = {} diff --git a/src/FlexSensor/WaferConfig.py b/src/FlexSensor/WaferConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..94fb4f5a20bb15747126b86c7bf52a47ce059c7a --- /dev/null +++ b/src/FlexSensor/WaferConfig.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +""" +Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> +Created: 2023-10-19 12:35 +Package Version: +""" +import confighandler as cfg + + +class WaferConfig(cfg.ConfigNode): + + def __init__(self) -> None: + super().__init__() + self.dies = cfg.Field("MaskARY1_Jakob_full") + self.structure_file = cfg.Field("../vas-files/list_of_structures_picasso.vas") + self.wafermap_file = cfg.Field("../Wafermapary1_48dies.map") + self.log_file = cfg.Field("{output_directory}/log_{date_time}.log") + self.measurement_output = cfg.Field("{output_directory}/measurement/measurement_{date_time}.csv") + self.measurement_mat_file = cfg.Field("{output_directory}/measurement/measurement_die_{die}_struct_{structure}_{date_time}_{it}.mat") + self.scope_image_file = cfg.Field("{output_directory}/scope_shots/scope_{wafer_nr}_die_{die}_struct_{structure}_{time}.png") + self.bookmark_file = cfg.Field("{output_directory}/klayout_bookmarks/bookmarks_{wafer_version}.lyb") + + + + self.register() + diff --git a/src/FlexSensor/__init__.py b/src/FlexSensor/__init__.py index 81dab0e1c8728d9d20fda311be5ccfd69e7324e7..e475ef5f305490a37b56f7ee6ccd7797247fe346 100644 --- a/src/FlexSensor/__init__.py +++ b/src/FlexSensor/__init__.py @@ -2,6 +2,18 @@ import os import pathlib import sys -from flexsensorpy.__version__ import __version__ +from .__version__ import __version__ -__all__ = [] +#from .Prober import Prober + + +from .generics import ConsoleWindow as Console + +from .__version__ import __version__ +from .MainWindow.controller.MainThreadController import MainThreadController +from .MainWindow.model.MainThreadModel import MainThreadModel +from .MainWindow.view.MainThreadView import MainWindow +from .MainWindow.view.SplashScreen import SplashScreen +from .generics.ApplicationInit import ApplicationInit +from .generics.ConsoleWindow import ConsoleWindow +from .pathes import configs_root diff --git a/src/FlexSensor/generics/ApplicationInit.py b/src/FlexSensor/generics/ApplicationInit.py new file mode 100644 index 0000000000000000000000000000000000000000..dbbe4b2810311a8724cc57d9a8752fa8b15cdca9 --- /dev/null +++ b/src/FlexSensor/generics/ApplicationInit.py @@ -0,0 +1,60 @@ +import logging +import os +import pathlib + +from PySide6 import QtGui, QtCore +from PySide6.QtWidgets import QFileDialog +from rich.logging import RichHandler + +from FlexSensor.FlexSensorConfig import FlexSensorConfig +from FlexSensor.generics.ConsoleWindow import ConsoleWindow +from FlexSensor.pathes import image_root + +import confighandler as Conf +class ApplicationInit: + + @staticmethod + def set_icon(app): + app_icon = QtGui.QIcon() + app_icon.addFile(f'{image_root}/FlexSensorIcon.png', QtCore.QSize(16, 16)) + app_icon.addFile(f'{image_root}/FlexSensorIcon.png', QtCore.QSize(24, 24)) + app_icon.addFile(f'{image_root}/FlexSensorIcon.png', QtCore.QSize(32, 32)) + app_icon.addFile(f'{image_root}/FlexSensorIcon.png', QtCore.QSize(48, 48)) + app_icon.addFile(f'{image_root}/FlexSensorIcon.png', QtCore.QSize(256, 256)) + app.setWindowIcon(app_icon) + + @staticmethod + def load_config_file(file_path): + file_path = pathlib.PurePosixPath(pathlib.Path(file_path).absolute()) + if not os.path.isfile(file_path): + logging.info(f"Configuration file {file_path} not found") + file_dialog = QFileDialog() + file_dialog.setFileMode(QFileDialog.ExistingFile) + file_path, _ = file_dialog.getOpenFileName(None, "Select a Configuration File") + # check if file dialog cancle was clicked + vaut_config = FlexSensorConfig() + if file_path != "": + vaut_config = FlexSensorConfig.load(file_path) + logging.info(f"Loading configuration file {file_path}") + logging.info(vaut_config) + return vaut_config + + @staticmethod + 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/VASInputFileParser.py b/src/FlexSensor/generics/VASInputFileParser.py new file mode 100644 index 0000000000000000000000000000000000000000..73eda1a89860792aaf51f328a613745cd341c5cf --- /dev/null +++ b/src/FlexSensor/generics/VASInputFileParser.py @@ -0,0 +1,388 @@ + +import ast +import logging +import os +import pathlib + +import confighandler +from PySide6.QtWidgets import QFileDialog + + +#import velox.controller.velox_config as velox_config + +class Structure: + + def __init__(self, name: str, x_in: int, y_in: int, x_out: int, y_out: int, enabled: bool, repetitions: int): + self.name = name + self.x_in = x_in # x coordinate of the input point + self.y_in = y_in # y coordinate of the input point + self.x_out = x_out # x coordinate of the output point + self.y_out = y_out # y coordinate of the output point + self.enabled = bool(enabled) # True if the structure is enabled + self.repetitions = repetitions # Number of repeated measurements of the structure + + self.is_reference(False) + self.in_out_diff_x = self.x_in - self.x_out + self.in_out_diff_y = self.y_in - self.y_out + + self.measurement_valid = False + + def __str__(self) -> str: + return (f"{self.repetitions} x Structure ({self.name}, {self.enabled}): " + f"IN ({self.x_in}, {self.y_in}), " + f"OUT ({self.x_out} {self.y_out})") + + def __repr__(self) -> str: + return (f"{self.repetitions} x Structure ({self.name}, {self.enabled}): " + f"IN ({self.x_in}, {self.y_in}), " + f"OUT ({self.x_out} {self.y_out})") + + def is_reference(self, is_reference: bool = False): + if isinstance(is_reference, bool): + self.is_reference = is_reference + return self.is_reference + +class VASInputFileParser(): + + def __init__(self) -> None: + self.logger = logging.getLogger("ParseInputFile") + self.grouped_structures = {} + + self.list_of_structures = {} + self.list_of_bookmarks = {} + self.num_of_structs = 0 + self.num_of_runs = 0 + + + + def convert(self, key, value): + value = ast.literal_eval(f"{value}") + return key, value + + def parse_line(self, line): + line = line.strip() + # check if line is empty + line_split = line.split('=') + if len(line_split) == 2: + key = line_split[0].strip().replace(' ', '') + value = line_split[1].strip().replace(' ', '') + else: + raise Exception(f"More than 2 parameters extracted. Expected 2 in line {line}") + + return key, value + + def as_bookmark(self, key, value): + self.list_of_bookmarks[key] = value + + def as_single_struct(self, key, value): + # convert to structure + if "enabled" not in value: + value['enabled'] = True + + if "repetitions" not in value: + value['repetitions'] = 1 + + structure = Structure( + key, + int(value['x_in']), int(value['y_in']), + int(value['x_out']), int(value['y_out']), + int(value['enabled']), + int(value['repetitions'])) + + self.list_of_structures[key] = structure + self.num_of_runs += structure.repetitions + return [(key, structure)] + + + def as_sequential_structs(self, key, value): + cur_list_of_structures = [] + num = value['num'] + spacing = 0 + + for idx in range(num): + if idx > 0: + spacing = value['spacing'] + + value['y_in'] = value['y_in'] + spacing + value['y_out'] = value['y_out'] + spacing + key_seq = f"{key}_{idx+1}" + structs = self.as_single_struct(key_seq, value)[0] + cur_list_of_structures.append((structs[0], structs[1])) + + return cur_list_of_structures + + def open_file_dialog(self, file_path): + file_path = pathlib.PurePosixPath(pathlib.Path(file_path).absolute()) + if not os.path.isfile(file_path): + logging.info(f"VAS file {file_path} not found") + file_dialog = QFileDialog() + file_dialog.setFileMode(QFileDialog.ExistingFile) + file_path, _ = file_dialog.getOpenFileName(None, "Select a VAS File", filter ="*.vas") + if file_path != "": + pass + return file_path + + def read_file(self, input_file) -> (pathlib.Path, dict, list): + current_group = None + cur_list_of_structures = {} + structs = [] + #list_of_structures = {} + self.logger.info(f"Reading input file: {input_file} of type type {type(input_file)}") + if isinstance(input_file, pathlib.Path): + input_file = str(input_file.absolute()) + input_file = self.open_file_dialog(input_file) + + with open(input_file, 'r') as f: + for idx, line in enumerate(f): + # check if line is empty + if line.startswith('#') or len(line.strip().replace(' ', '')) == 0: + continue + + key, value = self.parse_line(line) + if key == "group": + if len(cur_list_of_structures) > 0: + self.grouped_structures[current_group] = cur_list_of_structures + cur_list_of_structures = {} + structs = [] + current_group = value + continue + else: + key, value = self.convert(key, value) + + #list_of_structures[key] = value + if "bookmark" in key: + self.as_bookmark(key, value) + elif ("num" in value) and ("spacing" in value): + structs = self.as_sequential_structs(key, value) + else: + structs = self.as_single_struct(key, value) + + # convert to dictionary + for struct in structs: + cur_list_of_structures[struct[0]] = struct[1] + + if len(cur_list_of_structures) > 0: + self.grouped_structures[current_group] = cur_list_of_structures + cur_list_of_structures = {} + + self.num_of_structs = len( + [ + key for key in self.list_of_structures if self.list_of_structures[key].enabled == True + ] + ) + return pathlib.Path(input_file), self.grouped_structures, self.list_of_bookmarks + + # @staticmethod + # def read_input(vaut_config: velox_config.VAutomatorConfig): + # filename_rel = vaut_config.automator_config.structure_file.rel + # filename = vaut_config.automator_config.structure_file.abs + # ParseInputFile.logger.info("Reading input file: %s" % filename_rel) + + + # number_of_structures = 0 + + # list_of_structure_groups = [] + # list_of_bookmarks = [] + # list_of_structs_sub = [] + + # with open(filename, 'r') as f: + + # for idx, line in enumerate(f): + # line = line.strip() + + # if line.strip().startswith('#') or line.strip().replace(' ', '') == '': + # continue # skip comment lines + # else: + # line_split = line.split('=') + # if len(line_split) == 2: + # varname = line_split[0].strip().replace(' ', '') + # varcontent = line_split[1].strip().replace(' ', '') + # else: + # raise Exception("Error in line %d: %s" % (idx, line)) + + # if cmd != line.replace(' ', ''): + # raise ValueError( + # "Error parsing command, could not correctly seperate the string." + # "\nPlease check your input line %d:\nin >> '%s'\nout << '%s'" + # % (idx, line.replace(' ', ''), cmd)) + + # # Parse the lines + # if "bookmark" in line: + # cmd = ("%s=%s" % (varname, varcontent)).strip() + # # Check if command is the same + # if cmd != line.replace(' ', ''): + # raise ValueError( + # "Error parsing command, could not correctly seperate the string." + # "\nPlease check your input line %d:\nin >> '%s'\nout << '%s'" + # % (idx, line.replace(' ', ''), cmd)) + # else: + # setattr(ParseInputFile, varname, {}) + # # Exec ( assign the value to the attribute) + # exec("%s.%s" % ("ParseInputFile", cmd) ) + # # retrieve the value als correct type + # var_content = getattr(ParseInputFile, varname) + # # Add this structure to the list + # list_of_bookmarks.append({varname:var_content} ) + # #-uc-# print("Bookmark %s" % list_of_bookmarks[-1]) + # # Only if we have the keyword "spacing" and "num" in line, then proceed + # elif ("num" in line) and ("spacing" in line): + + # cmd = ("%s=%s" % (varname, varcontent)).strip() + # # Check if command is the same + # if cmd != line.replace(' ', ''): + # raise ValueError( + # "Error parsing command, could not correctly seperate the string." + # "\nPlease check your input line %d:\nin >> '%s'\nout << '%s'" + # % (idx, line.replace(' ', ''), cmd)) + # else: + # # Set the attribute for later accessing + # setattr(ParseInputFile, varname, {}) + # # Exec ( assign the value to the attribute) + # exec("%s.%s" % ("ParseInputFile", cmd) ) + # # retrieve the value als correct type + # var_content = getattr(ParseInputFile, varname) + # try: + # if var_content['num'] <= 0: + # raise ValueError("'num': Number of structur list can not be zero or below. Error in line %d: %s" % (idx, line)) + # except: + # raise ValueError("'num' keyword not found in dictionry. Error in line %d: %s" % (idx, line)) + + # try: + # if var_content['spacing'] == 0: + # raise ValueError("'spacing': Spacing can not be zero. Error in line %d: %s" % (idx, line)) + # except: + # raise ValueError("'spacing' keyword not found in dictionry. Error in line %d: %s" % (idx, line)) + + + + # for idx in range(0, var_content['num']): + # try: + # num_start = var_content['start'] + 1 + # except: + # num_start = 1 + + # y_in_temp = var_content['y_in'] + idx * var_content['spacing'] + # y_out_temp = var_content['y_out'] + idx * var_content['spacing'] + # x_in_temp = var_content['x_in'] + # x_out_temp = var_content['x_out'] + # if 'rep' not in var_content: + # var_content['rep'] = 1 + + # var_content_tmp ={ + # 'x_in': x_in_temp, + # 'y_in': y_in_temp, # Convert y-axis to negative values + # 'x_out': x_out_temp, + # 'y_out': y_out_temp, # Convert y-axis to negative values + # 'in_out_diff_x' :x_in_temp - x_out_temp, + # 'in_out_diff_y' :y_in_temp - y_out_temp, + # 'enabled': True, + # 'rep': var_content['rep'] + # } + # list_of_structs_sub.append( {varname+"_"+str(idx+num_start):var_content_tmp} ) + # number_of_structures += var_content['num'] + # elif "group" in line: + # groupname = line_split[1].strip().replace(' ', '') + + # if list_of_structs_sub == []: + # #-uc-# print ("Init group %s" % groupname) + # list_of_structs_sub = [] + # else: + + # if list_of_structs_sub != []: + # #-uc-# print ("Adding data %s to list" % (list_of_structs_sub)) + # list_of_structure_groups.append(list_of_structs_sub) + # #-uc-# print ("New group %s, reset group" % groupname) + # list_of_structs_sub = [] + # else: + # cmd = ("%s=%s" % (varname, varcontent)).strip() + # # Check if command is the same + # if cmd != line.replace(' ', ''): + # raise ValueError( + # "Error parsing command, could not correctly seperate the string." + # "\nPlease check your input line %d:\nin >> '%s'\nout << '%s'" + # % (idx, line.replace(' ', ''), cmd)) + # else: + # # Set the attribute for later accessing + # setattr(ParseInputFile, varname, {}) + # # Exec ( assign the value to the attribute) + # exec("%s.%s" % ("ParseInputFile", cmd) ) + # # retrieve the value als correct type + # var_content = getattr(ParseInputFile, varname) + # if 'rep' not in var_content: + # var_content['rep'] = 1 + # # Add this structure to the list + # try: + # var_content_tmp ={ + # 'x_in': var_content['x_in'], + # 'y_in': var_content['y_in'], + # 'x_out': var_content['x_out'], + # 'y_out': var_content['y_out'], + # 'in_out_diff_x' : var_content['x_in'] - var_content['x_out'], + # 'in_out_diff_y' : var_content['y_in'] - var_content['y_out'], + # 'enabled': True, + # 'rep': var_content['rep'] + # } + # except: + # raise ValueError("Error in line %d: %s" % (idx, line)) + # list_of_structs_sub.append( {varname:var_content_tmp} ) + # number_of_structures += 1 + + + # # Append the last group + # if list_of_structs_sub != []: + # #-uc-# print ("Adding last data %s to list" % (list_of_structs_sub)) + # list_of_structure_groups.append(list_of_structs_sub) + # #-uc-# print ("Last group %s" % groupname) + # list_of_structs_sub = [] + + # #print(len(list_of_structure_groups)) + # # for gr in list_of_structure_groups: + # # print("Group: %s\n\n" % gr) + # ParseInputFile.logger.info("Total number of structures to process %s" % number_of_structures) + # return list_of_structure_groups, list_of_bookmarks, number_of_structures + + def write_bookmarks( + self, cell_name="MaskARY1_final_2020_Feb_14", + bookmark_file="bookmarks.lyb" + ): + print(f"Writing bookmarks to file {bookmark_file}") + + with open(bookmark_file, 'w+') as f: + f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<bookmarks>\n") + for bookmark in self.list_of_bookmarks: + print(f"{bookmark}: {bookmarks[bookmark]}") + for key in bookmark: + bookmar_string = ( + "<bookmark>\n" + + " <name>" + str(bookmark) + "</name>\n" + + " <x-left>" + str(bookmarks[bookmark]['x_left']) + "</x-left>\n" + + " <x-right>" + str(bookmarks[bookmark]['x_right']) + "</x-right>\n" + + " <y-bottom>" + str(bookmarks[bookmark]['y_bottom']) + "</y-bottom>\n" + + " <y-top>" + str(bookmarks[bookmark]['y_top']) + "</y-top>\n" + + " <min-hier>0</min-hier>\n" + + " <max-hier>9</max-hier>\n" + + " <cellpaths>\n" + + " <cellpath>\n" + + " <cellname>" + str(cell_name) + "</cellname>\n" + + " </cellpath>\n" + + " </cellpaths>\n" + + "</bookmark>" + ) + + f.write(bookmar_string + "\n") + f.write("</bookmarks>") + + +# pi = ParseInputFile() +# grouped_structures, bookmarks = pi.read_file(input_file="./list_of_structures.vas") + + +# for groups in grouped_structures: +# print(f"Group *{groups}*") +# for structs in grouped_structures[groups]: +# print(f" -> {grouped_structures[groups][structs]}") + +# #for bookmark in bookmarks: +# # print(f"{bookmark}: {bookmarks[bookmark]}") + +# print(pi.num_of_runs) \ No newline at end of file diff --git a/src/FlexSensor/generics/logger.py b/src/FlexSensor/generics/logger.py index 89c95c6eca27bb4d0b69a51b51e101f69dfe0cef..490f6160860796b4a5cb28b34823cf94ac5b4314 100644 --- a/src/FlexSensor/generics/logger.py +++ b/src/FlexSensor/generics/logger.py @@ -3,19 +3,17 @@ 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 +from scipy.signal import find_peaks # , find_peaks_cwt import os -#from PySide6.QtNetwork import QAbstractSocket +# 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 + +from src.FlexSensor.generics.ConsoleWindow import ConsoleWindow class QTextEditLogger(logging.Handler, QtCore.QObject): @@ -34,14 +32,14 @@ class QTextEditLogger(logging.Handler, QtCore.QObject): 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" + FORMAT = "%Y-%m-%d %H-%M-%S.%f" @staticmethod def check_or_create_log_file(): @@ -50,96 +48,79 @@ class Logger: 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.") + except OSError as exc: + raise Exception("Could not create log file.") Logger.info("Log file created: %s" % Logger.log_file_full) - @staticmethod + @staticmethod def debug(*args): - msg = datetime.now().strftime(Logger.FORMAT) + " [DEBUG] " + "".join(str(arg) for arg in 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() + # 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;') + 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) + msg = datetime.now().strftime(Logger.FORMAT) + " [INFO] " + "".join(str(arg) for arg in args) # check if folder exists - #logger.check_or_create_log_file() + # 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;') + + # 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) + msg = datetime.now().strftime(Logger.FORMAT) + " [WARN] " + "".join(str(arg) for arg in args) # check if folder exists - #logger.check_or_create_log_file() + # logger.check_or_create_log_file() with open(Logger.log_file_full, "a+") as f: - f.write(msg+ "\n") + f.write(msg + "\n") - #status_bar.showMessage("[WARN] " + "".join(str(arg) for arg in args)) - #status_bar.setStyleSheet('border: 0; color: orange;') + # 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) + msg = datetime.now().strftime(Logger.FORMAT) + " [ERROR] " + "".join(str(arg) for arg in args) # check if folder exists - #logger.check_or_create_log_file() + # 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;') + + # 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) + msg = datetime.now().strftime(Logger.FORMAT) + " [FATAL] " + "".join(str(arg) for arg in args) # check if folder exists - #logger.check_or_create_log_file() + # 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;') + + # 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/pathes.py b/src/FlexSensor/pathes.py new file mode 100644 index 0000000000000000000000000000000000000000..c0b004bf495a66c22a932eac274a39f53dd022e3 --- /dev/null +++ b/src/FlexSensor/pathes.py @@ -0,0 +1,14 @@ +# PLace here your interpreter startup folder relative to ./flexsensor +# e.g. +# -> interpreter path C:\flexsensor +# -> source path C:\flexsensor\flexsensorpy +# content_root = './flexsensorpy' +import os +import pathlib + +content_root = "." + +# DO not change this unless you know what you are doing! +image_root = str(pathlib.Path(f"{content_root}/../images").resolve().absolute()) +libs_root = str(pathlib.Path(f"{content_root}/libs").resolve().absolute()) +configs_root = str(pathlib.Path(f"{content_root}/../configs").resolve().absolute())