Skip to content

Commit

Permalink
Merge pull request #988 from TheDeanLab/docs-and-version
Browse files Browse the repository at this point in the history
Docs + Version
  • Loading branch information
AdvancedImagingUTSW authored Sep 14, 2024
2 parents 12b2b14 + 2eea7ed commit a01ce69
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 43 deletions.
1 change: 1 addition & 0 deletions docs/source/user_guide/acquiring_home.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ Acquiring Data
acquiring_guide
features/features
features/example_feature_lists
known_issues
24 changes: 24 additions & 0 deletions docs/source/user_guide/known_issues.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
============
Known Issues
============

This page lists known issues with the **navigate** software that currently do not have
an obvious solution. Please report any other issues you encounter on GitHub.

Slow Channel Switching
----------------------

When we operate multiple channels, there is a clear time delay between channels.
This is most obvious when operating in the continuous mode, or when you are acquiring
a Z-stack in the Per Z Laser Cycling mode.

This delay is associated with the time it takes to load the waveforms onto the DAQ
card. One possible solution is to write the waveforms to different channels on the
DAQ, but this would require that the analog/digital signals be combined physically.
For example, if CH00 was delivered on AO0, and CH01 was delivered on AO1, but both
were communicating with a single laser, then the signals could be combined and
delivered to the laser. However, a more obvious solution would be to reduce the time
necessary to load the waveforms onto the DAQ card. One immediate way to do this is by
reducing the DAQ sampling rate, but this would reduce the resolution of the waveforms
. More sophisticated DAQ systems, including an FPGA, could also be used to eliminate
this delay.
2 changes: 1 addition & 1 deletion src/navigate/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.7
0.0.8
64 changes: 48 additions & 16 deletions src/navigate/controller/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,33 @@ def __init__(
file paths or using synthetic hardware modes.
"""

#: Tk top-level widget: Tk.tk GUI instance.
self.root = root

#: Tk top-level widget: Tk.tk GUI instance.
self.splash_screen = splash_screen

#: string: Path to the configuration yaml file.
self.configuration_path = configuration_path

#: string: Path to the experiment yaml file.
self.experiment_path = experiment_path

#: string: Path to the waveform constants yaml file.
self.waveform_constants_path = waveform_constants_path

#: string: Path to the REST API yaml file.
self.rest_api_path = rest_api_path

#: string: Path to the waveform templates yaml file.
self.waveform_templates_path = waveform_templates_path

#: string: Path to the GUI configuration yaml file.
self.gui_configuration_path = gui_configuration_path

#: iterable: Non-default command line input arguments for
self.args = args

#: Object: Thread pool for the controller.
self.threads_pool = SynchronizedThreadPool()

Expand All @@ -152,34 +179,28 @@ def __init__(
#: dict: Configuration dictionary
self.configuration = load_configs(
self.manager,
configuration=configuration_path,
experiment=experiment_path,
waveform_constants=waveform_constants_path,
rest_api_config=rest_api_path,
waveform_templates=waveform_templates_path,
gui=gui_configuration_path,
configuration=self.configuration_path,
experiment=self.experiment_path,
waveform_constants=self.waveform_constants_path,
rest_api_config=self.rest_api_path,
waveform_templates=self.waveform_templates_path,
gui=self.gui_configuration_path,
)

verify_configuration(self.manager, self.configuration)
verify_experiment_config(self.manager, self.configuration)
verify_waveform_constants(self.manager, self.configuration)

# Initialize the Model
#: ObjectInSubprocess: Model object in MVC architecture.
self.model = ObjectInSubprocess(
Model, args, self.configuration, event_queue=self.event_queue
)

logger.info(f"Spec - Configuration Path: {configuration_path}")
logger.info(f"Spec - Experiment Path: {experiment_path}")
logger.info(f"Spec - Waveform Constants Path: {waveform_constants_path}")
logger.info(f"Spec - Rest API Path: {rest_api_path}")

#: mp.Pipe: Pipe for sending images from model to view.
self.show_img_pipe = self.model.create_pipe("show_img_pipe")

#: string: Path to the default experiment yaml file.
self.default_experiment_file = experiment_path
self.default_experiment_file = self.experiment_path

#: string: Path to the waveform constants yaml file.
self.waveform_constants_path = waveform_constants_path
Expand All @@ -188,7 +209,7 @@ def __init__(
self.configuration_controller = ConfigurationController(self.configuration)

#: View: View object in MVC architecture.
self.view = view(root)
self.view = view(self.root)

#: dict: Event listeners for the controller.
self.event_listeners = {}
Expand Down Expand Up @@ -289,14 +310,25 @@ def __init__(
self.initialize_cam_view()

# destroy splash screen and show main screen
splash_screen.destroy()
root.deiconify()
self.splash_screen.destroy()
self.root.deiconify()

#: int: ID for the resize event.Only works on Windows OS.
self.resize_event_id = None
if platform.system() == "Windows":
self.view.root.bind("<Configure>", self.resize)

logger.info(self.__repr__())

def __repr__(self):
return (
f'Controller("{self.root}", "{self.splash_screen}", '
f'"{self.configuration_path}", "{self.experiment_path}", '
f'"{self.waveform_constants_path}", "{self.rest_api_path}", '
f'"{self.waveform_templates_path}", "{self.gui_configuration_path}", '
f'"{self.args}")'
)

def update_buffer(self):
"""Update the buffer size according to the camera
dimensions listed in the experimental parameters.
Expand Down
9 changes: 1 addition & 8 deletions src/navigate/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,7 @@ def main():
--rest-api-file
--waveform-templates-file
--logging-confi
Returns
-------
None
Examples
--------
>>> python main.py --synthetic-hardware
--configurator
"""
if platform.system() != "Windows":
print(
Expand Down
57 changes: 48 additions & 9 deletions src/navigate/model/devices/camera/hamamatsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ def __init__(self, microscope_name, device_connection, configuration):
"""
super().__init__(microscope_name, device_connection, configuration)

#: str: Name of the microscope
self.microscope_name = microscope_name

#: object: Device connection
self.device_connection = device_connection

#: dict: Configuration settings
self.configuration = configuration

#: dict: Camera parameters
self.camera_parameters["x_pixels"] = self.camera_controller.max_image_width
self.camera_parameters["y_pixels"] = self.camera_controller.max_image_height
Expand Down Expand Up @@ -114,11 +123,9 @@ def __init__(self, microscope_name, device_connection, configuration):
"trigger_source", self.camera_parameters["trigger_source"]
)

