feat: init
This commit is contained in:
203
test/config/test_experiment.py
Normal file
203
test/config/test_experiment.py
Normal file
@@ -0,0 +1,203 @@
|
||||
# Copyright (c) 2021-2025 The University of Texas Southwestern Medical Center.
|
||||
# All rights reserved.
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted for academic and research use only
|
||||
# (subject to the limitations in the disclaimer below)
|
||||
# provided that the following conditions are met:
|
||||
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# * Neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
|
||||
# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# Standard Imports
|
||||
import unittest
|
||||
import yaml
|
||||
import os
|
||||
import datetime
|
||||
|
||||
# Third Party Imports
|
||||
|
||||
# Local Imports
|
||||
|
||||
|
||||
class TextExperimentFile(unittest.TestCase):
|
||||
"""Test the experiment configuration file."""
|
||||
|
||||
def setUp(self):
|
||||
current_path = os.path.abspath(os.path.dirname(__file__))
|
||||
root_path = os.path.dirname(os.path.dirname(current_path))
|
||||
yaml_path = os.path.join(
|
||||
root_path, "src", "navigate", "config", "experiment.yml"
|
||||
)
|
||||
|
||||
with open(yaml_path) as file:
|
||||
self.data = yaml.safe_load(file)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def parse_entries(self, section, expected_values):
|
||||
"""Parse the entries in the configuration file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
section : str
|
||||
The section of the configuration file to parse
|
||||
expected_values : dict
|
||||
A dictionary of expected values for the section
|
||||
|
||||
|
||||
Raises
|
||||
------
|
||||
AssertionError
|
||||
If the key is not in the section or if the value is not the expected type
|
||||
"""
|
||||
keys = self.data[section].keys()
|
||||
for key in keys:
|
||||
self.assertIn(key, expected_values)
|
||||
assert isinstance(
|
||||
self.data[section][key], expected_values[key]
|
||||
), f"{key} is not of type {expected_values[key]}"
|
||||
|
||||
def test_user(self):
|
||||
expected_values = {"name": str}
|
||||
|
||||
self.parse_entries(section="User", expected_values=expected_values)
|
||||
|
||||
def test_saving(self):
|
||||
expected_values = {
|
||||
"root_directory": str,
|
||||
"save_directory": str,
|
||||
"user": str,
|
||||
"tissue": str,
|
||||
"celltype": str,
|
||||
"label": str,
|
||||
"file_type": str,
|
||||
"date": datetime.date,
|
||||
"solvent": str,
|
||||
}
|
||||
|
||||
self.parse_entries(section="Saving", expected_values=expected_values)
|
||||
|
||||
def test_camera_parameters(self):
|
||||
expected_values = {
|
||||
"x_pixels": int,
|
||||
"y_pixels": int,
|
||||
"sensor_mode": str,
|
||||
"readout_direction": str,
|
||||
"number_of_pixels": int,
|
||||
"binning": str,
|
||||
"pixel_size": float,
|
||||
"frames_to_average": float,
|
||||
"databuffer_size": int,
|
||||
}
|
||||
|
||||
self.parse_entries(section="CameraParameters", expected_values=expected_values)
|
||||
|
||||
def test_autofocus_parameters(self):
|
||||
expected_values = {
|
||||
"coarse_range": int,
|
||||
"coarse_step_size": int,
|
||||
"coarse_selected": int,
|
||||
"fine_range": int,
|
||||
"fine_step_size": int,
|
||||
"fine_selected": bool,
|
||||
"robust_fit": bool,
|
||||
"spline_fit": bool,
|
||||
"test_significance": bool,
|
||||
}
|
||||
|
||||
self.parse_entries(
|
||||
section="AutoFocusParameters", expected_values=expected_values
|
||||
)
|
||||
|
||||
def test_stage_parameters(self):
|
||||
expected_values = {
|
||||
"xy_step": float,
|
||||
"z_step": float,
|
||||
"theta_step": float,
|
||||
"f_step": float,
|
||||
"x": float,
|
||||
"y": float,
|
||||
"z": float,
|
||||
"theta": float,
|
||||
"f": float,
|
||||
"limits": bool,
|
||||
}
|
||||
|
||||
self.parse_entries(section="StageParameters", expected_values=expected_values)
|
||||
|
||||
def test_microscope_state(self):
|
||||
expected_values = {
|
||||
"microscope_name": str,
|
||||
"image_mode": str,
|
||||
"zoom": str,
|
||||
"stack_cycling_mode": str,
|
||||
"start_position": float,
|
||||
"end_position": float,
|
||||
"step_size": float,
|
||||
"number_z_steps": float,
|
||||
"timepoints": int,
|
||||
"stack_pause": float,
|
||||
"is_save": bool,
|
||||
"stack_acq_time": float,
|
||||
"timepoint_interval": int,
|
||||
"experiment_duration": float,
|
||||
"is_multiposition": bool,
|
||||
"channels": dict,
|
||||
"stack_z_origin": float,
|
||||
"stack_focus_origin": float,
|
||||
"start_focus": float,
|
||||
"end_focus": float,
|
||||
"abs_z_start": float,
|
||||
"abs_z_end": float,
|
||||
"waveform_template": str,
|
||||
}
|
||||
|
||||
self.parse_entries(section="MicroscopeState", expected_values=expected_values)
|
||||
|
||||
# Check that the channels dictionary has the correct keys
|
||||
channel_keys = self.data["MicroscopeState"]["channels"].keys()
|
||||
for key in channel_keys:
|
||||
# Number of channels can vary depending upon the experiment.
|
||||
assert "channel_" in key
|
||||
expected_values = {
|
||||
"is_selected": bool,
|
||||
"laser": str,
|
||||
"laser_index": int,
|
||||
"filter": str,
|
||||
"filter_position": int,
|
||||
"camera_exposure_time": float,
|
||||
"laser_power": str,
|
||||
"interval_time": str,
|
||||
"defocus": float,
|
||||
}
|
||||
|
||||
key_keys = self.data["MicroscopeState"]["channels"][key].keys()
|
||||
for key_key in key_keys:
|
||||
self.assertIn(key_key, expected_values)
|
||||
assert isinstance(
|
||||
self.data["MicroscopeState"]["channels"][key][key_key],
|
||||
expected_values[key_key],
|
||||
), f"{key_key} is not of type {expected_values[key_key]}"
|
||||
Reference in New Issue
Block a user