Skip to content
Merged
116 changes: 66 additions & 50 deletions src/navigate/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ def verify_experiment_config(manager, configuration):
"is_centered": True,
"center_x": 1024,
"center_y": 1024,
"readout_time": 0,
}
if (
"CameraParameters" not in configuration["experiment"]
Expand All @@ -371,58 +372,73 @@ def verify_experiment_config(manager, configuration):
"CameraParameters",
camera_parameters_dict_sample,
)
camera_setting_dict = configuration["experiment"]["CameraParameters"]
for k in camera_parameters_dict_sample:
if k not in camera_setting_dict.keys():
camera_setting_dict[k] = camera_parameters_dict_sample[k]
# binning
if camera_setting_dict["binning"] not in ["1x1", "2x2", "4x4"]:
camera_setting_dict["binning"] = "1x1"
# x_pixels and y_pixels
try:
camera_setting_dict["x_pixels"] = int(camera_setting_dict["x_pixels"])
except ValueError:
camera_setting_dict["x_pixels"] = camera_parameters_dict_sample["x_pixels"]

try:
camera_setting_dict["y_pixels"] = int(camera_setting_dict["y_pixels"])
except ValueError:
camera_setting_dict["y_pixels"] = camera_parameters_dict_sample["y_pixels"]

# image width and height
if camera_setting_dict["x_pixels"] <= 0:
camera_setting_dict["x_pixels"] = camera_parameters_dict_sample["x_pixels"]
if camera_setting_dict["y_pixels"] <= 0:
camera_setting_dict["y_pixels"] = camera_parameters_dict_sample["y_pixels"]
x_binning = int(camera_setting_dict["binning"][0])
y_binning = int(camera_setting_dict["binning"][2])
img_x_pixels = camera_setting_dict["x_pixels"] // x_binning
img_y_pixels = camera_setting_dict["y_pixels"] // y_binning
camera_setting_dict["img_x_pixels"] = img_x_pixels
camera_setting_dict["img_y_pixels"] = img_y_pixels
if camera_setting_dict["is_centered"]:
camera_setting_dict["center_x"] = camera_setting_dict["x_pixels"] // 2
camera_setting_dict["center_y"] = camera_setting_dict["y_pixels"] // 2

# sensor mode
if camera_setting_dict["sensor_mode"] not in ["Normal", "Light-Sheet"]:
camera_setting_dict["sensor_mode"] = "Normal"
if camera_setting_dict["readout_direction"] not in [
"Top-to-Bottom",
"Bottom-to-Top",
"Bidirectional",
"Rev. Bidirectional",
]:
camera_setting_dict["readout_direction"] = "Top-to-Bottom"

# databuffer_size, number_of_pixels
for k in ["databuffer_size", "number_of_pixels", "frames_to_average"]:
microscope_names = [""] + list(configuration["configuration"]["microscopes"].keys())
for microscope_name in microscope_names:
camera_setting_dict = configuration["experiment"]["CameraParameters"]
if microscope_name:
if (
microscope_name not in camera_setting_dict
or type(camera_setting_dict[microscope_name]) is not DictProxy
):
update_config_dict(
manager,
camera_setting_dict,
microscope_name,
camera_parameters_dict_sample,
)
camera_setting_dict = camera_setting_dict[microscope_name]

for k in camera_parameters_dict_sample:
if k not in camera_setting_dict.keys():
camera_setting_dict[k] = camera_parameters_dict_sample[k]
# binning
if camera_setting_dict["binning"] not in ["1x1", "2x2", "4x4"]:
camera_setting_dict["binning"] = "1x1"
# x_pixels and y_pixels
try:
camera_setting_dict[k] = int(camera_setting_dict[k])
camera_setting_dict["x_pixels"] = int(camera_setting_dict["x_pixels"])
except ValueError:
camera_setting_dict[k] = camera_parameters_dict_sample[k]
if camera_setting_dict[k] < 1:
camera_setting_dict[k] = camera_parameters_dict_sample[k]
camera_setting_dict["x_pixels"] = camera_parameters_dict_sample["x_pixels"]

try:
camera_setting_dict["y_pixels"] = int(camera_setting_dict["y_pixels"])
except ValueError:
camera_setting_dict["y_pixels"] = camera_parameters_dict_sample["y_pixels"]

# image width and height
if camera_setting_dict["x_pixels"] <= 0:
camera_setting_dict["x_pixels"] = camera_parameters_dict_sample["x_pixels"]
if camera_setting_dict["y_pixels"] <= 0:
camera_setting_dict["y_pixels"] = camera_parameters_dict_sample["y_pixels"]
x_binning = int(camera_setting_dict["binning"][0])
y_binning = int(camera_setting_dict["binning"][2])
img_x_pixels = camera_setting_dict["x_pixels"] // x_binning
img_y_pixels = camera_setting_dict["y_pixels"] // y_binning
camera_setting_dict["img_x_pixels"] = img_x_pixels
camera_setting_dict["img_y_pixels"] = img_y_pixels
if camera_setting_dict["is_centered"]:
camera_setting_dict["center_x"] = camera_setting_dict["x_pixels"] // 2
camera_setting_dict["center_y"] = camera_setting_dict["y_pixels"] // 2