logger.info("HamamatsuOrca Initialized")

def __del__(self):
"""Delete HamamatsuOrca class."""
logger.info("HamamatsuOrca Shutdown")
pass

@property
def serial_number(self):
Expand Down Expand Up @@ -205,7 +212,7 @@ def set_sensor_mode(self, mode):
] = self.camera_controller.step_image_height
else:
print("Camera mode not supported")
logger.info("Camera mode not supported")
logger.debug("Camera mode not supported")

def set_readout_direction(self, mode):
"""Set HamamatsuOrca readout direction.
Expand All @@ -230,7 +237,7 @@ def set_readout_direction(self, mode):
)
else:
print("Camera readout direction not supported")
logger.info("Camera readout direction not supported")
logger.debug("Camera readout direction not supported")

def calculate_readout_time(self):
"""Calculate duration of time needed to readout an image.
Expand Down Expand Up @@ -444,7 +451,15 @@ def __init__(self, microscope_name, device_connection, configuration):

# self.minimum_exposure_time = 6.304 * 10 ** -6

logger.info("HamamatsuOrcaLightning Initialized")
logger.info(self.__repr__())

def __repr__(self):
return (
f"HamamatsuOrcaLightning("
f"{self.microscope_name}, "
f"{self.device_connection}, "
f"{self.configuration})"
)

def calculate_light_sheet_exposure_time(
self, full_chip_exposure_time, shutter_width
Expand Down Expand Up @@ -515,7 +530,15 @@ def __init__(self, microscope_name, device_connection, configuration):
"image_height"
)

logger.info("HamamatsuOrcaFire Initialized")
logger.info(self.__repr__())

def __repr__(self):
return (
f"HamamatsuOrcaFire("
f"{self.microscope_name}, "
f"{self.device_connection}, "
f"{self.configuration})"
)

