Skip to content
38 changes: 15 additions & 23 deletions src/navigate/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,7 @@ def update_config_dict(
config_name : str
Name of dictionary to replace
new_config : dict or str
Dictionary values or
yaml file name
Dictionary values or yaml file name

Returns
-------
Expand Down Expand Up @@ -751,16 +750,16 @@ def verify_waveform_constants(manager, configuration):
# "delay",
]:
if k not in waveform_dict[microscope_name][zoom][laser].keys():
waveform_dict[microscope_name][zoom][laser][
k
] = config_dict["remote_focus"].get(k, "0")
waveform_dict[microscope_name][zoom][laser][k] = (
config_dict["remote_focus"].get(k, "0")
)
else:
try:
float(waveform_dict[microscope_name][zoom][laser][k])
except ValueError:
waveform_dict[microscope_name][zoom][laser][
k
] = config_dict["remote_focus"].get(k, "0")
waveform_dict[microscope_name][zoom][laser][k] = (
config_dict["remote_focus"].get(k, "0")
)

# delete non-exist lasers
for k in waveform_dict[microscope_name][zoom].keys():
Expand Down Expand Up @@ -1004,24 +1003,16 @@ def verify_configuration(manager, configuration):
laser_hardware_config = {"type": "Synthetic"}
laser_hardware_config["wavelength"] = laser_config["wavelength"]

update_config_dict(
manager,
laser_config,
"hardware",
laser_hardware_config
)
update_config_dict(manager, laser_config, "hardware", laser_hardware_config)

# zoom
zoom_config = device_config[microscope_name]["zoom"]
if "hardware" not in zoom_config:
update_config_dict(
manager,
zoom_config,
"hardware",
{"type": "Synthetic", "servo_id": 0}
manager, zoom_config, "hardware", {"type": "Synthetic", "servo_id": 0}
)
elif "type" not in zoom_config["hardware"]:
zoom_config["hardware"]["type"] = "Synthetic"
zoom_config["hardware"]["type"] = "Synthetic"

filter_wheel_config = device_config[microscope_name]["filter_wheel"]
if type(filter_wheel_config) == DictProxy:
Expand All @@ -1034,7 +1025,6 @@ def verify_configuration(manager, configuration):
[filter_wheel_config],
)


