diff --git a/.idea/flexsensor.iml b/.idea/flexsensor.iml index 0e3b1929902b2190c6124e46ca66f77568a49df2..0070e873e3f555948a9ec0566e7348283bccc0cb 100644 --- a/.idea/flexsensor.iml +++ b/.idea/flexsensor.iml @@ -1,32 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> -<module type="PYTHON_MODULE" version="4"> - <component name="NewModuleRootManager"> - <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.10 (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> +<module version="4"> <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/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py b/examples/MeasurementRoutine.py similarity index 92% rename from src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py rename to examples/MeasurementRoutine.py index b8e1fde3ab1edf8421cf73b7141e70072b6a8f31..20b693e0bd80f7644f60df2da5c72ecb3f12a1b4 100644 --- a/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py +++ b/examples/MeasurementRoutine.py @@ -1,4 +1,5 @@ import logging +import sys import time import traceback from datetime import datetime @@ -8,31 +9,41 @@ import LaserControl as Laser import mcpy import pandas as pd from PySide6.QtCore import Slot -from constants.FlexsensorConstants import Probe -from generics.generics import pch -import FlexSensor.Prober as Prober -from FlexSensor.FlexSensorConfig import FlexSensorConfig +import FlexSensor as fs +from FlexSensor import Prober + from FlexSensor.MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData -from FlexSensor.MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties -from FlexSensor.MeasurementData.Properties.LaserProperties import LaserProperties -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 +from FlexSensor.Prober.controller.OpticalInterface import Probe +from Properties import AD2CaptDeviceProperties +from Properties import LaserProperties +from Properties.MeasurementProperties import WaveguidePropertiesMZI, MeasurementProperties, \ + MPropertiesFindPeaks +from Properties.WaferProperties import WaferProperties + +sys.path.append('./src') + +# from FlexSensor.FlexSensorConfig import FlexSensorConfig +# from FlexSensor.MeasurementData.MeasuredData.SingleMeasuredData import SingleMeasuredData +# from FlexSensor.MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties +# from FlexSensor.MeasurementData.Properties.LaserProperties import LaserProperties +# 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): +class MeasurementRoutine(fs.BaseMeasurementRoutine): def __init__(self, laser: Laser, ad2device: AD2Dev, prober: Prober.Controller, - config: FlexSensorConfig): + config: fs.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.parsed_file = fs.VASInputFileParser() selected_file, self.grouped_structures, self.bookmarks = self.parsed_file.read_file( input_file=self.config.wafer_config.structure_file.get() @@ -92,7 +103,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): # self._init_ad2device_signals() self._write_info( - f"{pch('=', 50)} Starting measurement {pch('=', 50)}") + f"{self.pch('=', 50)} Starting measurement {self.pch('=', 50)}") # === Check contact height print(self.prober) @@ -139,7 +150,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): # If implementing multiple routines, and the steps may occure multiple times, move them to # the base class instead of reimplementing/copying! # ================================================================================================================== - def _step_place_input_probe(self, structure: Structure, fmt): + def _step_place_input_probe(self, structure: fs.Structure, fmt): """ Places the chuck, thus the input probe, such that the probe is on the correct position. Move the chuck to the given position. Since the input probe stays on the same position, @@ -296,11 +307,11 @@ class MeasurementRoutine(BaseMeasurementRoutine): raise e # Routine for measuring one structure - def _measure_structure(self, die_no: int, structure: Structure, structure_idx: int): + def _measure_structure(self, die_no: int, structure: fs.Structure, structure_idx: int): """Routine for measuring one structure """ - self.structure: Structure = structure + self.structure: fs.Structure = structure self.formatter = f"[Measurement. Die {die_no}]: {self.structure.name} |" timestamp = datetime.now().strftime('%d/%m/%Y %H:%M:%S.%f') diff --git a/src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py b/examples/Properties/AD2CaptDeviceProperties.py similarity index 96% rename from src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py rename to examples/Properties/AD2CaptDeviceProperties.py index 231b75c81572eb64175920632ffaeb01129645e7..a6b864929eb2c1aac76d4f8a9cd45c2ced4f2d61 100644 --- a/src/FlexSensor/MeasurementData/Properties/AD2CaptDeviceProperties.py +++ b/examples/Properties/AD2CaptDeviceProperties.py @@ -1,6 +1,6 @@ import pandas as pd -from MeasurementData.Properties.GenericProperties import GenericProperties +from FlexSensor.generics.GenericProperties import GenericProperties class AD2CaptDeviceProperties(GenericProperties): diff --git a/src/FlexSensor/MeasurementData/Properties/GenericProperties.py b/examples/Properties/GenericProperties.py similarity index 100% rename from src/FlexSensor/MeasurementData/Properties/GenericProperties.py rename to examples/Properties/GenericProperties.py diff --git a/src/FlexSensor/MeasurementData/Properties/LaserProperties.py b/examples/Properties/LaserProperties.py similarity index 96% rename from src/FlexSensor/MeasurementData/Properties/LaserProperties.py rename to examples/Properties/LaserProperties.py index ce91215b5571c1584f8f9f4ab52d48a29aa07601..04779cc7afa3ba88a1c89b453aca99c27d85951d 100644 --- a/src/FlexSensor/MeasurementData/Properties/LaserProperties.py +++ b/examples/Properties/LaserProperties.py @@ -1,11 +1,12 @@ import sys -from MeasurementData.Properties.GenericProperties import GenericProperties #import mcpy #sys.path.append('../mcpy/mcpy') import mcpy +from FlexSensor.generics.GenericProperties import GenericProperties + class LaserProperties(GenericProperties): diff --git a/src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py b/examples/Properties/MeasurementProperties.py similarity index 98% rename from src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py rename to examples/Properties/MeasurementProperties.py index 12d544401fb913e439ae3a36cd30743c0472ca0c..9bbe12bc85d190dba3eb1f21b45b8b40a194451e 100644 --- a/src/FlexSensor/MeasurementData/Properties/MeasurementProperties.py +++ b/examples/Properties/MeasurementProperties.py @@ -4,7 +4,7 @@ from PySide6.QtCore import Signal import mcpy from mcpy import Uncertainty, MCSamples -from MeasurementData.Properties.GenericProperties import GenericProperties +from FlexSensor.generics.GenericProperties import GenericProperties class MPropertiesFindPeaks(GenericProperties): diff --git a/src/FlexSensor/MeasurementData/Properties/WaferProperties.py b/examples/Properties/WaferProperties.py similarity index 97% rename from src/FlexSensor/MeasurementData/Properties/WaferProperties.py rename to examples/Properties/WaferProperties.py index 546de51e3e227faafd3c2a2b8e9f750eb8a95135..a46e3be03dac548d7a5909c32b9f90fafc6c5a4b 100644 --- a/src/FlexSensor/MeasurementData/Properties/WaferProperties.py +++ b/examples/Properties/WaferProperties.py @@ -1,6 +1,4 @@ - - -from MeasurementData.Properties.GenericProperties import GenericProperties +from FlexSensor.generics.GenericProperties import GenericProperties class WaferProperties(GenericProperties): diff --git a/examples/main.py b/examples/main.py index d93dd730418bc4d0d9e0aa6c85b2f55d8783f84e..fc13428c58d93910b88b937bc127f0a788bf72e8 100644 --- a/examples/main.py +++ b/examples/main.py @@ -9,8 +9,13 @@ import sys import time from PySide6.QtWidgets import QApplication +# set env variable VELOX_SIM=TRUE +# to use the simulator instead of the real hardware +import os +os.environ["VELOX_SIM"] = "TRUE" sys.path.append('./src') +from MeasurementRoutine import MeasurementRoutine import FlexSensor def main(argv): @@ -37,7 +42,7 @@ def main(argv): main_model = FlexSensor.MainThreadModel(config=config) #wdg = config.view.widget() #wdg.show() - main_controller = FlexSensor.MainThreadController(main_model) + main_controller = FlexSensor.MainThreadController(main_model, MeasurementRoutine) main_window = FlexSensor.MainWindow(main_model, main_controller) # test_win = StructureSelector() diff --git a/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py b/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py index 69a77e60cdb79f970e9786da1b4072fb3e040af3..c417978445733ef3ca4dee61ecbb1d5afe21f7f8 100644 --- a/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py +++ b/src/FlexSensor/InitialSetupWizard/pages/FifthPage.py @@ -4,6 +4,8 @@ import Prober as Prober from InitialSetupWizard.pages.ForthPage import ForthWizardPage from InitialSetupWizard.pages.WizardPage import WizardPage +import FlexSensor.Prober.controller.OpticalInterface + class FifthWizardPage(WizardPage): def __init__(self, prober: Prober.Controller, page_input_distance: ForthWizardPage, parent: QWizard = None): @@ -59,15 +61,15 @@ class FifthWizardPage(WizardPage): def train(self, distance, safe_move_distance): # First read out both positions - x_in, y_in, z_in, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=Prober.Probe.INPUT) - x_out, y_out, z_out, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=Prober.Probe.OUTPUT) + x_in, y_in, z_in, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=FlexSensor.Prober.controller.OpticalInterface.Probe.INPUT) + x_out, y_out, z_out, _, _, _ = self.prober.opt_if.set_optical_probe_home(probe=FlexSensor.Prober.controller.OpticalInterface.Probe.OUTPUT) pos = Prober.ProbePosition(input=(x_in, y_in, z_in), output=(x_out, y_out, z_out)) print(pos) # Now move the input probe away from the position # INPUT -safe_move_distance #=================================================================================== self.logger.info(f"Moving input probe {-safe_move_distance}um.") - self.prober.opt_if.move_optical_probe(Prober.Probe.INPUT, -safe_move_distance, '0', 'R') + self.prober.opt_if.move_optical_probe(FlexSensor.Prober.controller.OpticalInterface.Probe.INPUT, -safe_move_distance, '0', 'R') self.logger.info(f"Moved input probe {-safe_move_distance}um.") # ============================================================================================================== @@ -78,7 +80,7 @@ class FifthWizardPage(WizardPage): f"Make sure that the output probe has been moved!", title="Optical output probe are about to move", ): - self.prober.opt_if.move_optical_probe(Prober.Probe.OUTPUT, -distance, '0', 'R') + self.prober.opt_if.move_optical_probe(FlexSensor.Prober.controller.OpticalInterface.Probe.OUTPUT, -distance, '0', 'R') self.logger.info(f"Moved output probe {-distance}um.") else: self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") @@ -86,13 +88,13 @@ class FifthWizardPage(WizardPage): # ============================================================================================================== # ============================================================================================================== - self.prober.opt_if.set_optical_probe_home(Prober.Probe.OUTPUT) + self.prober.opt_if.set_optical_probe_home(FlexSensor.Prober.controller.OpticalInterface.Probe.OUTPUT) self.logger.info(f"Set optical output home to current position") # ============================================================================================================== # OUTPUT distance ============================================================================================== self.logger.info(f"Moving output probe {distance}um back to initial position ") - self.prober.opt_if.move_optical_probe(Prober.Probe.OUTPUT, distance, '0', 'R') + self.prober.opt_if.move_optical_probe(FlexSensor.Prober.controller.OpticalInterface.Probe.OUTPUT, distance, '0', 'R') # ============================================================================================================== # INPUT safe_move_distance ===================================================================================== @@ -102,7 +104,7 @@ class FifthWizardPage(WizardPage): f"Make sure that the output probe position has been reset!", title="Optical output probe are about to move" ): - self.prober.opt_if.move_optical_probe(Prober.Probe.INPUT, safe_move_distance, '0', 'R') + self.prober.opt_if.move_optical_probe(FlexSensor.Prober.controller.OpticalInterface.Probe.INPUT, safe_move_distance, '0', 'R') self.logger.info(f"Moved input probe {safe_move_distance}.") else: self.display_mbox_error(text="The movement has been aborted by the user.", title="Movement Aborted.") diff --git a/src/FlexSensor/MainWindow/controller/MainThreadController.py b/src/FlexSensor/MainWindow/controller/MainThreadController.py index e73b03633fd98b6e081582daaffd2b5ac053e9da..97b2adb8f3137517009a7f1e8d5842eadbe05de4 100644 --- a/src/FlexSensor/MainWindow/controller/MainThreadController.py +++ b/src/FlexSensor/MainWindow/controller/MainThreadController.py @@ -1,19 +1,16 @@ import logging +from typing import Type from PySide6.QtCore import QThread, Signal -import confighandler import LaserControl as Laser import CaptDeviceControl as AD2Dev -import Prober as Prober -import MeasurementEvaluationTool - from ..model.MainThreadModel import MainThreadModel -from FlexSensor.MeasurementRoutines.MeasurementRoutine import MeasurementRoutine -from Prober.controller.ProberController import ProberController +from ... import Prober from ...FSBase import FSBase +from ...MeasurementRoutines.BaseMeasurementRoutine import BaseMeasurementRoutine class MainThreadController(FSBase, object): @@ -21,6 +18,7 @@ class MainThreadController(FSBase, object): on_start_laser_sweep = Signal(name='on_start_laser_sweep') def __init__(self, model: MainThreadModel, + measurement_routine: Type[BaseMeasurementRoutine], enable_log: bool = True, log_level: int = logging.DEBUG, log_file: str = "flexsensor.log"): super().__init__() @@ -59,7 +57,7 @@ class MainThreadController(FSBase, object): self._device_initialization() # Load the measurement routine - self.model.measurement_routine = self._load_measurement_routine() + self.model.measurement_routine = self._load_measurement_routine(measurement_routine) # Thread for the measurement routine self.measurement_thread = QThread() @@ -107,7 +105,7 @@ class MainThreadController(FSBase, object): self.measurement_thread.started.connect(measurement_routine.run) self.logger.debug("Moved worker/measurement routine to thread and connected the signals.") - def _load_measurement_routine(self) -> MeasurementRoutine: + def _load_measurement_routine(self, measurement_routine: Type[BaseMeasurementRoutine]) -> BaseMeasurementRoutine: """ Loads the measurement routine and initializes it. @@ -120,13 +118,13 @@ class MainThreadController(FSBase, object): # if not self.device_are_init: # raise Exception("Some or all devices have not been initialized. First call `_device_initialization()`!") - measurement_routine = MeasurementRoutine( + _measurement_routine = measurement_routine( self.model.laser_controller, self.model.ad2_controller, self.model.prober_controller, self.model.config) self.logger.debug("Initialized MeasurementRoutine.") - return measurement_routine + return _measurement_routine def _device_initialization(self): """ diff --git a/src/FlexSensor/MainWindow/model/MainThreadModel.py b/src/FlexSensor/MainWindow/model/MainThreadModel.py index c267f7f5920b5f170fcd65f9f91eb5d4bf6e7d7f..b5b44eddc21dda9560d076c3af88a9a8ad0e1083 100644 --- a/src/FlexSensor/MainWindow/model/MainThreadModel.py +++ b/src/FlexSensor/MainWindow/model/MainThreadModel.py @@ -9,8 +9,9 @@ import confighandler as Config import MeasurementEvaluationTool as met # import ConfigHandler as Config -from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine +#from MeasurementRoutines.MeasurementRoutine import MeasurementRoutine from FlexSensor.FlexSensorConfig import FlexSensorConfig +from FlexSensor.MeasurementRoutines.BaseMeasurementRoutine import BaseMeasurementRoutine class MainThreadSignals(QObject): @@ -20,7 +21,7 @@ class MainThreadSignals(QObject): ad2_changed = Signal(AD2Dev.Model, AD2Dev.Controller, AD2Dev.View) prober_changed = Signal(Prober.Model, Prober.Controller, Prober.ControlWindow) - measurement_routine_changed = Signal(MeasurementRoutine) + measurement_routine_changed = Signal(BaseMeasurementRoutine) class MainThreadModel(QObject): @@ -32,7 +33,7 @@ class MainThreadModel(QObject): self._config: FlexSensorConfig = config - self._measurement_routine: MeasurementRoutine = None + self._measurement_routine: BaseMeasurementRoutine = None self.start_capture_flag: Value = Value('i', 0) self._ad2_model: AD2Dev.Model = None @@ -146,10 +147,10 @@ class MainThreadModel(QObject): self.signals.prober_changed.emit(self.prober_model, self.prober_controller, self.prober_window) @property - def measurement_routine(self) -> MeasurementRoutine: + def measurement_routine(self) -> BaseMeasurementRoutine: return self._measurement_routine @measurement_routine.setter - def measurement_routine(self, value: MeasurementRoutine): + def measurement_routine(self, value: BaseMeasurementRoutine): self._measurement_routine = value self.signals.measurement_routine_changed.emit(self.measurement_routine) diff --git a/src/FlexSensor/MainWindow/view/StepThroughView.py b/src/FlexSensor/MainWindow/view/StepThroughView.py index b33643dc2dca3fb5a14ecd69ec6142a84c6474a5..f9672041aea459d45ae1b2adb7df1b3cec7bc5ba 100644 --- a/src/FlexSensor/MainWindow/view/StepThroughView.py +++ b/src/FlexSensor/MainWindow/view/StepThroughView.py @@ -7,7 +7,7 @@ from PySide6.QtGui import QIcon import FlexSensor.Prober as Prober from FlexSensor.Prober.controller.ProberController import ProberController -from FlexSensor.constants.FlexsensorConstants import Probe +from FlexSensor.Prober.controller.OpticalInterface import Probe class StepThroughView(QMainWindow): diff --git a/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py index 6c6fb5c447b1450d1415d5f78c329423ce0b6d66..4d90f1fa5dcd4ea5822e0f723541edbe60e60021 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py @@ -8,20 +8,24 @@ import pandas as pd import scipy from numpy import ndarray -from MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties -from MeasurementData.Properties.LaserProperties import LaserProperties -from MeasurementData.MeasuredData.SupportClasses.MeasurementDataTables import MeasurementDataTables -from MeasurementData.Properties.MeasurementProperties import MeasurementProperties, \ - MPropertiesFindPeaks, WaveguideProperties -from MeasurementData.Properties.WaferProperties import WaferProperties +from FlexSensor.MeasurementData.MeasuredData.SupportClasses.MeasurementDataTables import MeasurementDataTables +from FlexSensor.generics.GenericProperties import GenericProperties + + +#from MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties +#from MeasurementData.Properties.LaserProperties import LaserProperties +#from MeasurementData.MeasuredData.SupportClasses.MeasurementDataTables import MeasurementDataTables +#from MeasurementData.Properties.MeasurementProperties import MeasurementProperties, \ +# MPropertiesFindPeaks, WaveguideProperties +#from MeasurementData.Properties.WaferProperties import WaferProperties class MeasuredData: - def __init__(self, laser_properties: LaserProperties, ad2_properties: AD2CaptDeviceProperties, - wafer_properties: WaferProperties, waveguide_properties: WaveguideProperties, - measurement_properties: MeasurementProperties): + def __init__(self, laser_properties: GenericProperties, ad2_properties: GenericProperties, + wafer_properties: GenericProperties, waveguide_properties: GenericProperties, + measurement_properties: GenericProperties): #super().__init__() self.logger = logging.getLogger("MeasuredSignal") # ============================================================================================================== diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py index e4aa424473ccd078507ae6f69246d07d7f42ba4b..11f7d4e9aafe46cb7539aa60f8b6a11b2cf4596d 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py @@ -1,4 +1,13 @@ import sys + +from FlexSensor.MeasurementData.MeasuredData.MeasuredData import MeasuredData +from FlexSensor.generics.GenericProperties import GenericProperties + +#from examples.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties +#from examples.Properties.LaserProperties import LaserProperties +#from examples.Properties.MeasurementProperties import WaveguideProperties, MeasurementProperties +#from examples.Properties.WaferProperties import WaferProperties + sys.path.append("../flexsensorpy") sys.path.append("../mcpy") import pathlib @@ -19,16 +28,6 @@ from scipy.io import matlab from scipy.signal import find_peaks import scipy -from MeasurementData.Properties.AD2CaptDeviceProperties import AD2CaptDeviceProperties - -from MeasurementData.Properties.LaserProperties import LaserProperties -from MeasurementData.MeasuredData.MeasuredData import MeasuredData -from MeasurementData.Properties.MeasurementProperties import (WaveguideProperties, - MeasurementProperties, - WaveguidePropertiesMZI, - MPropertiesFindPeaks) -from MeasurementData.Properties.WaferProperties import WaferProperties - import mcpy @@ -39,112 +38,113 @@ class SingleMeasuredData(MeasuredData): # ================================================================================================================== # Load a Measurement data from a matlab mat-file # ================================================================================================================== - @classmethod - def from_mat(cls, mat_file: Path | str) -> 'SingleMeasuredData': - """ - This allows to open "old" mat files, that do not have some data. - """ - mat_file = pathlib.Path(mat_file) - logging.info(f"Loading {mat_file.name}") - matf = scipy.io.loadmat(mat_file) - - inst = cls( - laser_properties=LaserProperties( - mcpy.Rectangular(2, 0.01, unit='nm/s'), - mcpy.Rectangular(2, 0.01, unit='nm/s'), - mcpy.Rectangular(0.5, 0.01, unit='nm/s^2'), - (mcpy.Rectangular(835, 0.01, unit='nm'), mcpy.Rectangular(870, 0.01, unit='nm')) - ), - ad2_properties=AD2CaptDeviceProperties( - 0, 0, matf['ad2_sample_rate'], matf['ad2_total_samples'], matf['measure_time'] - ), - wafer_properties=WaferProperties( - matf['wafer_nr'], - matf['structure_name'], - matf['die_nr'], - matf['chuck_col'], - matf['chuck_row'], - (int(matf['structure_x_in']), int(matf['structure_y_in'])), - (int(matf['structure_x_out']), int(matf['structure_y_out'])), - int(mat_file.name.split('_')[9].replace('.mat', '')) - ), - waveguide_properties=WaveguidePropertiesMZI( - length1=mcpy.Rectangular(10e6, 20, unit='nm'), - length2=mcpy.Rectangular(10.38e6, 20, unit='nm'), - width=mcpy.Rectangular(550, 20, unit='nm'), - height=mcpy.Rectangular(625, 2.405, unit='nm')), - measurement_properties=MeasurementProperties( - MPropertiesFindPeaks(0.1, 10000, None) - ), - timestamp=matf['timestamp'], - measurement_file=None, - measurement_data=matf['amplitude'][0] - ) - """ - date_format = '%a %b %d %H:%M:%S %Y' - x = datetime. strptime( - re.search('(?<=Created on: ).*', matf['__header__'].decode('UTF-8')).group(0), - date_format)""" - - return inst - - @classmethod - def from_mat_v2(cls, mat_file: Path | str): - def loadmat(filename): - ''' - this function should be called instead of direct spio.loadmat - as it cures the problem of not properly recovering python dictionaries - from mat files. It calls the function check keys to cure all entries - which are still mat-objects - ''' - data = scipy.io.loadmat(filename, struct_as_record=False, squeeze_me=True) - return _check_keys(data) - - def _check_keys(dict): - ''' - checks if entries in dictionary are mat-objects. If yes - todict is called to change them to nested dictionaries - ''' - for key in dict: - if isinstance(dict[key], matlab.mio5_params.mat_struct): - dict[key] = _todict(dict[key]) - return dict - - def _todict(matobj): - ''' - A recursive function which constructs from matobjects nested dictionaries - ''' - dict = {} - for strg in matobj._fieldnames: - elem = matobj.__dict__[strg] - if isinstance(elem, matlab.mio5_params.mat_struct): - dict[strg] = _todict(elem) - else: - dict[strg] = elem - return dict - - if isinstance(mat_file, str): - mat_file = Path(mat_file) - - logging.info(f"Loading {mat_file.name}") - matf = loadmat(mat_file) - # mcpy.Uncertainty.from_tuple(matf['laser_properties']['laser_wavelength']) - inst = cls( - laser_properties=LaserProperties.from_dict(matf['laser_properties']), - ad2_properties=AD2CaptDeviceProperties.from_dict(matf['ad2_properties']), - wafer_properties=WaferProperties.from_dict(matf['wafer_properties']), - waveguide_properties=WaveguidePropertiesMZI.from_dict(matf['waveguide_properties']), - measurement_properties=MeasurementProperties.from_dict(matf['measurement_properties']), - timestamp=matf['timestamp'], - measurement_data=pd.DataFrame({ - 'wavelength': matf['wavelength'], - 'amplitude': matf['amplitude'], - 'amplitude_detrended': matf['amplitude_detrended']}), - - #measurement_file=Path(f"{mat_file.absolute().parent}/{matf['measurement_file']}").absolute() - ) - return inst - + # @classmethod + # def from_mat(cls, mat_file: Path | str) -> 'SingleMeasuredData': + # """ + # This allows to open "old" mat files, that do not have some data. + # """ + # mat_file = pathlib.Path(mat_file) + # logging.info(f"Loading {mat_file.name}") + # matf = scipy.io.loadmat(mat_file) + # + # inst = cls( + # laser_properties= + # #LaserProperties( + # # mcpy.Rectangular(2, 0.01, unit='nm/s'), + # # mcpy.Rectangular(2, 0.01, unit='nm/s'), + # # mcpy.Rectangular(0.5, 0.01, unit='nm/s^2'), + # # (mcpy.Rectangular(835, 0.01, unit='nm'), mcpy.Rectangular(870, 0.01, unit='nm')) + # #), + # ad2_properties=AD2CaptDeviceProperties( + # 0, 0, matf['ad2_sample_rate'], matf['ad2_total_samples'], matf['measure_time'] + # ), + # wafer_properties=WaferProperties( + # matf['wafer_nr'], + # matf['structure_name'], + # matf['die_nr'], + # matf['chuck_col'], + # matf['chuck_row'], + # (int(matf['structure_x_in']), int(matf['structure_y_in'])), + # (int(matf['structure_x_out']), int(matf['structure_y_out'])), + # int(mat_file.name.split('_')[9].replace('.mat', '')) + # ), + # waveguide_properties=WaveguidePropertiesMZI( + # length1=mcpy.Rectangular(10e6, 20, unit='nm'), + # length2=mcpy.Rectangular(10.38e6, 20, unit='nm'), + # width=mcpy.Rectangular(550, 20, unit='nm'), + # height=mcpy.Rectangular(625, 2.405, unit='nm')), + # measurement_properties=MeasurementProperties( + # MPropertiesFindPeaks(0.1, 10000, None) + # ), + # timestamp=matf['timestamp'], + # measurement_file=None, + # measurement_data=matf['amplitude'][0] + # ) + # """ + # date_format = '%a %b %d %H:%M:%S %Y' + # x = datetime. strptime( + # re.search('(?<=Created on: ).*', matf['__header__'].decode('UTF-8')).group(0), + # date_format)""" + # + # return inst + # + # @classmethod + # def from_mat_v2(cls, mat_file: Path | str): + # def loadmat(filename): + # ''' + # this function should be called instead of direct spio.loadmat + # as it cures the problem of not properly recovering python dictionaries + # from mat files. It calls the function check keys to cure all entries + # which are still mat-objects + # ''' + # data = scipy.io.loadmat(filename, struct_as_record=False, squeeze_me=True) + # return _check_keys(data) + # + # def _check_keys(dict): + # ''' + # checks if entries in dictionary are mat-objects. If yes + # todict is called to change them to nested dictionaries + # ''' + # for key in dict: + # if isinstance(dict[key], matlab.mio5_params.mat_struct): + # dict[key] = _todict(dict[key]) + # return dict + # + # def _todict(matobj): + # ''' + # A recursive function which constructs from matobjects nested dictionaries + # ''' + # dict = {} + # for strg in matobj._fieldnames: + # elem = matobj.__dict__[strg] + # if isinstance(elem, matlab.mio5_params.mat_struct): + # dict[strg] = _todict(elem) + # else: + # dict[strg] = elem + # return dict + # + # if isinstance(mat_file, str): + # mat_file = Path(mat_file) + # + # logging.info(f"Loading {mat_file.name}") + # matf = loadmat(mat_file) + # # mcpy.Uncertainty.from_tuple(matf['laser_properties']['laser_wavelength']) + # inst = cls( + # laser_properties=LaserProperties.from_dict(matf['laser_properties']), + # ad2_properties=AD2CaptDeviceProperties.from_dict(matf['ad2_properties']), + # wafer_properties=WaferProperties.from_dict(matf['wafer_properties']), + # waveguide_properties=WaveguidePropertiesMZI.from_dict(matf['waveguide_properties']), + # measurement_properties=MeasurementProperties.from_dict(matf['measurement_properties']), + # timestamp=matf['timestamp'], + # measurement_data=pd.DataFrame({ + # 'wavelength': matf['wavelength'], + # 'amplitude': matf['amplitude'], + # 'amplitude_detrended': matf['amplitude_detrended']}), + # + # #measurement_file=Path(f"{mat_file.absolute().parent}/{matf['measurement_file']}").absolute() + # ) + # return inst + # @staticmethod def convert(mat_file): """Reads the mat file and converts the new format to the old format""" @@ -157,11 +157,11 @@ class SingleMeasuredData(MeasuredData): def __init__(self, - laser_properties: LaserProperties, - ad2_properties: AD2CaptDeviceProperties, - wafer_properties: WaferProperties, - waveguide_properties: WaveguideProperties, - measurement_properties: MeasurementProperties, + laser_properties: GenericProperties, + ad2_properties: GenericProperties, + wafer_properties: GenericProperties, + waveguide_properties: GenericProperties, + measurement_properties: GenericProperties, timestamp: datetime, measurement_file: Path | str = None, measurement_data = None, diff --git a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/BaseMeasurementRoutine.py similarity index 98% rename from src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py rename to src/FlexSensor/MeasurementRoutines/BaseMeasurementRoutine.py index 5d74c2ac9f1ce727b2294a3027704d2628d29131..8d96026eac953793c59fe1098686495bee7146af 100644 --- a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py +++ b/src/FlexSensor/MeasurementRoutines/BaseMeasurementRoutine.py @@ -34,6 +34,9 @@ class BaseMeasurementRoutine(QObject, FSBase): self.signals = WorkerSignals() + def pch(self, c, num): + return ''.join([str(c) for i in range(0, num)]) + @Slot() def run(self): raise NotImplementedError() diff --git a/src/FlexSensor/Prober/__init__.py b/src/FlexSensor/Prober/__init__.py index 95b5a7471c8a867464ba1c388ebea37539947c47..31950790fd251dc9c1e502ea5ab65447b93ae7ce 100644 --- a/src/FlexSensor/Prober/__init__.py +++ b/src/FlexSensor/Prober/__init__.py @@ -7,9 +7,17 @@ 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 +from .controller.OpticalInterface import OpticalInterface + + +from .controller.ProberController import ProberController as Controller +from .view.ProberControlWindow import ProberControlWindow as ControlWindow + + + + if os.getenv("VELOX_SIM") == "TRUE": try: @@ -36,3 +44,4 @@ else: ReadChuckPosition, ReadChuckHeights, MoveChuck, SnapImage, GetDieDataAsColRow, StepToDie, ReportKernelVersion) + diff --git a/src/FlexSensor/Prober/controller/OpticalInterface.py b/src/FlexSensor/Prober/controller/OpticalInterface.py index d0bcc46b3441d8257a5937dd0041b554850a2c66..de8d91298adcddfd8e1dcbc96f8ec5f38b09e937 100644 --- a/src/FlexSensor/Prober/controller/OpticalInterface.py +++ b/src/FlexSensor/Prober/controller/OpticalInterface.py @@ -2,8 +2,8 @@ import logging from Prober.model.OpticalInterfaceModel import OpticalInterfaceModel from Prober.model.OpticalInterfaceStoredData import OpticalInterfaceStoredData -from constants.FlexsensorConstants import Probe -from generics.generics import pch +#from constants.FlexsensorConstants import Probe +#from generics.generics import pch from FlexSensor.FSBase import FSBase @@ -22,6 +22,8 @@ class OpticalInterface(FSBase): # ================================================================================================================== # pythonized api calls # ================================================================================================================== + def pch(self, c, num): + return ''.join([str(c) for i in range(0, num)]) def enable_flight_height_control(self, enable_in=True, enable_out=True): # Disable Flight Height Control @@ -189,7 +191,7 @@ class OpticalInterface(FSBase): output_power) def search_for_light(self, threshold: float = -70, threshold_areascan: float = -60, retries: float = 3): - self.logger.debug(f"[OptIF Task] - {pch('*', 20)} Search for light {pch('*', 20)}") + self.logger.debug(f"[OptIF Task] - {self.pch('*', 20)} Search for light {self.pch('*', 20)}") self.signals.log_debug.emit("OptIF Task", f"*** Search for light ***", None) # Recenter the probes, perform an area scan, recenter again. @@ -221,7 +223,7 @@ class OpticalInterface(FSBase): x_1, x_2, y_1, y_2, input_power, output_power = self._recenter_and_scan() retries -= 1 - self.logger.debug(f"[OptIF Task] - {pch('*', 20)} Search for light completed {pch('*', 20)}") + self.logger.debug(f"[OptIF Task] - {self.pch('*', 20)} Search for light completed {self.pch('*', 20)}") self.signals.log_debug.emit("OptIF Task", f"*** Search for light completed***", None) return input_power, output_power @@ -268,3 +270,7 @@ class OpticalInterface(FSBase): # Store and load functions # ================================================================================================================== + +class Probe: + INPUT = 0 + OUTPUT = 1 diff --git a/src/FlexSensor/Prober/controller/ProberController.py b/src/FlexSensor/Prober/controller/ProberController.py index b115c694b152fa129ddec03e6cc52fb331dbb25b..15badaa95c0817c20e6a95f4e2c1bb1a4aaa248c 100644 --- a/src/FlexSensor/Prober/controller/ProberController.py +++ b/src/FlexSensor/Prober/controller/ProberController.py @@ -4,14 +4,14 @@ import confighandler as Config #from ConfigHandler.controller.VAutomatorConfig import VAutomatorConfig import FlexSensor.Prober as Prober from FlexSensor.FSBase import FSBase -from FlexSensor.Prober.controller.OpticalInterface import OpticalInterface -from FlexSensor.Prober.model.ProberModel import ProberModel -from FlexSensor.constants.FlexsensorConstants import Probe +from FlexSensor.Prober.controller import OpticalInterface +#from FlexSensor.Prober.controller.OpticalInterface import OpticalInterface, Probe +#from FlexSensor.Prober.model.ProberModel import ProberModel from FlexSensor.generics.generics import pch class ProberController(FSBase): - def __init__(self, model: ProberModel, + def __init__(self, model: Prober.Model, enable_log=True, log_level=logging.DEBUG, log_file=None, *args, **kwargs): super().__init__() @@ -22,7 +22,7 @@ class ProberController(FSBase): self.msg_server = Prober.MessageServerInterface() # Optical Interface Control hexapods and piezos - self.opt_if = OpticalInterface(self.signals, self.msg_server) + self.opt_if = Prober.OpticalInterface(self.signals, self.msg_server) self.logger.info("Prober initialized") self.model.version = self.report_kernel_version() @@ -217,8 +217,8 @@ class ProberController(FSBase): # Move hexapod and nano to height 50 um height = 80 - self.opt_if.set_probe_height(Probe.INPUT, height) - self.opt_if.set_probe_height(Probe.OUTPUT, height) + self.opt_if.set_probe_height(OpticalInterface.Probe.INPUT, height) + self.opt_if.set_probe_height(OpticalInterface.Probe.OUTPUT, height) # Read the die data: die number, col, row self.model.die, self.model.die_col, self.model.die_row = self.get_die_as_col_row() @@ -299,7 +299,7 @@ class ProberController(FSBase): self.write_log("warning", "No light found.") return False - def store_hexapod_position(): + def store_hexapod_position(self): """ Stores the hexpods and nanocube position for later retrieval """ diff --git a/src/FlexSensor/Prober/model/ProberModel.py b/src/FlexSensor/Prober/model/ProberModel.py index ec97dcfd6cc8da82684eba9c4b907f2a8c4694c3..d7e9d0eee86a7705377480970871d14baa5e456b 100644 --- a/src/FlexSensor/Prober/model/ProberModel.py +++ b/src/FlexSensor/Prober/model/ProberModel.py @@ -2,7 +2,6 @@ from pathlib import Path from PySide6.QtCore import QObject, Signal -from MeasurementData.Properties.WaferProperties import WaferProperties from FlexSensor.FlexSensorConfig import FlexSensorConfig @@ -62,12 +61,12 @@ class ProberModel: #self._wafer_map = self.config. - @property - def laser_properties(self) -> WaferProperties: - return WaferProperties(self.acceleration, - self.deceleration, - self.velocity, - (self.sweep_start_wavelength, self.sweep_stop_wavelength)) + #@property + #def laser_properties(self) -> WaferProperties: + # return WaferProperties(self.acceleration, + # self.deceleration, + # self.velocity, + # (self.sweep_start_wavelength, self.sweep_stop_wavelength)) @property def connected(self) -> bool: return self._connected diff --git a/src/FlexSensor/Prober/view/ProberControlWindow.py b/src/FlexSensor/Prober/view/ProberControlWindow.py index a037aa69ddd1889ec1ad8e3086da61b5ca08f8c2..db1ee783650683869eccc580b5270c97e7214f2b 100644 --- a/src/FlexSensor/Prober/view/ProberControlWindow.py +++ b/src/FlexSensor/Prober/view/ProberControlWindow.py @@ -6,14 +6,22 @@ from PySide6.QtWidgets import QGridLayout, QApplication, QMainWindow, QWidget, Q import confighandler as Config -#from MapFileParser import MapFileParser from FlexSensor.Prober.controller.ProberController import ProberController from FlexSensor.Prober.model.ProberModel import ProberModel +#from MapFileParser import MapFileParser +#from FlexSensor import Prober from FlexSensor.Prober.view.widgets.DieGridWidget import DieGridWidget from FlexSensor.Prober.view.widgets.ProberPositionWidget import ProberPositionWidget from FlexSensor.Prober.view.widgets.ProberStatusWidget import ProberStatusWidget +#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): def __init__(self, model: ProberModel, controller: ProberController): diff --git a/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py b/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py index 9db1dfde64d455f62e7574d9407525a5099f26e9..b46ee7b6e95a26896fbecbb5b0b0621199ea3195 100644 --- a/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py +++ b/src/FlexSensor/Prober/view/widgets/ProberPositionWidget.py @@ -1,11 +1,14 @@ from PySide6.QtWidgets import QWidget, QGroupBox, QGridLayout, QLabel, QProgressBar -from Prober.model.ProberModel import ProberModel +from FlexSensor import Prober + + +#from Prober.model.ProberModel import ProberModel class ProberPositionWidget(QWidget): - def __init__(self, model: ProberModel, chuck_position="Vertical"): + def __init__(self, model: Prober.Model, chuck_position="Vertical"): super().__init__() self.model = model self.layout = QGridLayout() diff --git a/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py b/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py index 00e2073375bd698281f6887da38514385df74376..9406071104859dde3cf2f268b3cf80159464a0ac 100644 --- a/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py +++ b/src/FlexSensor/Prober/view/widgets/ProberStatusWidget.py @@ -2,12 +2,15 @@ from PySide6.QtCore import Qt from PySide6.QtGui import QIcon from PySide6.QtWidgets import QWidget, QLabel, QGridLayout, QStyle, QFrame, QProgressBar, QGroupBox -from Prober.model.ProberModel import ProberModel +from FlexSensor import Prober + + +#from Prober.model.ProberModel import ProberModel class ProberStatusWidget(QWidget): - def __init__(self, model: ProberModel): + def __init__(self, model: Prober.Model): super().__init__() self.setFixedSize(300, 200) self.model = model diff --git a/src/FlexSensor/__init__.py b/src/FlexSensor/__init__.py index e475ef5f305490a37b56f7ee6ccd7797247fe346..d7aae92934b5cbcd1862dd8c94ff6e29f842d618 100644 --- a/src/FlexSensor/__init__.py +++ b/src/FlexSensor/__init__.py @@ -6,6 +6,7 @@ from .__version__ import __version__ #from .Prober import Prober +from . import FlexSensorConfig from .generics import ConsoleWindow as Console @@ -17,3 +18,8 @@ from .MainWindow.view.SplashScreen import SplashScreen from .generics.ApplicationInit import ApplicationInit from .generics.ConsoleWindow import ConsoleWindow from .pathes import configs_root + +# for the measurement routines +from .MeasurementRoutines.BaseMeasurementRoutine import BaseMeasurementRoutine +from .generics.VASInputFileParser import VASInputFileParser +from .generics.VASInputFileParser import Structure diff --git a/src/FlexSensor/constants/FlexsensorConstants.py b/src/FlexSensor/constants/FlexsensorConstants.py index 37913cb0695cc5479cd7e98967eb5386e46743e0..8b137891791fe96927ad78e64b0aad7bded08bdc 100644 --- a/src/FlexSensor/constants/FlexsensorConstants.py +++ b/src/FlexSensor/constants/FlexsensorConstants.py @@ -1,3 +1 @@ -class Probe: - INPUT = 0 - OUTPUT = 1 +