def calculate_light_sheet_exposure_time(
self, full_chip_exposure_time, shutter_width
Expand Down Expand Up @@ -582,7 +605,15 @@ def __init__(self, microscope_name, device_connection, configuration):

# self.minimum_exposure_time = 9.74436 * 10 ** -6

logger.info("HamamatsuOrca Initialized")
logger.info(self.__repr__())

def __repr__(self):
return (
f"HamamatsuOrca("
f"{self.microscope_name}, "
f"{self.device_connection}, "
f"{self.configuration})"
)

def calculate_light_sheet_exposure_time(
self, full_chip_exposure_time, shutter_width
Expand Down Expand Up @@ -646,7 +677,15 @@ def __init__(self, microscope_name, device_connection, configuration):
"Bottom-to-Top",
]

logger.info("HamamatsuOrcaFusion Initialized")
logger.info(self.__repr__())

def __repr__(self):
return (
f"HamamatsuOrcaFusion("
f"{self.microscope_name}, "
f"{self.device_connection}, "
f"{self.configuration})"
)

def calculate_light_sheet_exposure_time(
self, full_chip_exposure_time, shutter_width
Expand Down
31 changes: 23 additions & 8 deletions src/navigate/model/devices/camera/photometrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def __init__(self, microscope_name, device_connection, configuration):
Name of microscope in configuration
device_connection : object
Hardware device to connect to. will be saved in camera_controller
configuration : multiprocesing.managers.DictProxy
configuration : multiprocessing.managers.DictProxy
Global configuration of the microscope
-------
Expand All @@ -110,6 +110,15 @@ def __init__(self, microscope_name, device_connection, configuration):
"Bottom-to-Top",
]

#: str: Name of the microscope
self.microscope_name = microscope_name

#: obj: Camera Controller
self.device_connection = device_connection

#: dict: Configuration of the microscope
self.configuration = configuration

#: int: Exposure Time in milliseconds
self._exposuretime = 20

Expand Down Expand Up @@ -148,13 +157,20 @@ def __init__(self, microscope_name, device_connection, configuration):
]
self.camera_controller.gain = self.camera_parameters["gain"]

logger.info("Photometrics Initialized")
logger.info(self.__repr__())

def __repr__(self):
return (
f"PhotometricsBase("
f"{self.microscope_name}, "
f"{self.device_connection}, "
f"{self.configuration})"
)

def __del__(self):
"""Delete PhotometricsBase object."""
if hasattr(self, "camera_controller"):
self.camera_controller.close()
logger.info("PhotometricsBase Shutdown")

@property
def serial_number(self):
Expand Down Expand Up @@ -202,7 +218,7 @@ def set_sensor_mode(self, mode):
self._scanmode = modes_dict[mode]
else:
print("Camera mode not supported" + str(modes_dict[mode]))
logger.info("Camera mode not supported" + str(modes_dict[mode]))
logger.debug("Camera mode not supported" + str(modes_dict[mode]))

def set_readout_direction(self, mode):
"""Set Photometrics readout direction.
Expand All @@ -223,7 +239,7 @@ def set_readout_direction(self, mode):
elif mode == "Alternate":
self.camera_controller.prog_scan_dir = 2
else:
logger.info("Camera readout direction not supported")
logger.debug("Camera readout direction not supported")

def calculate_readout_time(self):
"""Calculate duration of time needed to readout an image.
Expand Down Expand Up @@ -409,9 +425,9 @@ def set_ROI(self, roi_width=3200, roi_height=3200, center_x=1600, center_y=1600)
return False

# Calculate Location of Image Edges
roi_top = center_y - roi_height//2
roi_top = center_y - roi_height // 2
roi_bottom = roi_top + roi_height - 1
roi_left = center_x - roi_width//2
roi_left = center_x - roi_width // 2

if roi_top % 2 != 0 or roi_bottom % 2 == 0:
logger.debug(f"can't set ROI to {roi_width} and {roi_height}")
Expand All @@ -420,7 +436,6 @@ def set_ROI(self, roi_width=3200, roi_height=3200, center_x=1600, center_y=1600)
# Set ROI
self.camera_controller.set_roi(roi_left, roi_top, roi_width, roi_height)
self.x_pixels, self.y_pixels = self.camera_controller.shape()
logger.info(f"Photometrics ROI shape, {self.camera_controller.shape()}")
return self.x_pixels == roi_width and self.y_pixels == roi_height

def initialize_image_series(self, data_buffer=None, number_of_frames=100):
Expand Down
Loading

0 comments on commit a01ce69

Please sign in to comment.