temp_config = device_config[microscope_name]["filter_wheel"]
for _, filter_wheel_config in enumerate(temp_config):
filter_wheel_idx = build_ref_name(
Expand Down Expand Up @@ -1091,7 +1081,7 @@ def verify_positions_config(positions):
return []

position_num = len(positions)
for i in range(position_num - 1, start_index-1, -1):
for i in range(position_num - 1, start_index - 1, -1):
position = positions[i]
try:
for j in range(len(position)):
Expand All @@ -1101,6 +1091,7 @@ def verify_positions_config(positions):

return positions


def support_deceased_configuration(configuration):
"""Support old version of configurations.

Expand All @@ -1120,7 +1111,9 @@ def support_deceased_configuration(configuration):
for microscope_name in device_config.keys():
microscope_config = device_config[microscope_name]
if "remote_focus_device" in microscope_config.keys():
microscope_config["remote_focus"] = microscope_config.pop("remote_focus_device")
microscope_config["remote_focus"] = microscope_config.pop(
"remote_focus_device"
)
is_updated = True
if "lasers" in microscope_config.keys():
microscope_config["laser"] = microscope_config.pop("lasers")
Expand All @@ -1136,4 +1129,3 @@ def support_deceased_configuration(configuration):
if stage["type"] in deceased_device_type_names:
stage["type"] = deceased_device_type_names[stage["type"]]
is_updated = True

48 changes: 39 additions & 9 deletions src/navigate/controller/configuration_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,14 @@ def __init__(self, configuration):
)
)

def change_microscope(self) -> bool:
def update_configuration(self) -> None:
"""Update the microscope configuration to reflect any changes made to it."""

self.microscope_config = self.configuration["configuration"]["microscopes"][
self.microscope_name
]

def change_microscope(self, microscope_name=None) -> bool:
"""Get the new microscope configuration dict according to the name.

Gets the name of the microscope, retrieves its configuration, and updates the
Expand All @@ -87,9 +94,11 @@ def change_microscope(self) -> bool:
-------
result: bool
"""
microscope_name = self.configuration["experiment"]["MicroscopeState"][
"microscope_name"
]
if microscope_name is None:
microscope_name = self.configuration["experiment"]["MicroscopeState"][
"microscope_name"
]

assert (
microscope_name in self.configuration["configuration"]["microscopes"].keys()
)
Expand Down Expand Up @@ -255,7 +264,9 @@ def get_stage_position_limits(self, suffix):
if self.microscope_config is not None:
stage_dict = self.microscope_config["stage"]
for a in axes:
position_limits[a] = stage_dict.get(a + suffix, 0 if suffix == "_min" else 100)
position_limits[a] = stage_dict.get(
a + suffix, 0 if suffix == "_min" else 100
)
else:
for a in axes:
position_limits[a] = 0 if suffix == "_min" else 100
Expand All @@ -279,7 +290,7 @@ def stage_flip_flags(self):
for axis in self.stage_axes:
flip_flags[axis] = stage_dict.get(f"flip_{axis}", False)
return flip_flags

@property
def stage_axes(self):
"""Return the axes of the stage
Expand All @@ -298,9 +309,9 @@ def stage_axes(self):
else:
axes = list(stage_config["axes"])
return axes

return ["x", "y"]

@property
def all_stage_axes(self):
"""Return all the axes of the stage
Expand Down Expand Up @@ -411,6 +422,20 @@ def stage_setting_dict(self):
return self.microscope_config["stage"]
return None

@property
def has_analog_stage(self):
"""Check to see if the has_ni_galvo_stage flag is set in the configuration.

Returns
-------
has_ni_galvo_stage : bool
True if the microscope has an NI galvo stage, False otherwise.
"""

if self.microscope_config is not None:
return self.microscope_config["stage"].get("has_ni_galvo_stage", False)
return False

def get_stages_by_axis(self, axis_prefix="z"):
"""Return a list of all stage names.

Expand All @@ -430,7 +455,12 @@ def get_stages_by_axis(self, axis_prefix="z"):
stages = list(stages)
else:
stages = [stages]
return [f"{stage['type']} - {axis}" for stage in stages for axis in stage["axes"] if axis.startswith(axis_prefix)]
return [
f"{stage['type']} - {axis}"
for stage in stages
for axis in stage["axes"]
if axis.startswith(axis_prefix)
]
return []

@property
Expand Down
1 change: 1 addition & 0 deletions src/navigate/controller/sub_controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .microscope_popup import MicroscopePopupController # noqa
from .adaptive_optics import AdaptiveOpticsPopupController # noqa
from .histogram import HistogramController # noqa
from .stages_advanced import AdvancedStageParametersController # noqa

# from .uninstall_plugin_controller import UninstallPluginController # noqa
from .plugins import PluginsController, UninstallPluginController # noqa
Expand Down
47 changes: 42 additions & 5 deletions src/navigate/controller/sub_controllers/menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

# Third Party Imports

# Local Imports
# Local View Imports
from navigate.view.popups.ilastik_setting_popup import ilastik_setting_popup
from navigate.view.popups.autofocus_setting_popup import AutofocusPopup
from navigate.view.popups.adaptiveoptics_popup import AdaptiveOpticsPopup
Expand All @@ -53,6 +53,9 @@
)
from navigate.view.popups.feature_list_popup import FeatureListPopup
from navigate.view.popups.camera_setting_popup import CameraSettingPopup
from navigate.view.popups.stages_advanced_popup import AdvancedStageParametersPopup

# Local Controller Imports
from navigate.controller.sub_controllers.gui import GUIController
from navigate.controller.sub_controllers import (
AutofocusPopupController,
Expand All @@ -65,7 +68,10 @@
FeatureAdvancedSettingController,
AdaptiveOpticsPopupController,
UninstallPluginController,
AdvancedStageParametersController,
)