# sensor mode
if camera_setting_dict["sensor_mode"] not in ["Normal", "Light-Sheet"]:
camera_setting_dict["sensor_mode"] = "Normal"
if camera_setting_dict["readout_direction"] not in [
"Top-to-Bottom",
"Bottom-to-Top",
"Bidirectional",
"Rev. Bidirectional",
]:
camera_setting_dict["readout_direction"] = "Top-to-Bottom"

# databuffer_size, number_of_pixels
for k in ["databuffer_size", "number_of_pixels", "frames_to_average"]:
try:
camera_setting_dict[k] = int(camera_setting_dict[k])
except ValueError:
camera_setting_dict[k] = camera_parameters_dict_sample[k]
if camera_setting_dict[k] < 1:
camera_setting_dict[k] = camera_parameters_dict_sample[k]

# stage parameters
stage_dict_sample = {}
Expand Down
144 changes: 76 additions & 68 deletions src/navigate/controller/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,18 @@ def update_buffer(self):
Size dictated by x_pixels, y_pixels, an number_of_frames in
configuration file.
"""
microscope_name = self.configuration["experiment"]["MicroscopeState"][
"microscope_name"
]
img_width = int(
self.configuration["experiment"]["CameraParameters"]["img_x_pixels"]
self.configuration["experiment"]["CameraParameters"][microscope_name][
"img_x_pixels"
]
)
img_height = int(
self.configuration["experiment"]["CameraParameters"]["img_y_pixels"]
self.configuration["experiment"]["CameraParameters"][microscope_name][
"img_y_pixels"
]
)
if img_width == self.img_width and img_height == self.img_height:
return
Expand All @@ -325,11 +332,6 @@ def update_buffer(self):
self.img_width = img_width
self.img_height = img_height

# virtual microscopes
for microscope_name in list(self.additional_microscopes.keys()):
self.destroy_virtual_microscope(microscope_name)
self.additional_microscopes = {}

def update_acquire_control(self):
"""Update the acquire control based on the current experiment parameters."""
self.view.acqbar.stop_stage.config(
Expand All @@ -356,6 +358,7 @@ def change_microscope(self, microscope_name, zoom=None):
self.stage_controller.initialize()
self.channels_tab_controller.initialize()
self.camera_setting_controller.update_camera_device_related_setting()
self.camera_setting_controller.populate_experiment_values()
self.camera_setting_controller.calculate_physical_dimensions()
self.camera_view_controller.update_snr()

Expand Down Expand Up @@ -451,10 +454,15 @@ def update_experiment_setting(self):

"""
warning_message = self.camera_setting_controller.update_experiment_values()
microscope_name = self.configuration["experiment"]["MicroscopeState"][
"microscope_name"
]

# set waveform template
if self.acquire_bar_controller.mode in ["live", "single", "z-stack"]:
camera_setting = self.configuration["experiment"]["CameraParameters"]
camera_setting = self.configuration["experiment"]["CameraParameters"][
microscope_name
]
if camera_setting["sensor_mode"] == "Light-Sheet" and camera_setting[
"readout_direction"
] in ["Bidirectional", "Rev. Bidirectional"]:
Expand Down Expand Up @@ -482,6 +490,13 @@ def update_experiment_setting(self):
# TODO: validate experiment dict

warning_message += self.channels_tab_controller.verify_experiment_values()

# additional microscopes
for microscope_name in self.additional_microscopes_configs:
if hasattr(self, f"{microscope_name.lower()}_camera_setting_controller"):
getattr(
self, f"{microscope_name.lower()}_camera_setting_controller"
).update_experiment_values()
if warning_message:
return warning_message
return ""
Expand Down Expand Up @@ -557,6 +572,14 @@ def set_mode_of_sub(self, mode):
self.camera_setting_controller.set_mode(mode)
self.mip_setting_controller.set_mode(mode)
self.waveform_tab_controller.set_mode(mode)

# additional microscopes
for microscope_name in self.additional_microscopes_configs:
if hasattr(self, f"{microscope_name.lower()}_camera_setting_controller"):
getattr(
self, f"{microscope_name.lower()}_camera_setting_controller"
).set_mode(mode)

if mode == "stop":
# GUI Failsafe
self.acquire_bar_controller.stop_acquire()
Expand Down Expand Up @@ -987,15 +1010,18 @@ def capture_image(self, command, mode, *args):
return
self.acquire_bar_controller.view.acquire_btn.configure(text="Stop")
self.acquire_bar_controller.view.acquire_btn.configure(state="normal")
microscope_name = self.configuration["experiment"]["MicroscopeState"][
"microscope_name"
]

