diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 35eb1ddfbbc029bcab630581847471d7f238ec53..ad6e05a2d19ec1157890da37188ca7444bcc37ac 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,7 @@ <project version="4"> <component name="VcsDirectoryMappings"> <mapping directory="" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/src/FlexSensor/resources/cmp" vcs="Git" /> + <mapping directory="$PROJECT_DIR$/src/FlexSensor/resources/resources/cmp" vcs="Git" /> </component> </project> \ No newline at end of file diff --git a/AppSettings.yaml b/AppSettings.yaml deleted file mode 100644 index 557b455709db5e2b78e8218c47f70536a6b0ded2..0000000000000000000000000000000000000000 --- a/AppSettings.yaml +++ /dev/null @@ -1,13 +0,0 @@ -# - Configuration file stored 2023-11-24 11:46:57.988160 - -AppSettings: #!!python/object:controller.AppSettings - ENABLE_CUSTOM_TITLE_BAR: True # ENABLE_CUSTOM_TITLE_BAR: None - MENU_WIDTH: 240 # MENU_WIDTH: None - LEFT_BOX_WIDTH: 240 # LEFT_BOX_WIDTH: None - RIGHT_BOX_WIDTH: 240 # RIGHT_BOX_WIDTH: None - TIME_ANIMATION: 500 # TIME_ANIMATION: None - BTN_LEFT_BOX_COLOR: "background-color: rgb(44, 49, 58);" # BTN_LEFT_BOX_COLOR: None - BTN_RIGHT_BOX_COLOR: "background-color: #ff79c6;" # BTN_RIGHT_BOX_COLOR: None - MENU_SELECTED_STYLESHEET: " - 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); - " # MENU_SELECTED_STYLESHEET: None diff --git a/CaptDeviceConfig.yaml b/CaptDeviceConfig.yaml deleted file mode 100644 index a484f38a70ec7e09d1871b8543d0e689735a4872..0000000000000000000000000000000000000000 --- a/CaptDeviceConfig.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# - Configuration file stored 2023-11-24 11:46:57.990884 - -CaptDeviceConfig: #!!python/object:controller.CaptDeviceConfig - sample_rate: 50000 # Sample rate: Sample rate of the device - streaming_rate: 500 # Streaming rate: Streaming rate in Hz (should be below 1kHz) - ain_channel: 0 # Analog In Channel: Analog in channel. Defines which channel is used for capturing. - show_simulator: True # Show Simulators: Show available simulators in the device list provided by the DreamWaves API. - streaming_history: 2000 # Streaming history (ms): Defines the range of the stream in ms - total_samples: 200000 # total_samples: None - sample_time: 45 # sample_time: None - ad2_raw_out_file: "{output_directory}/measurement/ad2_raw/ad2_out_{wafer_nr}_{date}.csv" # ad2_raw_out_file: None diff --git a/FlexSensorConfig.yaml b/FlexSensorConfig.yaml deleted file mode 100644 index d910b23f859637e3b1f3ff4d985b54deaf16fcd2..0000000000000000000000000000000000000000 --- a/FlexSensorConfig.yaml +++ /dev/null @@ -1,49 +0,0 @@ -# - Configuration file stored 2023-11-24 11:47:09.019578 - -FlexSensorConfig: #!!python/object:controller.FlexSensorConfig - wafer_version: "MaskARY1_Jakob_full" # Wafer Version: Wafer Version to be measured - wafer_number: "T40741W177G0" # Wafer Number: Wafer Number to be measured - output_directory: "@Path:<.>" # Output Directory: Measurement output directory - -# Sub-Configurations - wafer_config: #!!python/object:controller.WaferConfig - dies: "MaskARY1_Jakob_full" # dies: None - structure_file: "@Path:<H:/ET PhD - Dokumente/Silicon Photonics/FlexSensor 6/flexsensor-public/flexsensor/jakob.vas>" # structure_file: None - wafermap_file: "@Path:<H:/ET PhD - Dokumente/Silicon Photonics/FlexSensor 6/flexsensor-public/flexsensor/Wafermapary1_48dies.map>" # wafermap_file: None - log_file: "@Path:<{output_directory}/log_{date_time}.log>" # log_file: None - measurement_output: "@Path:<{output_directory}/measurement/measurement_{date_time}.csv>" # measurement_output: None - measurement_mat_file: "@Path:<{output_directory}/measurement/measurement_die_{die}_struct_{structure}_{date_time}_{it}.mat>" # measurement_mat_file: None - scope_image_file: "@Path:<{output_directory}/scope_shots/scope_{wafer_nr}_die_{die}_struct_{structure}_{time}.png>" # scope_image_file: None - bookmark_file: "@Path:<{output_directory}/klayout_bookmarks/bookmarks_{wafer_version}.lyb>" # bookmark_file: None - - app_config: #!!python/object:controller.AppSettings - ENABLE_CUSTOM_TITLE_BAR: True # ENABLE_CUSTOM_TITLE_BAR: None - MENU_WIDTH: 240 # MENU_WIDTH: None - LEFT_BOX_WIDTH: 240 # LEFT_BOX_WIDTH: None - RIGHT_BOX_WIDTH: 240 # RIGHT_BOX_WIDTH: None - TIME_ANIMATION: 500 # TIME_ANIMATION: None - BTN_LEFT_BOX_COLOR: "background-color: rgb(44, 49, 58);" # BTN_LEFT_BOX_COLOR: None - BTN_RIGHT_BOX_COLOR: "background-color: #ff79c6;" # BTN_RIGHT_BOX_COLOR: None - MENU_SELECTED_STYLESHEET: " - 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); - " # MENU_SELECTED_STYLESHEET: None - - laser_config: #!!python/object:controller.LaserConfig - wl_sweep_start: 850 # wl_sweep_start: None - wl_sweep_stop: 850 # wl_sweep_stop: None - velocity: 1.0 # velocity: None - acceleration: 2.0 # acceleration: None - deceleration: 1.0 # deceleration: None - available_ports: ['USB0', 'USB1', 'USB2', 'USB3', 'USB4', 'USB5', 'USB6', 'USB7', 'USB8', 'USB9'] # available_ports: None - port: "USB0" # port: None - - captdev_config: #!!python/object:controller.CaptDeviceConfig - sample_rate: 50000 # Sample rate: Sample rate of the device - streaming_rate: 500 # Streaming rate: Streaming rate in Hz (should be below 1kHz) - ain_channel: 0 # Analog In Channel: Analog in channel. Defines which channel is used for capturing. - show_simulator: True # Show Simulators: Show available simulators in the device list provided by the DreamWaves API. - streaming_history: 2000 # Streaming history (ms): Defines the range of the stream in ms - total_samples: 200000 # total_samples: None - sample_time: 45 # sample_time: None - ad2_raw_out_file: "{output_directory}/measurement/ad2_raw/ad2_out_{wafer_nr}_{date}.csv" # ad2_raw_out_file: None - diff --git a/LaserConfig.yaml b/LaserConfig.yaml deleted file mode 100644 index ccc8b9899ade4f6c374944bd21f91583b664384f..0000000000000000000000000000000000000000 --- a/LaserConfig.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# - Configuration file stored 2023-11-24 11:46:57.989159 - -LaserConfig: #!!python/object:controller.LaserConfig - wl_sweep_start: 840 # wl_sweep_start: None - wl_sweep_stop: 850 # wl_sweep_stop: None - velocity: 2.0 # velocity: None - acceleration: 1.0 # acceleration: None - deceleration: 1.0 # deceleration: None - available_ports: ['USB0', 'USB1', 'USB2', 'USB3', 'USB4', 'USB5', 'USB6', 'USB7', 'USB8', 'USB9'] # available_ports: None - port: "USB0" # port: None diff --git a/WaferConfig.yaml b/WaferConfig.yaml deleted file mode 100644 index eb6f68d85f7f5b6bbdc1f1d11a1ad2e3aec267b4..0000000000000000000000000000000000000000 --- a/WaferConfig.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# - Configuration file stored 2023-11-24 11:46:57.988160 - -WaferConfig: #!!python/object:controller.WaferConfig - dies: "MaskARY1_Jakob_full" # dies: None - structure_file: "@Path:<../vas-files/list_of_structures_picasso.vas>" # structure_file: None - wafermap_file: "@Path:<../Wafermapary1_48dies.map>" # wafermap_file: None - log_file: "@Path:<{output_directory}/log_{date_time}.log>" # log_file: None - measurement_output: "@Path:<{output_directory}/measurement/measurement_{date_time}.csv>" # measurement_output: None - measurement_mat_file: "@Path:<{output_directory}/measurement/measurement_die_{die}_struct_{structure}_{date_time}_{it}.mat>" # measurement_mat_file: None - scope_image_file: "@Path:<{output_directory}/scope_shots/scope_{wafer_nr}_die_{die}_struct_{structure}_{time}.png>" # scope_image_file: None - bookmark_file: "@Path:<{output_directory}/klayout_bookmarks/bookmarks_{wafer_version}.lyb>" # bookmark_file: None diff --git a/examples/main.py b/examples/main.py index 40281bc3c8baeb0fce959e80ef56151478defa82..d93dd730418bc4d0d9e0aa6c85b2f55d8783f84e 100644 --- a/examples/main.py +++ b/examples/main.py @@ -6,6 +6,7 @@ Package Version: """ import logging import sys +import time from PySide6.QtWidgets import QApplication @@ -13,32 +14,37 @@ sys.path.append('./src') import FlexSensor def main(argv): + FlexSensor.ApplicationInit.setup_logging() + logging.info(f"Starting Velox GUI Version {FlexSensor.__version__}") app = QApplication(sys.argv) splash_screen = FlexSensor.SplashScreen._display_splash_screen() - + splash_screen.show() 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.setup_logging(cw) FlexSensor.ApplicationInit.set_icon(app) # Read the inital config file + config = FlexSensor.ApplicationInit.load_config_file(f"{FlexSensor.configs_root}/init_config.yaml") + config.autosave(enable=True, path="autosave_configs/init_config.yaml") + - logging.info(f"Starting Velox GUI Version {FlexSensor.__version__}") main_model = FlexSensor.MainThreadModel(config=config) - wdg = config.view.widget() - wdg.show() + #wdg = config.view.widget() + #wdg.show() main_controller = FlexSensor.MainThreadController(main_model) main_window = FlexSensor.MainWindow(main_model, main_controller) # test_win = StructureSelector() - + #config.save(f"{FlexSensor.configs_root}/init_config.yaml") main_window.show() splash_screen.finish(main_window) + sys.exit(app.exec()) if __name__ == "__main__": diff --git a/requirements.txt b/requirements.txt index 8d69cc2ed181a49776947c7fdb96144d658218d5..e3fa87a58047382e56f85d700e0de12b23840249 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,17 +6,14 @@ pyqtgraph pandas # Custom added packages -#git+https://gitlab.tugraz.at/flexsensor-public/confighandler.git@develop -../confighandler - -#git+https://gitlab.tugraz.at/flexsensor-public/captdevicecontrol.git@develop -../captdevicecontrol - -#git+https://gitlab.tugraz.at/flexsensor-public/lasercontrol.git@develop -../lasercontrol - +git+https://gitlab.tugraz.at/flexsensor-public/modules/confighandler.git@develop +git+https://gitlab.tugraz.at/flexsensor-public/modules/fswidgets.git@develop +git+https://gitlab.tugraz.at/flexsensor-public/captdevicecontrol.git@develop +git+https://gitlab.tugraz.at/flexsensor-public/lasercontrol.git@develop #git+https://gitlab.tugraz.at/flexsensor-public/mcpy.git@develop -../mcpy -#git+https://gitlab.tugraz.at/flexsensor-public/fswidgets.git@develop -../fswidgets \ No newline at end of file +#../tools/confighandler +#../captdevicecontrol +#../lasercontrol +../mcpy +#../tools/fswidgets \ No newline at end of file diff --git a/src/FlexSensor/AppSettings.py b/src/FlexSensor/AppSettings.py index d93fb95048a4d1fe47899f335f368c36773b9034..5c6bde698280b498685c4ac4ae257550d2829822 100644 --- a/src/FlexSensor/AppSettings.py +++ b/src/FlexSensor/AppSettings.py @@ -4,6 +4,8 @@ Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> Created: 2023-10-19 12:35 Package Version: """ +import logging + import confighandler as cfg diff --git a/src/FlexSensor/FSBase.py b/src/FlexSensor/FSBase.py new file mode 100644 index 0000000000000000000000000000000000000000..0ce4962e2b591fff98bae3114fa999ae72c18898 --- /dev/null +++ b/src/FlexSensor/FSBase.py @@ -0,0 +1,79 @@ +import logging +import time + +from rich.logging import RichHandler + + +class FSBase: + + # ================================================================================================================== + # Public methods + # ================================================================================================================== + def __init__(self): + self._internal_logger = None + self._internal_log_handler = None + self.name = self.__class__.__name__ + + def create_new_logger(self, logger_name: str, logger_handler: logging.Handler = logging.NullHandler(), + enabled=True, level=logging.DEBUG, propagate=True) -> logging.Logger: + # logger_handler.setLevel(level) + _internal_logger = logging.getLogger(logger_name) + _internal_logger.handlers = [logger_handler] + _internal_logger.propagate = propagate + _internal_logger.setLevel(level) + + if enabled: + _internal_logger.disabled = False + _internal_logger.info(f"Logger {logger_name} created with ({len(_internal_logger.handlers)}) " + f"handlers and has been enabled (Level {_internal_logger.level}).") + else: + _internal_logger.info(f"Logger {logger_name} created and has been disabled.") + _internal_logger.disabled = True + + return _internal_logger + + def set_log_enabled(self, logger: logging.log, enable: bool) -> None: + """ + Enables or disables internal logging. If disabled, the internal logger will be disabled and no messages will be + emitted to the state queue. + :param enable: True to enable, False to disable + + Args: + logger: + """ + if logger is not None: + if enable: + logger.disabled = False + logger.info(f"Internal logger of {self.name} has been enabled.") + + else: + logger.warning(f"Internal logger of {self.name} has been disabled.") + logger.disabled = True + else: + raise Exception(f"Can't enable or disable {logger}.") # + + def set_log_level(self, logger: logging.log, level: int) -> None: + """ + Sets the internal logging level. + :param level: + :return: + + Args: + logger: + """ + if logger is not None: + if level == logging.DEBUG: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to DEBUG.") + elif level == logging.INFO: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to INFO.") + elif level == logging.WARNING: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to WARNING.") + elif level == logging.ERROR: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to ERROR.") + elif level == logging.CRITICAL: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to CRITICAL.") + else: + logger.info(f"Internal log level of {self.__class__.__name__} has been set to level {level}.") + logger.handlers[0].setLevel(level) + else: + raise Exception("Can't set internal log level. Internal logger not initialized") diff --git a/src/FlexSensor/FlexSensorConfig.py b/src/FlexSensor/FlexSensorConfig.py index baada5e511d438a1bdc71710a5b48d53ab765d30..f54603f9b0691a1b017df33a81e8ee5843b893d3 100644 --- a/src/FlexSensor/FlexSensorConfig.py +++ b/src/FlexSensor/FlexSensorConfig.py @@ -4,6 +4,7 @@ Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> Created: 2023-10-19 12:35 Package Version: """ +import logging from pathlib import Path import confighandler as cfg @@ -26,6 +27,9 @@ class FlexSensorConfig(cfg.ConfigNode): self.output_directory = cfg.Field(Path("./"), friendly_name="Output Directory", description="Measurement output directory") + self.log_file = cfg.Field("fs.log", friendly_name="Log File", + description="") + self.wafer_config = WaferConfig() self.app_config = AppSettings() self.laser_config = Laser.Config() diff --git a/src/FlexSensor/MainWindow/controller/MainThreadController.py b/src/FlexSensor/MainWindow/controller/MainThreadController.py index 8d08d08bc2aa55d2ae519027a501dba8458ff39e..e73b03633fd98b6e081582daaffd2b5ac053e9da 100644 --- a/src/FlexSensor/MainWindow/controller/MainThreadController.py +++ b/src/FlexSensor/MainWindow/controller/MainThreadController.py @@ -1,6 +1,6 @@ import logging -from PySide6.QtCore import QThread +from PySide6.QtCore import QThread, Signal import confighandler import LaserControl as Laser @@ -13,12 +13,43 @@ from ..model.MainThreadModel import MainThreadModel from FlexSensor.MeasurementRoutines.MeasurementRoutine import MeasurementRoutine from Prober.controller.ProberController import ProberController +from ...FSBase import FSBase + + +class MainThreadController(FSBase, object): + + on_start_laser_sweep = Signal(name='on_start_laser_sweep') + + def __init__(self, model: MainThreadModel, + enable_log: bool = True, log_level: int = logging.DEBUG, log_file: str = "flexsensor.log"): + super().__init__() -class MainThreadController(object): - def __init__(self, model: MainThreadModel): - self.logger = logging.getLogger("MainThread") self._model = model + self._enable_log = enable_log + self._log_file = log_file + self._log_level = log_level + + self.logger = self.create_new_logger(self.name, + enabled=self.enable_log, level=self.log_level) + + self.model.ad2_model = AD2Dev.Model(self.model.config.captdev_config) + self.model.ad2_controller = AD2Dev.Controller(self.model.ad2_model, self.model.start_capture_flag) + self.model.ad2_window = AD2Dev.View(self.model.ad2_model, self.model.ad2_controller) + + # Devices + self.model.laser_model = Laser.Model(self.model.config.laser_config) + self.model.laser_controller = Laser.Controller(self.model.laser_model, self.model.start_capture_flag, + module_log_level=logging.DEBUG) + + self.model.laser_window = Laser.View(self.model.laser_model, self.model.laser_controller) + self.model.laser_controller.connect_capture_device(self.model.ad2_controller) + + + self.model.prober_model = Prober.Model(self.model.config) + self.model.prober_controller = Prober.Controller(self.model.prober_model) + self.model.prober_window = Prober.ControlWindow(self.model.prober_model, self.model.prober_controller) + # self.model._laser_controller.connect_device(self._vaut_config.laser_config.get_port()) mypath = ( @@ -40,6 +71,18 @@ class MainThreadController(object): def model(self) -> MainThreadModel: return self._model + @property + def enable_log(self) -> bool: + return self._enable_log + + @property + def log_file(self) -> str: + return self._log_file + + @property + def log_level(self) -> int: + return self._log_level + def start_measurement_routine(self): # 1. Create all working folders self._create_working_folders() @@ -50,18 +93,20 @@ class MainThreadController(object): if self.measurement_thread.isRunning(): self.logger.debug("Thread is running.") + def _on_start_laser_sweep_emitted(self): + self.logger.debug("Start laser sweep emitted.") + def _create_working_folders(self): """Creates all working folders to store the measurement data. """ pass - #self.model.config.setup_folders() + # self.model.config.setup_folders() def _move_measurement_routine_thread(self, measurement_routine): measurement_routine.moveToThread(self.measurement_thread) self.measurement_thread.started.connect(measurement_routine.run) self.logger.debug("Moved worker/measurement routine to thread and connected the signals.") - def _load_measurement_routine(self) -> MeasurementRoutine: """ Loads the measurement routine and initializes it. @@ -72,8 +117,8 @@ class MainThreadController(object): Raises: Exception: If some or all devices have not been initialized. """ - if not self.device_are_init: - raise Exception("Some or all devices have not been initialized. First call `_device_initialization()`!") + # if not self.device_are_init: + # raise Exception("Some or all devices have not been initialized. First call `_device_initialization()`!") measurement_routine = MeasurementRoutine( self.model.laser_controller, @@ -87,7 +132,7 @@ class MainThreadController(object): """ Initializes all devices and connects the signals and slots. """ - self.model.ad2_controller.connect_device(0) + # self.model.ad2_controller.connect_device(0) # # Connect the required signals and slots # self.model.laser_model.signals.laser_ready_for_sweep_changed.connect( # self.model.ad2_controller.start_capture_flag) @@ -98,4 +143,4 @@ class MainThreadController(object): # self.model.laser_model.signals.wavelength_sweep_running_changed.connect( # self.model.ad2_controller.set_ad2_acq_status) - self.device_are_init = True + self.device_are_init = False diff --git a/src/FlexSensor/MainWindow/model/MainThreadModel.py b/src/FlexSensor/MainWindow/model/MainThreadModel.py index 748f7cbe6d4107e10ae23aa68e73fcfd955f7b3d..c267f7f5920b5f170fcd65f9f91eb5d4bf6e7d7f 100644 --- a/src/FlexSensor/MainWindow/model/MainThreadModel.py +++ b/src/FlexSensor/MainWindow/model/MainThreadModel.py @@ -1,3 +1,5 @@ +from multiprocessing import Value + from PySide6.QtCore import QObject, Signal import LaserControl as Laser @@ -32,19 +34,20 @@ class MainThreadModel(QObject): self._measurement_routine: MeasurementRoutine = None - 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) + self.start_capture_flag: Value = Value('i', 0) + self._ad2_model: AD2Dev.Model = None + self._ad2_controller: AD2Dev.Controller = None + self._ad2_window: AD2Dev.View = None # Devices - self._laser_model: Laser.Model = Laser.Model(self.config.laser_config) - self._laser_controller: Laser.Controller = Laser.Controller(self._laser_model) + self._laser_model: Laser.Model = None + self._laser_controller: Laser.Controller = None + self._laser_window: Laser.View =None - self._laser_window: Laser.View = Laser.View(self._laser_model, self._laser_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) + self._prober_model: Prober.Model = None + self._prober_controller: Prober.Controller =None + self._prober_window: Prober.ControlWindow = None # Widgets self.mea_eval_tool_model: met.Model = met.Model() diff --git a/src/FlexSensor/MainWindow/view/MainThreadView.py b/src/FlexSensor/MainWindow/view/MainThreadView.py index 5f0951a5bd57e53d2b56fc262aad10443b3155bb..a2c6c93371b86e78069238354026e4b496b6186e 100644 --- a/src/FlexSensor/MainWindow/view/MainThreadView.py +++ b/src/FlexSensor/MainWindow/view/MainThreadView.py @@ -13,6 +13,8 @@ from pyqtgraph.dockarea import * import FlexSensor.__version__ as fsversion import confighandler as Config + +from FlexSensor.FSBase import FSBase from FlexSensor.MainWindow.view.BaseWindow import BaseWindow from FlexSensor.MainWindow.view.widgets.HomeStatusWidget import HomeStatusWidget from FlexSensor.MainWindow.view.widgets.MenuBarDefinition import MenuBarDefinition @@ -32,11 +34,13 @@ from FlexSensor.constants.qs_style_sheets import CSSPlayPushButton from FlexSensor.generics.VASInputFileParser import VASInputFileParser -class MainWindow(BaseWindow): +class MainWindow(BaseWindow, FSBase): def __init__(self, model: MainThreadModel, controller: MainThreadController): super().__init__(Ui_MainWindow(), model.config) - self.logger = logging.getLogger("MainThread (UI)") + self.logger = self.create_new_logger( + self.name + ) self._model: MainThreadModel = model self._controller: MainThreadController = controller @@ -129,7 +133,7 @@ class MainWindow(BaseWindow): 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_ad2 = tabwidget.addTab(WidgetAD2Settings(self.model.config.captdev_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( @@ -381,7 +385,7 @@ class MainWindow(BaseWindow): def closeEvent(self, event): # do stuff - self.model.ad2_controller.stop_process() + self.model.ad2_controller.exit() self.model.laser_controller.stop_process() event.accept() # let the window close diff --git a/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py index 903c0e26ce83531547e3cd739b9aaa1680c993cb..5dce441d8e979409ef92ccb92dcd4d4596118147 100644 --- a/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py +++ b/src/FlexSensor/MainWindow/view/widgets/WidgetSettingsFilesFolders.py @@ -1,6 +1,7 @@ import confighandler from LaserControl.LaserConfig import LaserConfig -from PySide6.QtWidgets import QWidget, QGridLayout, QGroupBox, QLineEdit, QPushButton, QLabel, QDoubleSpinBox +from PySide6.QtWidgets import QWidget, QGridLayout, QGroupBox, QLineEdit, QPushButton, QLabel, QDoubleSpinBox, \ + QTreeWidget from FlexSensor.FlexSensorConfig import FlexSensorConfig @@ -20,19 +21,10 @@ class WidgetSettingsInFilesFolders(QWidget): grid_group_box = QGroupBox("Input Files") layout = QGridLayout() # Working directory - 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) - 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) + layout.addWidget( self.config.output_directory.view.ui_field(), 0, 0) # row, column, rowspan, colspan + layout.addWidget(self.config.wafer_config.wafermap_file.view.ui_field(), 1, 0) # row, column, rowspan, colspan + layout.addWidget(self.config.wafer_config.structure_file.view.ui_field(), 2, 0) # row, column, rowspan, colspan + grid_group_box.setLayout(layout) self.layout.addWidget(grid_group_box) @@ -60,48 +52,15 @@ class WidgetSettingsOutFilesFolders(QWidget): def init_UI(self): layout = QGridLayout() - grid_group_box = QGroupBox("Output Files") + grid_group_box = QGroupBox("Analog Discovery 2 Settings") grid_group_box.setLayout(layout) + layout.addWidget(self.config.view.widget(max_level=0), 0, 0) + tree = QTreeWidget() - self.lbl_log_file = QLabel(parent=self) - self.tb_log_file.textChanged.connect(self.on_tb_log_file_text_changed) - self.on_tb_log_file_text_changed(self.tb_log_file.text()) - layout.addWidget(QLabel("Log File"), 0, 0) # row, column, rowspan, colspan - layout.addWidget(self.tb_log_file, 0, 1) # row, column, rowspan, colspan - layout.addWidget(self.lbl_log_file, 1, 0, 1, 2) # row, column, rowspan, colspan - - # measurement output - self.lbl_measurement_output = QLabel(parent=self) - self.tb_measurement_output.textChanged.connect(self.on_tb_measurement_output_text_changed) - self.on_tb_measurement_output_text_changed(self.tb_measurement_output.text()) - layout.addWidget(QLabel("Measurement output"), 2, 0) # row, column, rowspan, colspan - layout.addWidget(self.tb_measurement_output, 2, 1) # row, column, rowspan, colspan - layout.addWidget(self.lbl_measurement_output, 3, 0, 1, 2) # row, column, rowspan, colspan - - # Mat files output - self.lbl_mat_files_output = QLabel(parent=self) - self.on_tb_mat_files_output_text_changed(self.tb_mat_files_output.text()) - - self.tb_mat_files_output.textChanged.connect(self.on_tb_mat_files_output_text_changed) - layout.addWidget(QLabel("Matlab Files"), 4, 0) # row, column, rowspan, colspan - layout.addWidget(self.tb_mat_files_output, 4, 1) # row, column, rowspan, colspan - layout.addWidget(self.lbl_mat_files_output, 5, 0, 1, 2) # row, column, rowspan, colspan - - # bookmark files - self.lbl_bookmark_file = QLabel(parent=self) - self.on_tb_bookmark_file_text_changed(self.tb_bookmark_file.text()) - self.tb_bookmark_file.textChanged.connect(self.on_tb_bookmark_file_text_changed) - self.tb_scope_image_file.textChanged.connect(self.on_tb_scope_image_file_text_changed) - layout.addWidget(QLabel("Bookmark files"), 6, 0) # row, column, rowspan, colspan - layout.addWidget(self.tb_bookmark_file, 6, 1) # row, column, rowspan, colspan - layout.addWidget(self.lbl_bookmark_file, 7, 0, 1, 2) # row, column, rowspan, colspan - - # scope shots - self.lbl_scope_image_file = QLabel(parent=self) - self.on_tb_scope_image_file_text_changed(self.tb_scope_image_file.text()) - layout.addWidget(QLabel("Scope Shots"), 8, 0) # row, column, rowspan, colspan - layout.addWidget(self.tb_scope_image_file, 8, 1) # row, column, rowspan, colspan - layout.addWidget(self.lbl_scope_image_file, 9, 0, 1, 2) + tree.setColumnCount(3) + tree.setHeaderLabels(["Name", "Type", "Description"]) + tree.addTopLevelItem(self.config.view.ui_tree_widget_item(tree, max_level=0)) + layout.addWidget(tree, 1, 0) self.layout.addWidget(grid_group_box) self.setLayout(self.layout) @@ -183,48 +142,13 @@ class WidgetAD2Settings(QWidget): layout = QGridLayout() grid_group_box = QGroupBox("Analog Discovery 2 Settings") grid_group_box.setLayout(layout) + layout.addWidget(self.config.view.widget(), 0, 0) + tree = QTreeWidget() - lbl_sample_rate = QLabel("Sample Rate") - layout.addWidget(lbl_sample_rate, 1, 0) - #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.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.setSingleStep(1) - #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.setSingleStep(1) - #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) - #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) + tree.setColumnCount(3) + tree.setHeaderLabels(["Name", "Type", "Description"]) + tree.addTopLevelItem(self.config.view.ui_tree_widget_item(tree)) + layout.addWidget(tree, 1, 0) self.layout.addWidget(grid_group_box) self.setLayout(self.layout) @@ -257,72 +181,13 @@ class WidgetLaserSettings(QWidget): layout = QGridLayout() grid_group_box = QGroupBox("Laser Settings") grid_group_box.setLayout(layout) + layout.addWidget(self.config.view.widget(), 0, 0) + tree = QTreeWidget() - 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.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.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.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.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.config.laser_config.set_velocity(v)) - self.num_velocity.setRange(0, 10 ** 8) - self.num_velocity.setSingleStep(1) - #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.config.laser_config.set_acceleration(v)) - self.num_acceleration.setRange(0, 10 ** 8) - self.num_acceleration.setSingleStep(1) - #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.config.laser_config.set_deceleration(v)) - self.num_deceleration.setRange(0, 10 ** 8) - self.num_deceleration.setSingleStep(1) - #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) + tree.setColumnCount(3) + tree.setHeaderLabels(["Name", "Type", "Description"]) + tree.addTopLevelItem(self.config.view.ui_tree_widget_item(tree)) + layout.addWidget(tree, 1, 0) 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 9f8c4d1a8ebce10b50d91808c4755d81e849635e..6c6fb5c447b1450d1415d5f78c329423ce0b6d66 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/MeasuredData.py @@ -49,7 +49,7 @@ class MeasuredData: # ============================================================================================================== # COnnect the signals - self._measurement_properties.find_peaks.properties_changed.connect(self.find_peaks) + self.measurement_properties.find_peaks.properties_changed.connect(self.find_peaks) # ================================================================================================================== # diff --git a/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py index 37c00a116e6c7f58140c5b7f795f41a5ae6e5b92..bdf48ef3936c1763a7e680ee80f67b97c86250ef 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/MultiMeasuredData.py @@ -124,7 +124,7 @@ class MultiMeasuredData(MeasuredData): if __name__ == "__main__": - setup_logging() + #setup_logging() mypath = 'E:\measurements_06032022\measurements_06032022\mea_mzi2_2_2022_03_06\T40741W177G0\MaskARY1_Jakob\measurement_small' mm_data = MeasurementDataLoader.from_folder(mypath) diff --git a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py index 97877e5b59973d17780965608e26b9d84ba91835..e4aa424473ccd078507ae6f69246d07d7f42ba4b 100644 --- a/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py +++ b/src/FlexSensor/MeasurementData/MeasuredData/SingleMeasuredData.py @@ -655,7 +655,7 @@ if __name__ == "__main__": app = QApplication() # Load a mat file from E:\03_Simulations\03_Simulations\measurements\Ary1 using scipy - setup_logging() + #setup_logging() # filename = r"E:\03_Simulations\03_Simulations\measurements\Ary1\Ary1_2021-03-10_15-00-00.mat" data1 = SingleMeasuredData.from_mat( r"support/measurement_die_22_struct_mzi2_2_20220306_1908_rep_11.mat" diff --git a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py index a471bcfd9e41841181ee5f55c6c9ff8dabf833e0..5d74c2ac9f1ce727b2294a3027704d2628d29131 100644 --- a/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py +++ b/src/FlexSensor/MeasurementRoutines/BasemeasurementRoutine.py @@ -11,20 +11,21 @@ import CaptDeviceControl as CaptDevice import LaserControl as Laser import confighandler as Config +from FlexSensor.FSBase import FSBase from FlexSensor.FlexSensorConfig import FlexSensorConfig from FlexSensor.Prober.controller.ProberController import ProberController from FlexSensor.MeasurementRoutines.WorkerSignals import WorkerSignals -class BaseMeasurementRoutine(QObject): +class BaseMeasurementRoutine(QObject, FSBase): - def __init__(self, laser: Laser, ad2device: CaptDevice, prober: ProberController, config: FlexSensorConfig): + def __init__(self, laser: Laser.Controller, ad2device: CaptDevice.Controller, prober: ProberController, config: FlexSensorConfig): super().__init__() - self.logger = logging.getLogger("Base Measurement Routine") + self.logger = self.create_new_logger(self.name) self.config = config - self.ad2device: CaptDevice = ad2device - self.laser: Laser = laser + self.ad2device: CaptDevice.Controller = ad2device + self.laser: Laser.Controller = 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 0bc9d5122a989edb872e4eb4846b8392448eb7de..b8e1fde3ab1edf8421cf73b7141e70072b6a8f31 100644 --- a/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py +++ b/src/FlexSensor/MeasurementRoutines/MeasurementRoutine.py @@ -1,4 +1,5 @@ import logging +import time import traceback from datetime import datetime @@ -13,6 +14,8 @@ 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.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 @@ -56,19 +59,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.config.wafer_config.dies}\n" + f"Init Prober Class. Number of runs per die: {self.number_of_runs}, dies {self.config.wafer_config.dies.get()}\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.config.wafer_config.get_structure_file().relative}") - self.logger.info(f">> Working directory {self.config.output_directory.get().relative}") - self.logger.info(f">> Log File {self.config.wafer_config.log_file.get().relative}") - self.logger.info(f">> Measurments CVS File {self.config.wafer_config.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}") + self.logger.info(f"<< Input file {self.config.wafer_config.structure_file.get()}") + self.logger.info(f">> Working directory {self.config.output_directory.get()}") + self.logger.info(f">> Log File {self.config.wafer_config.log_file.get()}") + self.logger.info(f">> Measurements CVS File {self.config.wafer_config.measurement_output.get()}") + self.logger.info(f">> Measurements Mat File {self.config.wafer_config.measurement_mat_file.get()}") + self.logger.info(f">> KLayout Bookmark file {self.config.wafer_config.bookmark_file.get()}") + self.logger.info(f">> Scope Image File {self.config.wafer_config.scope_image_file.get()}") # as long as the connection was successful, we can send some commands. # if it was not successful, an exception is thrown. @@ -95,7 +98,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.config.wafer_config.dies): + for die_idx, die_no in enumerate(self.config.wafer_config.dies.get()): # 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) @@ -187,14 +190,14 @@ class MeasurementRoutine(BaseMeasurementRoutine): 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}") - self.prober.snap_image("eVue2", scope_file.absolute, 2) + self.write_log("info", f"{fmt} Saving scope image to {scope_file}") + self.prober.snap_image("eVue2", scope_file, 2) except Exception as e: - self.logger.warning(f"{fmt} Cannot save scope image to {scope_file.relative}: {e}\n\n" + self.logger.warning(f"{fmt} Cannot save scope image to {scope_file}: {e}\n\n" f"{traceback.format_exc()}") self.signals.warning.emit(type(e), - f"Cannot save scope image to {scope_file.relative}. {e}", + f"Cannot save scope image to {scope_file}. {e}", traceback.format_exc()) def _step_search_for_light(self, fmt): @@ -232,7 +235,13 @@ class MeasurementRoutine(BaseMeasurementRoutine): #captured_values = self.ad2device.model.recorded_samples # Just starts an endless loop #print(len(captured_values)) #measure_time = self.ad2device.model.recording_time - captured_values, measure_time = self.laser.sweep_and_measure() + self.laser.start_wavelength_sweep.emit(self.laser.model.sweep_start_wavelength, + self.laser.model.sweep_stop_wavelength) + while self.laser.model.wavelength_sweep_running: + self.logger.info(f"{fmt} Wavelength sweep running. Waiting for sweep to finish.") + time.sleep(1) + measure_time = self.ad2device.model.capturing_information.recording_time + captured_values = self.ad2device.model.capturing_information.recorded_samples self.write_log("info", f"{self.formatter} Finished data acquisition: {len(captured_values)}. Took {round(measure_time, 5)} seconds.") return measure_time, captured_values @@ -242,8 +251,12 @@ class MeasurementRoutine(BaseMeasurementRoutine): try: cur_measured_signal = SingleMeasuredData( - laser_properties=self.laser.model.laser_properties, - ad2_properties=self.ad2device.model.ad2_properties, + 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, 0, 0, 0), wafer_properties=wafer_properties, waveguide_properties=WaveguidePropertiesMZI( length1=mcpy.Rectangular(10e6, 20, unit='nm'), @@ -321,8 +334,10 @@ 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.config.wafer_config.get_scope_image_file( - keywords={"{die}": self.die_no, "{structure}": self.structure.name}), self.formatter) + self._step_snap_image( + str(self.config.wafer_config.scope_image_file.get()). + replace("{die}", str(self.die_no)). + replace("{structure}", str(self.structure.name)), self.formatter) # Search for the light self._step_search_for_light(self.formatter) @@ -337,7 +352,7 @@ class MeasurementRoutine(BaseMeasurementRoutine): # For displaying the data in the GUI measure_time, captured_values = self._step_capture_transmission(rep, self.formatter) data = [[ - self.config.wafer_nr, self.die_no, self.chuck_col, + self.config.wafer_number.get(), 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, @@ -346,20 +361,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.config.wafer_config.get_measurement_output())) + self.siph_data.to_csv(str(self.config.wafer_config.measurement_output.get())) self.siph_data.to_excel( 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.config.wafer_config.get_measurement_output()}", e, + f"{self.config.wafer_config.measurement_output.get()}", e, traceback) self.signals.error.emit((type(e), f"Could not write sphi data to file " - f"{self.config.wafer_config.get_measurement_output()}: {e}", + f"{self.config.wafer_config.measurement_output.get()}: {e}", traceback.format_exc())) wafer_properties = WaferProperties( - wafer_number=self.config.wafer_nr, + wafer_number=self.config.wafer_number.get(), structure_name=self.structure.name, die_nr=self.die_no, chuck_col=self.chuck_col, @@ -368,21 +383,21 @@ class MeasurementRoutine(BaseMeasurementRoutine): structure_out=(self.structure.x_out, self.structure.y_out), repetitions=rep) - cur_measured_signal = self._step_create_MeasuredSignal( - self.siph_data, - captured_values, - wafer_properties) - - cur_measured_signal._save_mat_file( - filename=self.config.wafer_config.get_measurement_mat_file(keywords={"{die}": self.die_no, - "{structure}": self.structure.name, - "{it}": f"rep_{rep + 1}"}).absolute - ) + #cur_measured_signal = self._step_create_MeasuredSignal( + # self.siph_data, + # captured_values, + # wafer_properties) + + #cur_measured_signal._save_mat_file( + # filename=self.config.wafer_config.get_measurement_mat_file(keywords={"{die}": self.die_no, + # "{structure}": self.structure.name, + # "{it}": f"rep_{rep + 1}"}).absolute + #) rep += 1 self.logger.info(f"Repetition {rep}/{self.structure.repetitions} measured successfully!") - self.signals.routine_iteration_finished.emit(cur_measured_signal, rep) + #self.signals.routine_iteration_finished.emit(cur_measured_signal, rep) # Report the progress to the frontend self.write_log("info", "[OK] Continuing with next structure.") # idx_struct = idx_struct + 1 diff --git a/src/FlexSensor/Prober/controller/OpticalInterface.py b/src/FlexSensor/Prober/controller/OpticalInterface.py index 4d1cb934953988128ad9365d85a7de13305083b2..d0bcc46b3441d8257a5937dd0041b554850a2c66 100644 --- a/src/FlexSensor/Prober/controller/OpticalInterface.py +++ b/src/FlexSensor/Prober/controller/OpticalInterface.py @@ -5,25 +5,18 @@ from Prober.model.OpticalInterfaceStoredData import OpticalInterfaceStoredData from constants.FlexsensorConstants import Probe from generics.generics import pch +from FlexSensor.FSBase import FSBase +class OpticalInterface(FSBase): - - - - - - - - - -class OpticalInterface(object): - - def __init__(self, prober_signals, msg_server): + def __init__(self, prober_signals, msg_server, + enable_log=True, log_level=logging.DEBUG, log_file=None): + super().__init__() self.stored = OpticalInterfaceStoredData() self.signals = prober_signals self.msg_server = msg_server - self.logger = logging.getLogger("Optical Interface") + self.logger = self.create_new_logger(self.name, enabled=enable_log, level=log_level) self.logger.info("Optical Interface initialized") # ================================================================================================================== diff --git a/src/FlexSensor/Prober/controller/OpticalProbesPosition.py b/src/FlexSensor/Prober/controller/OpticalProbesPosition.py index 19e061486ebbf6887f9f7ad90bfd226d4b8d5b34..bf2a8464ef08a7b6eaea036e035e4b989a1e6daf 100644 --- a/src/FlexSensor/Prober/controller/OpticalProbesPosition.py +++ b/src/FlexSensor/Prober/controller/OpticalProbesPosition.py @@ -1,13 +1,16 @@ import sys import logging +from FlexSensor.FSBase import FSBase -class OpticalProbesPosition: + +class OpticalProbesPosition(FSBase): def __init__(self, input: tuple, output: tuple): + super().__init__() self.INPUT: ProbePosition = ProbePosition(input) self.OUT: ProbePosition = ProbePosition(output) - self.logger = logging.getLogger('OpticalProbesPosition') + self.logger = self.create_new_logger(self.name) def __str__(self): diff --git a/src/FlexSensor/Prober/controller/ProberController.py b/src/FlexSensor/Prober/controller/ProberController.py index 70a2f9c5c9a512ea8b7ae147b52cd0dbec638383..b115c694b152fa129ddec03e6cc52fb331dbb25b 100644 --- a/src/FlexSensor/Prober/controller/ProberController.py +++ b/src/FlexSensor/Prober/controller/ProberController.py @@ -3,17 +3,21 @@ import logging 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.generics.generics import pch -class ProberController: - def __init__(self, model: ProberModel, *args, **kwargs): - +class ProberController(FSBase): + def __init__(self, model: ProberModel, + enable_log=True, log_level=logging.DEBUG, log_file=None, + *args, **kwargs): + super().__init__() self.model = model - self.logger = logging.getLogger("Prober") + self.logger = self.create_new_logger(self.name, enabled=enable_log, level=log_level) + self.signals = Prober.Signals() self.msg_server = Prober.MessageServerInterface() diff --git a/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py b/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py index d847ac3a11b51549c03a6fb7fa4706c79a2f645a..9191dc7f9d082a8251743e9252298085ef69d05f 100644 --- a/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py +++ b/src/FlexSensor/Prober/velox_api/simulator/VeloxSimulator.py @@ -12066,7 +12066,8 @@ class MessageServerInterface(object): } def __init__(self): - print ("MessageServerInterface: initializing") + pass + #print("MessageServerInterface: initializing") def __enter__(self): #-uc-# print ("MessageServerInterface: entering") diff --git a/src/FlexSensor/Prober/view/ProberControlWindow.py b/src/FlexSensor/Prober/view/ProberControlWindow.py index 7d88c5b1269d1def5090bc43e019b3eaac7de926..a037aa69ddd1889ec1ad8e3086da61b5ca08f8c2 100644 --- a/src/FlexSensor/Prober/view/ProberControlWindow.py +++ b/src/FlexSensor/Prober/view/ProberControlWindow.py @@ -50,7 +50,7 @@ class ProberControlWindow(QMainWindow): if __name__ == "__main__": - setup_logging() + #setup_logging() logging.warning("ProberControlWindow.py is not meant to be run as a script.") app = QApplication() diff --git a/src/FlexSensor/WaferConfig.py b/src/FlexSensor/WaferConfig.py index 4791bdcc8ec9d57c722a4f92d637be9e986d0541..5d67d40066060615e2668774d75220db27ae9bb2 100644 --- a/src/FlexSensor/WaferConfig.py +++ b/src/FlexSensor/WaferConfig.py @@ -4,6 +4,7 @@ Author(s): Christoph Schmidt <christoph.schmidt@tugraz.at> Created: 2023-10-19 12:35 Package Version: """ +import logging from pathlib import Path import confighandler as cfg @@ -13,7 +14,7 @@ class WaferConfig(cfg.ConfigNode): def __init__(self) -> None: super().__init__() - self.dies = cfg.Field("MaskARY1_Jakob_full") + self.dies = cfg.Field([29, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46]) self.structure_file = cfg.Field(Path("../vas-files/list_of_structures_picasso.vas")) self.wafermap_file = cfg.Field(Path("../Wafermapary1_48dies.map")) self.log_file = cfg.Field(Path("{output_directory}/log_{date_time}.log")) diff --git a/src/FlexSensor/generics/ApplicationInit.py b/src/FlexSensor/generics/ApplicationInit.py index dbbe4b2810311a8724cc57d9a8752fa8b15cdca9..31066eea59b7038f00dfab1cd4d98e0bc9233075 100644 --- a/src/FlexSensor/generics/ApplicationInit.py +++ b/src/FlexSensor/generics/ApplicationInit.py @@ -27,34 +27,31 @@ class ApplicationInit: 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") + #logging.info(f"Configuration file {file_path} not found") file_dialog = QFileDialog() + #file_dialog.setFilter("FlexSensor YAML Config File (*.yaml)") file_dialog.setFileMode(QFileDialog.ExistingFile) - file_path, _ = file_dialog.getOpenFileName(None, "Select a Configuration File") + # Set the type of files that can be selected + file_path, _ = file_dialog.getOpenFileName(None, "Select a Configuration File", filter="FlexSensor Config (*.yaml)") # check if file dialog cancle was clicked vaut_config = FlexSensorConfig() + vaut_config.module_log_level = logging.DEBUG + vaut_config.module_log_enabled = True if file_path != "": - vaut_config = FlexSensorConfig.load(file_path) - logging.info(f"Loading configuration file {file_path}") - logging.info(vaut_config) + vaut_config.load(file=file_path, as_auto_save=True) + #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 + def setup_logging(console_window=None): + # disable matplotlib logging + logging.getLogger('matplotlib').setLevel(logging.WARNING) + FORMAT = "%(name)s %(message)s" + logging.basicConfig( + level="INFO", format=FORMAT, datefmt="[%X]", handlers=[ + RichHandler(rich_tracebacks=True) + ] + ) + if console_window is not None: + logging.getLogger().addHandler(console_window) diff --git a/src/FlexSensor/generics/VASInputFileParser.py b/src/FlexSensor/generics/VASInputFileParser.py index 73eda1a89860792aaf51f328a613745cd341c5cf..2c1c0e84c39e5e6c586ec2f8f46b182455b603e8 100644 --- a/src/FlexSensor/generics/VASInputFileParser.py +++ b/src/FlexSensor/generics/VASInputFileParser.py @@ -1,4 +1,3 @@ - import ast import logging import os @@ -7,20 +6,22 @@ import pathlib import confighandler from PySide6.QtWidgets import QFileDialog +from FlexSensor.FSBase import FSBase + -#import velox.controller.velox_config as velox_config +# 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.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 @@ -29,20 +30,21 @@ class Structure: 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})") - + 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})") - + 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 + return self.is_reference + -class VASInputFileParser(): +class VASInputFileParser(FSBase): def __init__(self) -> None: self.logger = logging.getLogger("ParseInputFile") @@ -53,12 +55,10 @@ class VASInputFileParser(): 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 @@ -67,10 +67,10 @@ class VASInputFileParser(): 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}") - + 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 @@ -84,28 +84,27 @@ class VASInputFileParser(): structure = Structure( key, - int(value['x_in']), int(value['y_in']), - int(value['x_out']), int(value['y_out']), - int(value['enabled']), + 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'] + num = value['num'] spacing = 0 for idx in range(num): if idx > 0: - spacing = value['spacing'] - + spacing = value['spacing'] + value['y_in'] = value['y_in'] + spacing value['y_out'] = value['y_out'] + spacing - key_seq = f"{key}_{idx+1}" + key_seq = f"{key}_{idx + 1}" structs = self.as_single_struct(key_seq, value)[0] cur_list_of_structures.append((structs[0], structs[1])) @@ -117,7 +116,7 @@ class VASInputFileParser(): 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") + file_path, _ = file_dialog.getOpenFileName(None, "Select a VAS File", filter="*.vas") if file_path != "": pass return file_path @@ -126,7 +125,7 @@ class VASInputFileParser(): current_group = None cur_list_of_structures = {} structs = [] - #list_of_structures = {} + # 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()) @@ -137,7 +136,7 @@ class VASInputFileParser(): # 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: @@ -147,29 +146,29 @@ class VASInputFileParser(): current_group = value continue else: - key, value = self.convert(key, value) - - #list_of_structures[key] = value - if "bookmark" in key: + 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( + self.num_of_structs = len( [ - key for key in self.list_of_structures if self.list_of_structures[key].enabled == True - ] - ) + 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 @@ -177,7 +176,6 @@ class VASInputFileParser(): # 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 @@ -186,7 +184,7 @@ class VASInputFileParser(): # list_of_structs_sub = [] # with open(filename, 'r') as f: - + # for idx, line in enumerate(f): # line = line.strip() @@ -199,13 +197,13 @@ class VASInputFileParser(): # 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() @@ -226,7 +224,7 @@ class VASInputFileParser(): # #-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(' ', ''): @@ -246,28 +244,26 @@ class VASInputFileParser(): # 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 @@ -282,12 +278,12 @@ class VASInputFileParser(): # 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) @@ -326,7 +322,6 @@ class VASInputFileParser(): # 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 != []: @@ -334,7 +329,7 @@ class VASInputFileParser(): # 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) @@ -342,37 +337,36 @@ class VASInputFileParser(): # 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" + self, cell_name="MaskARY1_final_2020_Feb_14", + bookmark_file="bookmarks.lyb" ): - print(f"Writing bookmarks to file {bookmark_file}") - + 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>" + 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") @@ -385,4 +379,4 @@ class VASInputFileParser(): # #for bookmark in bookmarks: # # print(f"{bookmark}: {bookmarks[bookmark]}") -# print(pi.num_of_runs) \ No newline at end of file +# print(pi.num_of_runs) diff --git a/src/FlexSensor/pathes.py b/src/FlexSensor/pathes.py index c0b004bf495a66c22a932eac274a39f53dd022e3..012c6cdc66d3788322be7e2747cd737fa332a516 100644 --- a/src/FlexSensor/pathes.py +++ b/src/FlexSensor/pathes.py @@ -6,9 +6,9 @@ import os import pathlib -content_root = "." +content_root = "./src/FlexSensor" # DO not change this unless you know what you are doing! -image_root = str(pathlib.Path(f"{content_root}/../images").resolve().absolute()) +image_root = str(pathlib.Path(f"{content_root}/resources").resolve().absolute()) libs_root = str(pathlib.Path(f"{content_root}/libs").resolve().absolute()) configs_root = str(pathlib.Path(f"{content_root}/../configs").resolve().absolute()) diff --git a/tests/testing_loggers.py b/tests/testing_loggers.py new file mode 100644 index 0000000000000000000000000000000000000000..eae28fe2648d1594822d81fb82e8d96b8a3452e4 --- /dev/null +++ b/tests/testing_loggers.py @@ -0,0 +1,57 @@ +import logging + +from rich.logging import RichHandler + + +class MyClass: + + # ================================================================================================================== + # Public methods + # ================================================================================================================== + def __init__(self): + self.name = self.__class__.__name__ + self.logger = self.create_new_logger(self.name) + + def create_new_logger(self, logger_name: str, + logger_format: str = "%(asctime)s - %(name)s %(message)s", + to_file='mylog.log', + level=logging.DEBUG) -> logging.Logger: + + # Set the formatter + _std_handler_formatter = logging.Formatter(logger_format) + _file_handler_formatter = logging.Formatter(f"%(levelname)s {logger_format})") + + _std_handler: logging.Handler = RichHandler(rich_tracebacks=True) + _std_handler.setLevel(level) + _std_handler.setFormatter(_std_handler_formatter) + + # Add a file handler as well + _file_handler = logging.FileHandler(to_file) + _file_handler.setLevel(logging.DEBUG) # Always set the file handler to debug + _file_handler.setFormatter(_file_handler_formatter) + + # Assign the handler to the logger + _logger = logging.getLogger(logger_name) + _logger.handlers = [_std_handler, _file_handler] + _logger.setLevel(logging.DEBUG) # Set the logger to debug, so every message is printed using the file handler + + return _logger + + def test_logging(self, msg): + self.logger.warning(msg) + + +if __name__ == "__main__": + #logging.basicConfig(level=logging.INFO) + myclass = MyClass() + myclass.test_logging("MSG 1 Hello from MyClass") # The message is printed twice + + logger = logging.getLogger("mylogger") # create a new logger + logger.setLevel(logging.DEBUG) + # (Not expected) This does not print anything, despite the level is set to DEBUG + logger.debug("MSG 2 Hello from a new logger myLogger") + # (Expected) This does not print, since the default level is WARNING + logging.info("MSG 3 Hello from the default logger") + # This now prints, since the level is WARNING + logger.warning("MSG 4 Hello from a new logger myLogger") + logging.warning("MSG 5: Hello from the default logger")