Refactor settings into base settings, fixup modules

TODO: reset
This commit is contained in:
lorow 2023-10-05 22:57:34 +02:00
parent ff5974ec8d
commit aa3be78f54
9 changed files with 130 additions and 162 deletions

View File

@ -2,61 +2,20 @@ import PySimpleGUI as sg
from config import EyeTrackConfig
from osc import EyeId
from queue import Queue
from threading import Event
from settings.BaseSettings import BaseSettingsWidget
from settings.modules.AdvancedTrackingAlgoSettingsModule import (
AdvancedTrackingAlgoSettingsModule,
)
from settings.modules.BlinkAlgoModule import BlinkAlgoSettingsModule
from settings.modules.TrackingAlgorithmModule import TrackingAlgorithmModule
class AlgoSettingsWidget:
def __init__(
self, widget_id: EyeId, main_config: EyeTrackConfig
):
self.gui_general_settings_layout = f"-GENERALSETTINGSLAYOUT{widget_id}-"
self.main_config = main_config
self.config = main_config.settings
# Define the window's contents
self.general_settings_layout = [
class AlgoSettingsWidget(BaseSettingsWidget):
def __init__(self, widget_id: EyeId, main_config: EyeTrackConfig):
settings_modules = [
TrackingAlgorithmModule,
BlinkAlgoSettingsModule,
AdvancedTrackingAlgoSettingsModule,
]
self.widget_layout = [
[
sg.Text(
"Tracking Algorithm Order Settings:", background_color="#242224"
),
],
[
sg.Column(
self.general_settings_layout,
key=self.gui_general_settings_layout,
background_color="#424042",
),
],
]
self.cancellation_event = (
Event()
) # Set the event until start is called, otherwise we can block if shutdown is called.
self.cancellation_event.set()
self.image_queue = Queue()
def started(self):
return not self.cancellation_event.is_set()
def start(self):
# If we're already running, bail
if not self.cancellation_event.is_set():
return
self.cancellation_event.clear()
def stop(self):
# If we're not running yet, bail
if self.cancellation_event.is_set():
return
self.cancellation_event.set()
def render(self, window, event, values):
# If anything has changed in our configuration settings, change/update those.
changed = False
if changed:
self.main_config.save()
super().__init__(widget_id, main_config, settings_modules)

View File

@ -148,14 +148,14 @@ def main():
background_color="#424042",
),
sg.Column(
settings[0].widget_layout,
settings[0].get_layout(),
vertical_alignment="top",
key=SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.SETTINGS]),
background_color="#424042",
),
sg.Column(
settings[1].widget_layout,
settings[1].get_layout(),
vertical_alignment="top",
key=ALGO_SETTINGS_NAME,
visible=(config.eye_display_id in [EyeId.ALGOSETTINGS]),

View File

@ -1,102 +1,18 @@
import PySimpleGUI as sg
from config import EyeTrackConfig, EyeTrackSettingsConfig
from config import EyeTrackConfig
from osc import EyeId
from threading import Event
from settings.BaseSettings import BaseSettingsWidget
from settings.modules.GeneralSettingsModule import GeneralSettingsModule
from settings.modules.OneEuroSettingsModule import OneEuroSettingsModule
from settings.modules.OSCSettingsModule import OSCSettingsModule
class SettingsWidget:
class SettingsWidget(BaseSettingsWidget):
def __init__(self, widget_id: EyeId, main_config: EyeTrackConfig):
self.is_saving = False
self.main_config = main_config
self.config = main_config.settings
settings_modules = [
GeneralSettingsModule,
OneEuroSettingsModule,
OSCSettingsModule,
]
super().__init__(widget_id, main_config, settings_modules)
self.initialized_modules = self._initialize_modules(
settings_modules=settings_modules, widget_id=widget_id
)
self.gui_general_settings_layout = f"-GENERALSETTINGSLAYOUT{widget_id}-"
# Define the window's contents
self.general_settings_layout = []
for module in self.initialized_modules:
self.general_settings_layout.extend(module.get_layout())
self.widget_layout = [
[
sg.Text("General Settings:", background_color="#242224"),
],
[
sg.Column(
self.general_settings_layout,
key=self.gui_general_settings_layout,
background_color="#424042",
),
],
]
self.cancellation_event = (
Event()
) # Set the event until start is called, otherwise we can block if shutdown is called.
self.cancellation_event.set()
def started(self):
return not self.cancellation_event.is_set()
def start(self):
# If we're already running, bail
if not self.cancellation_event.is_set():
return
self.cancellation_event.clear()
def stop(self):
# If we're not running yet, bail
if self.cancellation_event.is_set():
return
self.cancellation_event.set()
def _update_and_save_config(self, validated_data: dict):
self.main_config.update(validated_data, save=True)
self.is_saving = False
def _handle_errors(self, errors):
print(errors)
def render(self, window, event, values):
validated_data, errors = {}, []
# we might want to think about event driven architecture here eventually, validate only
# if anything changes instead of checking for changes
for module in self.initialized_modules:
module_validated_data = module.validate(values)
if module_validated_data.changes:
validated_data.update(module_validated_data.changes)
if module_validated_data.errors:
errors.append(module_validated_data.errors)
if not errors and validated_data and not self.is_saving:
self.is_saving = True
self._update_and_save_config(validated_data)
if errors:
self._handle_errors(errors)
def _initialize_modules(self, settings_modules, widget_id):
return [
module(
config=self.config,
settings=self.main_config,
settings_base_class=EyeTrackSettingsConfig,
widget_id=widget_id,
)
for module in settings_modules
]

View File

@ -2,19 +2,21 @@
from pythonosc import udp_client
from pythonosc import osc_server
from pythonosc import dispatcher
from config import EyeTrackConfig
from utils.misc_utils import PlaySound,SND_FILENAME,SND_ASYNC
import queue
import threading
from enum import IntEnum
import time
class EyeId(IntEnum):
RIGHT = 0
LEFT = 1
BOTH = 2
SETTINGS = 3
ALGOSETTINGS = 4
from config import EyeTrackConfig
def eyelid_transformer(self,eye_blink):
if self.config.osc_invert_eye_close:

View File

@ -0,0 +1,97 @@
from typing import Iterable, Optional
import PySimpleGUI as sg
from config import EyeTrackConfig, EyeTrackSettingsConfig
from threading import Event
from osc import EyeId # TODO this is bad, fix this
class BaseSettingsWidget:
def __init__(
self,
widget_id: EyeId,
main_config: EyeTrackConfig,
settings_modules: Iterable,
):
self.gui_general_settings_layout = f"-GENERALSETTINGSLAYOUT{widget_id}-"
self.is_saving = False
self.main_config = main_config
self.config = main_config.settings
self.initialized_modules = self._initialize_modules(
settings_modules=settings_modules, widget_id=widget_id
)
self.general_settings_layout = []
for module in self.initialized_modules:
self.general_settings_layout.extend(module.get_layout())
self.widget_layout = [
[
sg.Column(
self.general_settings_layout,
key=self.gui_general_settings_layout,
background_color="#424042",
),
],
]
self.cancellation_event = (
Event()
) # Set the event until start is called, otherwise we can block if shutdown is called.
self.cancellation_event.set()
def started(self):
return not self.cancellation_event.is_set()
def start(self):
# If we're already running, bail
if not self.cancellation_event.is_set():
return
self.cancellation_event.clear()
def stop(self):
# If we're not running yet, bail
if self.cancellation_event.is_set():
return
self.cancellation_event.set()
def _update_and_save_config(self, validated_data: dict):
self.main_config.update(validated_data, save=True)
self.is_saving = False
def _handle_errors(self, errors):
print(errors)
def render(self, window, event, values):
validated_data, errors = {}, []
# we might want to think about event driven architecture here eventually, validate only
# if anything changes instead of checking for changes
for module in self.initialized_modules:
module_validated_data = module.validate(values)
if module_validated_data.changes:
validated_data.update(module_validated_data.changes)
if module_validated_data.errors:
errors.append(module_validated_data.errors)
if not errors and validated_data and not self.is_saving:
self.is_saving = True
self._update_and_save_config(validated_data)
if errors:
self._handle_errors(errors)
def _initialize_modules(self, settings_modules, widget_id):
return [
module(
config=self.config,
settings=self.main_config,
settings_base_class=EyeTrackSettingsConfig,
widget_id=widget_id,
)
for module in settings_modules
]
def get_layout(self) -> Iterable:
return self.widget_layout

View File

@ -3,7 +3,6 @@ import PySimpleGUI as sg
class AdvancedTrackingAlgoSettingsValidationModel(BaseValidationModel):
gui_HSF_radius: int
gui_HSF_radius_left: int
gui_HSF_radius_right: int
gui_blob_maxsize: int
@ -12,22 +11,19 @@ class AdvancedTrackingAlgoSettingsValidationModel(BaseValidationModel):
gui_legacy_ransac_thresh_right: int
gui_skip_autoradius: bool
gui_thresh_add: int
gui_threshold_slider: int
gui_update_check: int
gui_threshold: int
class GeneralSettingsModule(BaseSettingsModule):
class AdvancedTrackingAlgoSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, settings_base_class, **kwargs):
super().__init__(config, widget_id, settings_base_class, **kwargs)
self.validation_model = AdvancedTrackingAlgoSettingsValidationModel
self.gui_HSF_radius = f"-HSFRADIUS{widget_id}-"
self.gui_blob_maxsize = f"-BLOBMAXSIZE{widget_id}-"
self.gui_blob_minsize = f"-BLOBMINSIZE{widget_id}-"
self.gui_skip_autoradius = f"-SKIPAUTORADIUS{widget_id}-"
self.gui_thresh_add = f"-THRESHADD{widget_id}-"
self.gui_update_check = f"-UPDATECHECK{widget_id}-"
self.gui_threshold_slider = f"-BLOBTHRESHOLD{widget_id}-"
self.gui_threshold = f"-BLOBTHRESHOLD{widget_id}-"
self.gui_HSF_radius_left = f"-HSFRADIUSLEFT{widget_id}-"
self.gui_HSF_radius_right = f"-HSFRADIUSRIGHT{widget_id}-"
@ -36,6 +32,7 @@ class GeneralSettingsModule(BaseSettingsModule):
def get_layout(self):
return [
[sg.Text("Advanced Tracking Algorithm Settings:", background_color="#242224")],
[
sg.Checkbox(
"HSF: Skip Auto Radius",
@ -81,7 +78,7 @@ class GeneralSettingsModule(BaseSettingsModule):
range=(0, 110),
default_value=self.config.gui_threshold,
orientation="h",
key=self.gui_threshold_slider,
key=self.gui_threshold,
background_color="#424042",
tooltip="Adjusts the threshold for blob tracking.",
),

View File

@ -14,7 +14,7 @@ class BlinkAlgoSettingsValidationModel(BaseValidationModel):
gui_circular_crop_right: bool
class GeneralSettingsModule(BaseSettingsModule):
class BlinkAlgoSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, settings_base_class, **kwargs):
super().__init__(config, widget_id, settings_base_class, **kwargs)
self.validation_model = BlinkAlgoSettingsValidationModel
@ -31,12 +31,6 @@ class GeneralSettingsModule(BaseSettingsModule):
def get_layout(self):
return [
[
sg.Text(
"Blink Algo Settings:",
background_color="#242224",
)
],
[sg.Text("Blink Algo Settings:", background_color="#242224")],
[
sg.Checkbox(

View File

@ -25,6 +25,9 @@ class GeneralSettingsModule(BaseSettingsModule):
def get_layout(self):
return [
[
sg.Text("General Settings:", background_color="#242224"),
],
[
sg.Checkbox(
"Flip Left Eye X Axis",

View File

@ -19,7 +19,7 @@ class TrackingAlgorithmValidationModel(BaseValidationModel):
gui_RANSAC3DP: int
class GeneralSettingsModule(BaseSettingsModule):
class TrackingAlgorithmModule(BaseSettingsModule):
def __init__(self, config, widget_id, settings_base_class, **kwargs):
super().__init__(config, widget_id, settings_base_class, **kwargs)
self.algo_count = ["1", "2", "3", "4", "5", "6"]