self.camera_view_controller.initialize_non_live_display(
self.configuration["experiment"]["MicroscopeState"],
self.configuration["experiment"]["CameraParameters"],
self.configuration["experiment"]["CameraParameters"][microscope_name],
)

self.mip_setting_controller.initialize_non_live_display(
self.configuration["experiment"]["MicroscopeState"],
self.configuration["experiment"]["CameraParameters"],
self.configuration["experiment"]["CameraParameters"][microscope_name],
)

self.stop_acquisition_flag = False
Expand Down Expand Up @@ -1076,11 +1102,15 @@ def capture_image(self, command, mode, *args):
def launch_additional_microscopes(self):
"""Launch additional microscopes."""

def display_images(camera_view_controller, show_img_pipe, data_buffer):
def display_images(
microscope_name, camera_view_controller, show_img_pipe, data_buffer
):
"""Display images from additional microscopes.

Parameters
----------
microscope_name : str
Microscope name
camera_view_controller : CameraViewController
Camera View Controller object.
show_img_pipe : multiprocessing.Pipe
Expand All @@ -1091,9 +1121,8 @@ def display_images(camera_view_controller, show_img_pipe, data_buffer):
configuration file.
"""
camera_view_controller.initialize_non_live_display(
data_buffer,
self.configuration["experiment"]["MicroscopeState"],
self.configuration["experiment"]["CameraParameters"],
self.configuration["experiment"]["CameraParameters"][microscope_name],
)
images_received = 0
while True:
Expand Down Expand Up @@ -1122,72 +1151,51 @@ def display_images(camera_view_controller, show_img_pipe, data_buffer):
break
images_received += 1

# destroy unnecessary additional microscopes
temp = []
for microscope_name in self.additional_microscopes:
if microscope_name not in self.additional_microscopes_configs:
temp.append(microscope_name)
for microscope_name in temp:
# destroy all additional microscopes
for microscope_name in list(self.additional_microscopes.keys()):
self.destroy_virtual_microscope(microscope_name)
self.additional_microscopes = {}

# show additional camera view popup
for microscope_name in self.additional_microscopes_configs:
if microscope_name not in self.additional_microscopes:
show_img_pipe = self.model.create_pipe(
f"{microscope_name}_show_img_pipe"
)
data_buffer = self.model.launch_virtual_microscope(
microscope_name,
self.additional_microscopes_configs[microscope_name],
)
show_img_pipe = self.model.create_pipe(f"{microscope_name}_show_img_pipe")
data_buffer = self.model.launch_virtual_microscope(
microscope_name,
self.additional_microscopes_configs[microscope_name],
)

self.additional_microscopes[microscope_name] = {
"show_img_pipe": show_img_pipe,
"data_buffer": data_buffer,
}
if (
self.additional_microscopes[microscope_name].get(
"camera_view_controller", None
)
is None
):
popup_window = CameraViewPopupWindow(self.view, microscope_name)
camera_view_controller = CameraViewController(
popup_window.camera_view, self
)
camera_view_controller.data_buffer = self.additional_microscopes[
microscope_name
]["data_buffer"]
popup_window.popup.bind("<Configure>", camera_view_controller.resize)
self.additional_microscopes[microscope_name][
"popup_window"
] = popup_window
self.additional_microscopes[microscope_name][
"camera_view_controller"
] = camera_view_controller
popup_window.popup.protocol(
"WM_DELETE_WINDOW",
combine_funcs(
popup_window.popup.dismiss,
lambda: self.additional_microscopes[microscope_name].pop(
"camera_view_controller"
),
self.additional_microscopes[microscope_name] = {
"show_img_pipe": show_img_pipe,
"data_buffer": data_buffer,
}
popup_window = CameraViewPopupWindow(self.view, microscope_name)
camera_view_controller = CameraViewController(
popup_window.camera_view, self
)
camera_view_controller.data_buffer = self.additional_microscopes[
microscope_name
]["data_buffer"]
camera_view_controller.microscope_name = microscope_name
popup_window.popup.bind("<Configure>", camera_view_controller.resize)
self.additional_microscopes[microscope_name]["popup_window"] = popup_window
self.additional_microscopes[microscope_name][
"camera_view_controller"
] = camera_view_controller
popup_window.popup.protocol(
"WM_DELETE_WINDOW",
combine_funcs(
popup_window.popup.dismiss,
lambda: self.additional_microscopes[microscope_name].pop(
"camera_view_controller"
),
)

# clear show_img_pipe
show_img_pipe = self.additional_microscopes[microscope_name][
"show_img_pipe"
]
while show_img_pipe.poll():
image_id = show_img_pipe.recv()
if image_id == "stop":
break
),
)

# start thread
capture_img_thread = threading.Thread(
target=display_images,
args=(
microscope_name,
self.additional_microscopes[microscope_name][
"camera_view_controller"
],
Expand Down
Loading
Loading