# Local Tools Imports
from navigate.tools.file_functions import save_yaml_file, load_yaml_file
from navigate.tools.decorators import FeatureList
from navigate.tools.common_functions import load_module_from_file, combine_funcs
Expand Down Expand Up @@ -359,6 +365,14 @@ def initialize_menus(self):
None,
],
"add_separator_1": [None, None, None, None, None],
"Advanced Stage Parameters": [
"standard",
self.stage_limits_popup,
None,
None,
None,
],
"add_separator_2": [None, None, None, None, None],
},
}
self.populate_menu(stage_control_menu)
Expand Down Expand Up @@ -1002,17 +1016,25 @@ def popup_help(self) -> None:
def toggle_stage_limits(self, *args) -> None:
"""Toggle stage limits."""
if self.disable_stage_limits.get() == 1:
limits_enabled = False
self.parent_controller.configuration["experiment"]["StageParameters"][
"limits"
] = False
] = limits_enabled
logger.debug("Disabling stage limits")
self.parent_controller.execute("stage_limits", False)
self.parent_controller.execute("stage_limits", limits_enabled)
else:
limits_enabled = True
self.parent_controller.configuration["experiment"]["StageParameters"][
"limits"
] = True
] = limits_enabled
logger.debug("Enabling stage limits")
self.parent_controller.execute("stage_limits", True)
self.parent_controller.execute("stage_limits", limits_enabled)

# If the stage limits popup is open, update it.
if hasattr(self.parent_controller, "stage_limits_popup_controller"):
self.parent_controller.stage_limits_popup_controller.view.enable_stage_limits_var.set(
limits_enabled
)

@log_function_call
def popup_autofocus_setting(self, *args) -> None:
Expand Down Expand Up @@ -1422,3 +1444,18 @@ def func(*args):
)

return func

def stage_limits_popup(self, *args, **kwargs) -> None:
"""Pop up the Stage Limits setting window."""
if hasattr(self.parent_controller, "stage_limits_popup_controller"):
self.parent_controller.stage_limits_popup_controller.showup()
return
popup = AdvancedStageParametersPopup(self.view)
stage_limits_controller = AdvancedStageParametersController(
popup, self.parent_controller
)
setattr(
self.parent_controller,
"stage_limits_popup_controller",
stage_limits_controller,
)
16 changes: 10 additions & 6 deletions src/navigate/controller/sub_controllers/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,6 @@ def __init__(
command=self.parent_controller.channels_tab_controller.update_end_position
)



def stage_key_press(self, event: tk.Event) -> None:
"""The stage key press.

Expand Down Expand Up @@ -210,6 +208,7 @@ def initialize(self) -> None:
"""Initialize the Stage limits of steps and positions."""
config = self.parent_controller.configuration_controller
self.stage_axes = config.stage_axes

# disable stages not available for the current microscope
for axis in set(config.all_stage_axes) - set(self.stage_axes):
stage_frame = getattr(self.view, f"{axis}_frame")
Expand Down Expand Up @@ -310,7 +309,7 @@ def disable_synthetic_stages(self, config: ConfigurationController) -> None:
elif axis == "y":
self.view.xy_frame.toggle_button_states(flag, ["y"])
self.view.position_frame.inputs["y"].widget.config(state=state)

else:
stage_frame = getattr(self.view, f"{axis}_frame")
stage_frame.toggle_button_states(flag, [axis])
Expand Down Expand Up @@ -621,6 +620,7 @@ def update_step_size_handler(self, axis: str) -> Callable[[], None]:
handler : Callable[[], None]
Function to update step size in experiment.yml.
"""

def func(*args):
"""Callback functions bind to step size variables."""
microscope_name = self.parent_controller.configuration["experiment"][
Expand Down Expand Up @@ -659,15 +659,19 @@ def set_hover_descriptions(self) -> None:
description = f"\N{GREEK SMALL LETTER MU}m in {axis.upper()}."

for i in range(len(btn_prefix)):
exec(f"self.view.{frame_prefix}_frame.{btn_prefix[i]}_{btn_suffix}.hover."
f"setdescription('Move {step_multiple[i] * step_value} {description}')")
exec(
f"self.view.{frame_prefix}_frame.{btn_prefix[i]}_{btn_suffix}.hover."
f"setdescription('Move {step_multiple[i] * step_value} {description}')"
)

# Position Frame
for axis in self.stage_axes:
if axis == "theta":
description = "Theta stage position in degrees."
else:
description = f"{axis.upper()} stage position in \N{GREEK SMALL LETTER MU}m."
description = (
f"{axis.upper()} stage position in \N{GREEK SMALL LETTER MU}m."
)
self.view.position_frame.inputs[axis].widget.hover.setdescription(
description
)
Expand Down
Loading