From c1624601a8e9620a9b818d41de4c7ae2b3d71cdf Mon Sep 17 00:00:00 2001 From: sfmig <33267254+sfmig@users.noreply.github.com> Date: Mon, 4 Dec 2023 19:20:47 +0000 Subject: [PATCH] unit tests for setup steps (WIP) --- tests/data/input_data_GIN.json | 39 ++++++++++ tests/data/input_data_locally.json | 39 ++++++++++ tests/data/input_data_missing_background.json | 39 ++++++++++ tests/data/input_data_missing_signal.json | 39 ++++++++++ tests/data/input_data_not_locally_or_GIN.json | 37 +++++++++ .../test_cellfinder_workflow.py | 2 +- tests/test_unit/test_cellfinder.py | 76 ++++++++++++++++++- workflows/cellfinder.py | 5 +- 8 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 tests/data/input_data_GIN.json create mode 100644 tests/data/input_data_locally.json create mode 100644 tests/data/input_data_missing_background.json create mode 100644 tests/data/input_data_missing_signal.json create mode 100644 tests/data/input_data_not_locally_or_GIN.json diff --git a/tests/data/input_data_GIN.json b/tests/data/input_data_GIN.json new file mode 100644 index 00000000..a80a4ba4 --- /dev/null +++ b/tests/data/input_data_GIN.json @@ -0,0 +1,39 @@ +{ + "install_path": ".cellfinder_workflows", + "data_url": "https://gin.g-node.org/BrainGlobe/test-data/raw/master/cellfinder/cellfinder-test-data.zip", + "data_hash": "b0ef53b1530e4fa3128fcc0a752d0751909eab129d701f384fc0ea5f138c5914", + "extract_dir_relative": "cellfinder_test_data", + "signal_subdir": "signal", + "background_subdir": "background", + "output_path_basename_relative": "cellfinder_output_", + "detected_cells_filename": "detected_cells.xml", + "voxel_sizes": [ + 5, + 2, + 2 + ], + "start_plane": 0, + "end_plane": -1, + "trained_model": null, + "model_weights": null, + "model": "resnet50_tv", + "batch_size": 32, + "n_free_cpus": 2, + "network_voxel_sizes": [ + 5, + 1, + 1 + ], + "soma_diameter": 16, + "ball_xy_size": 6, + "ball_z_size": 15, + "ball_overlap_fraction": 0.6, + "log_sigma_size": 0.2, + "n_sds_above_mean_thresh": 10, + "soma_spread_factor": 1.4, + "max_cluster_size": 100000, + "cube_width": 50, + "cube_height": 50, + "cube_depth": 20, + "network_depth": "50" +} diff --git a/tests/data/input_data_locally.json b/tests/data/input_data_locally.json new file mode 100644 index 00000000..a80a4ba4 --- /dev/null +++ b/tests/data/input_data_locally.json @@ -0,0 +1,39 @@ +{ + "install_path": ".cellfinder_workflows", + "data_url": "https://gin.g-node.org/BrainGlobe/test-data/raw/master/cellfinder/cellfinder-test-data.zip", + "data_hash": "b0ef53b1530e4fa3128fcc0a752d0751909eab129d701f384fc0ea5f138c5914", + "extract_dir_relative": "cellfinder_test_data", + "signal_subdir": "signal", + "background_subdir": "background", + "output_path_basename_relative": "cellfinder_output_", + "detected_cells_filename": "detected_cells.xml", + "voxel_sizes": [ + 5, + 2, + 2 + ], + "start_plane": 0, + "end_plane": -1, + "trained_model": null, + "model_weights": null, + "model": "resnet50_tv", + "batch_size": 32, + "n_free_cpus": 2, + "network_voxel_sizes": [ + 5, + 1, + 1 + ], + "soma_diameter": 16, + "ball_xy_size": 6, + "ball_z_size": 15, + "ball_overlap_fraction": 0.6, + "log_sigma_size": 0.2, + "n_sds_above_mean_thresh": 10, + "soma_spread_factor": 1.4, + "max_cluster_size": 100000, + "cube_width": 50, + "cube_height": 50, + "cube_depth": 20, + "network_depth": "50" +} diff --git a/tests/data/input_data_missing_background.json b/tests/data/input_data_missing_background.json new file mode 100644 index 00000000..cba67561 --- /dev/null +++ b/tests/data/input_data_missing_background.json @@ -0,0 +1,39 @@ +{ + "install_path": ".cellfinder_workflows", + "data_url": "https://gin.g-node.org/BrainGlobe/test-data/raw/master/cellfinder/cellfinder-test-data.zip", + "data_hash": "b0ef53b1530e4fa3128fcc0a752d0751909eab129d701f384fc0ea5f138c5914", + "extract_dir_relative": "cellfinder_test_data", + "signal_subdir": "signal", + "background_subdir": "__", + "output_path_basename_relative": "cellfinder_output_", + "detected_cells_filename": "detected_cells.xml", + "voxel_sizes": [ + 5, + 2, + 2 + ], + "start_plane": 0, + "end_plane": -1, + "trained_model": null, + "model_weights": null, + "model": "resnet50_tv", + "batch_size": 32, + "n_free_cpus": 2, + "network_voxel_sizes": [ + 5, + 1, + 1 + ], + "soma_diameter": 16, + "ball_xy_size": 6, + "ball_z_size": 15, + "ball_overlap_fraction": 0.6, + "log_sigma_size": 0.2, + "n_sds_above_mean_thresh": 10, + "soma_spread_factor": 1.4, + "max_cluster_size": 100000, + "cube_width": 50, + "cube_height": 50, + "cube_depth": 20, + "network_depth": "50" +} diff --git a/tests/data/input_data_missing_signal.json b/tests/data/input_data_missing_signal.json new file mode 100644 index 00000000..185e12a5 --- /dev/null +++ b/tests/data/input_data_missing_signal.json @@ -0,0 +1,39 @@ +{ + "install_path": ".cellfinder_workflows", + "data_url": "https://gin.g-node.org/BrainGlobe/test-data/raw/master/cellfinder/cellfinder-test-data.zip", + "data_hash": "b0ef53b1530e4fa3128fcc0a752d0751909eab129d701f384fc0ea5f138c5914", + "extract_dir_relative": "cellfinder_test_data", + "signal_subdir": "__", + "background_subdir": "background", + "output_path_basename_relative": "cellfinder_output_", + "detected_cells_filename": "detected_cells.xml", + "voxel_sizes": [ + 5, + 2, + 2 + ], + "start_plane": 0, + "end_plane": -1, + "trained_model": null, + "model_weights": null, + "model": "resnet50_tv", + "batch_size": 32, + "n_free_cpus": 2, + "network_voxel_sizes": [ + 5, + 1, + 1 + ], + "soma_diameter": 16, + "ball_xy_size": 6, + "ball_z_size": 15, + "ball_overlap_fraction": 0.6, + "log_sigma_size": 0.2, + "n_sds_above_mean_thresh": 10, + "soma_spread_factor": 1.4, + "max_cluster_size": 100000, + "cube_width": 50, + "cube_height": 50, + "cube_depth": 20, + "network_depth": "50" +} diff --git a/tests/data/input_data_not_locally_or_GIN.json b/tests/data/input_data_not_locally_or_GIN.json new file mode 100644 index 00000000..ac1ed3de --- /dev/null +++ b/tests/data/input_data_not_locally_or_GIN.json @@ -0,0 +1,37 @@ +{ + "install_path": ".cellfinder_workflows", + "extract_dir_relative": "cellfinder_test_data", + "signal_subdir": "signal", + "background_subdir": "background", + "output_path_basename_relative": "cellfinder_output_", + "detected_cells_filename": "detected_cells.xml", + "voxel_sizes": [ + 5, + 2, + 2 + ], + "start_plane": 0, + "end_plane": -1, + "trained_model": null, + "model_weights": null, + "model": "resnet50_tv", + "batch_size": 32, + "n_free_cpus": 2, + "network_voxel_sizes": [ + 5, + 1, + 1 + ], + "soma_diameter": 16, + "ball_xy_size": 6, + "ball_z_size": 15, + "ball_overlap_fraction": 0.6, + "log_sigma_size": 0.2, + "n_sds_above_mean_thresh": 10, + "soma_spread_factor": 1.4, + "max_cluster_size": 100000, + "cube_width": 50, + "cube_height": 50, + "cube_depth": 20, + "network_depth": "50" +} diff --git a/tests/test_integration/test_cellfinder_workflow.py b/tests/test_integration/test_cellfinder_workflow.py index 930dcffe..c0fe19b8 100644 --- a/tests/test_integration/test_cellfinder_workflow.py +++ b/tests/test_integration/test_cellfinder_workflow.py @@ -34,7 +34,7 @@ def test_run_with_default_config(tmp_path, default_json_config_path): / "workflows" / "cellfinder.py", ], - cwd=tmp_path, + cwd=tmp_path, # ------------------- stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, diff --git a/tests/test_unit/test_cellfinder.py b/tests/test_unit/test_cellfinder.py index 6e69318b..7da49aa7 100644 --- a/tests/test_unit/test_cellfinder.py +++ b/tests/test_unit/test_cellfinder.py @@ -1 +1,75 @@ -# cellfinder-specific unit tests +import json +import logging + +from workflows.cellfinder import read_cellfinder_config, retrieve_input_data +from workflows.utils import DEFAULT_JSON_CONFIG_PATH_CELLFINDER + +# @pytest.fixture() --- for where configs are +# def + + +def test_read_cellfinder_config( + input_config_path=DEFAULT_JSON_CONFIG_PATH_CELLFINDER, +): + # read json as Cellfinder config + config = read_cellfinder_config(input_config_path) + + # read json as dict + with open(input_config_path) as cfg: + config_dict = json.load(cfg) + + # check keys of dict are a subset of Cellfinder config attributes + assert all( + [ky in config.__dataclass_fields__.keys() for ky in config_dict.keys()] + ) + + +# define different configs +# @pytest.mark.parametrize( +# "input_config_path, message", +# [ +# (DEFAULT_JSON_CONFIG_PATH_CELLFINDER, +# "Fetching input data from the local directories"), +# (, "The directory does not exist"), +# (, "The directory does not exist"), +# (,"Input data not found locally, +# and URL/hash to GIN repository not provided"), +# (,"Fetching input data from the provided GIN repository") +# ] +# ) +def test_retrieve_input_data(caplog, input_config_path, message): + # set logger to capture + caplog.set_level( + logging.DEBUG, logger="root" + ) # --- why root? :( "workflows.utils") + + # read json as Cellfinder config + config = read_cellfinder_config(input_config_path) + + # retrieve data + retrieve_input_data(config) + + assert message in caplog.messages + + # if ( + # Path(config.signal_dir_path).exists() + # and Path(config.background_dir_path).exists() + # ): + + # # with caplog.at_level( + # # logging.DEBUG, + # # logger="root" # why root? + # # ): + # updated_config = retrieve_input_data(config) + + # assert message in caplog.messages + + # # If exactly one of the input data directories is missing, print error + # elif ( + # Path(config.signal_dir_path).resolve().exists() + # or Path(config.background_dir_path).resolve().exists() + # ): + + +# def test_setup_workflow(): +# pass diff --git a/workflows/cellfinder.py b/workflows/cellfinder.py index 040d900d..16851734 100644 --- a/workflows/cellfinder.py +++ b/workflows/cellfinder.py @@ -98,6 +98,7 @@ def read_cellfinder_config(input_config_path): """Instantiate a CellfinderConfig from the input json file (assumes config is json serializable) + Parameters ---------- input_config_path : _type_ @@ -142,7 +143,7 @@ def retrieve_input_data(config: CellfinderConfig) -> CellfinderConfig: for running cellfinder. """ # Fetch logger - logger = logging.getLogger("root") + logger = logging.getLogger("workflow.utils") # Check if input data (signal and background) exist locally. # If both directories exist, get list of signal and background files @@ -250,7 +251,7 @@ def setup_workflow(input_config_path: Path) -> CellfinderConfig: """ # Fetch logger - logger = logging.getLogger("root") + logger = logging.getLogger("workflow.utils") # Check config file exists assert input_config_path.exists()