diff --git a/tests/test_interpret.py b/tests/test_interpret.py index 8030e4c98..d84147e97 100644 --- a/tests/test_interpret.py +++ b/tests/test_interpret.py @@ -61,6 +61,9 @@ def test_interpret(cmdopt, tmp_path, test_name): else: raise NotImplementedError(f"Test {test_name} is not implemented.") + if cmdopt["no-gpu"]: + cnn_input.append("--no-gpu") + run_interpret(cnn_input, tmp_out_dir, ref_dir) diff --git a/tests/test_random_search.py b/tests/test_random_search.py index e1c530513..5b68787e8 100644 --- a/tests/test_random_search.py +++ b/tests/test_random_search.py @@ -1,6 +1,5 @@ # coding: utf8 -import json import os import shutil from os.path import join @@ -8,7 +7,7 @@ import pytest -from tests.testing_tools import compare_folders +from .testing_tools import change_gpu_in_toml, compare_folders # random searxh for ROI with CNN @@ -34,10 +33,12 @@ def test_random_search(cmdopt, tmp_path, test_name): else: raise NotImplementedError(f"Test {test_name} is not implemented.") - run_test_random_search(toml_path, generate_input, tmp_out_dir, ref_dir) + run_test_random_search( + toml_path, generate_input, tmp_out_dir, ref_dir, cmdopt["no-gpu"] + ) -def run_test_random_search(toml_path, generate_input, tmp_out_dir, ref_dir): +def run_test_random_search(toml_path, generate_input, tmp_out_dir, ref_dir, no_gpu): if os.path.exists(tmp_out_dir): shutil.rmtree(tmp_out_dir) @@ -45,6 +46,9 @@ def run_test_random_search(toml_path, generate_input, tmp_out_dir, ref_dir): os.makedirs(tmp_out_dir, exist_ok=True) shutil.copy(toml_path, tmp_out_dir) + if no_gpu: + change_gpu_in_toml(tmp_out_dir / "random_search.toml") + flag_error_generate = not os.system("clinicadl " + " ".join(generate_input)) performances_flag = os.path.exists( tmp_out_dir / "job-1" / "split-0" / "best-loss" / "train" diff --git a/tests/test_resume.py b/tests/test_resume.py index 3cf883c32..cdf6031ee 100644 --- a/tests/test_resume.py +++ b/tests/test_resume.py @@ -1,15 +1,14 @@ # coding: utf8 import json -import os import shutil from os import system -from os.path import join from pathlib import Path import pytest from clinicadl import MapsManager -from tests.testing_tools import compare_folders + +from .testing_tools import modify_maps @pytest.fixture( @@ -33,6 +32,18 @@ def test_resume(cmdopt, tmp_path, test_name): shutil.copytree(input_dir / test_name, tmp_out_dir / test_name) maps_stopped = tmp_out_dir / test_name + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: # modify the input MAPS + with open(maps_stopped / "maps.json", "r") as f: + config = json.load(f) + config = modify_maps( + maps=config, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], + ) + with open(maps_stopped / "maps.json", "w") as f: + json.dump(config, f) + flag_error = not system(f"clinicadl -vv train resume {maps_stopped}") assert flag_error @@ -48,4 +59,13 @@ def test_resume(cmdopt, tmp_path, test_name): json_data_out = json.load(out) with open(ref_dir / "maps_image_cnn" / "maps.json", "r") as ref: json_data_ref = json.load(ref) + + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: + json_data_ref = modify_maps( + maps=json_data_ref, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], + ) + assert json_data_ref == json_data_out diff --git a/tests/test_train_ae.py b/tests/test_train_ae.py index 311e145d0..b20749258 100644 --- a/tests/test_train_ae.py +++ b/tests/test_train_ae.py @@ -3,12 +3,11 @@ import json import os import shutil -from os.path import join from pathlib import Path import pytest -from tests.testing_tools import clean_folder, compare_folders +from .testing_tools import clean_folder, compare_folders, modify_maps @pytest.fixture( @@ -27,8 +26,8 @@ def test_train_ae(cmdopt, tmp_path, test_name): base_dir = Path(cmdopt["input"]) input_dir = base_dir / "train" / "in" ref_dir = base_dir / "train" / "ref" - tmp_out_dir = base_dir / "train" / "out" - # tmp_out_dir.mkdir(parents=True) + tmp_out_dir = tmp_path / "train" / "out" + tmp_out_dir.mkdir(parents=True) clean_folder(tmp_out_dir, recreate=True) @@ -102,18 +101,12 @@ def test_train_ae(cmdopt, tmp_path, test_name): with open(ref_dir / ("maps_" + test_name) / "maps.json", "r") as ref: json_data_ref = json.load(ref) - if test_name == "patch_multi_ae": - json_data_out["multi_network"] = True - if cmdopt["no-gpu"]: - json_data_ref["gpu"] = False - if cmdopt["adapt-base-dir"]: - base_dir = base_dir.resolve() - ref_base_dir = Path(json_data_ref["caps_directory"]).parents[2] - json_data_ref["caps_directory"] = str( - base_dir / Path(json_data_ref["caps_directory"]).relative_to(ref_base_dir) - ) - json_data_ref["tsv_path"] = str( - base_dir / Path(json_data_ref["tsv_path"]).relative_to(ref_base_dir) + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: + json_data_ref = modify_maps( + maps=json_data_ref, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], ) assert json_data_out == json_data_ref # ["mode"] == mode diff --git a/tests/test_train_cnn.py b/tests/test_train_cnn.py index da5b3a3f1..761fedbee 100644 --- a/tests/test_train_cnn.py +++ b/tests/test_train_cnn.py @@ -3,12 +3,11 @@ import json import os import shutil -from os.path import join from pathlib import Path import pytest -from tests.testing_tools import compare_folders +from .testing_tools import compare_folders, modify_maps @pytest.fixture( @@ -101,6 +100,9 @@ def test_train_cnn(cmdopt, tmp_path, test_name): else: raise NotImplementedError(f"Test {test_name} is not implemented.") + if cmdopt["no-gpu"]: + test_input.append("--no-gpu") + if tmp_out_dir.is_dir(): shutil.rmtree(tmp_out_dir) @@ -117,6 +119,13 @@ def test_train_cnn(cmdopt, tmp_path, test_name): with open(ref_dir / ("maps_" + test_name) / "maps.json", "r") as ref: json_data_ref = json.load(ref) + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: + json_data_ref = modify_maps( + maps=json_data_ref, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], + ) assert json_data_out == json_data_ref # ["mode"] == mode assert compare_folders( diff --git a/tests/test_train_from_json.py b/tests/test_train_from_json.py index f48791d31..363af9aff 100644 --- a/tests/test_train_from_json.py +++ b/tests/test_train_from_json.py @@ -1,17 +1,14 @@ -import os -import pathlib +import json import shutil -from os import path, system -from os.path import join +from os import system from pathlib import Path -from .testing_tools import compare_folders_with_hashes, create_hashes_dict, models_equal +from .testing_tools import compare_folders_with_hashes, create_hashes_dict, modify_maps def test_json_compatibility(cmdopt, tmp_path): base_dir = Path(cmdopt["input"]) input_dir = base_dir / "train_from_json" / "in" - ref_dir = base_dir / "train_from_json" / "ref" tmp_out_dir = tmp_path / "train_from_json" / "out" tmp_out_dir.mkdir(parents=True) @@ -22,6 +19,19 @@ def test_json_compatibility(cmdopt, tmp_path): if reproduced_maps_dir.exists(): shutil.rmtree(reproduced_maps_dir) + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: # virtually modify the input MAPS + with open(config_json, "r") as f: + config = json.load(f) + config_json = tmp_out_dir / "modified_maps.json" + config = modify_maps( + maps=config, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], + ) + with open(config_json, "w+") as f: + json.dump(config, f) + flag_error = not system( f"clinicadl train from_json {str(config_json)} {str(reproduced_maps_dir)} -s {split}" ) @@ -31,7 +41,6 @@ def test_json_compatibility(cmdopt, tmp_path): def test_determinism(cmdopt, tmp_path): base_dir = Path(cmdopt["input"]) input_dir = base_dir / "train_from_json" / "in" - ref_dir = base_dir / "train_from_json" / "ref" tmp_out_dir = tmp_path / "train_from_json" / "out" tmp_out_dir.mkdir(parents=True) @@ -50,8 +59,11 @@ def test_determinism(cmdopt, tmp_path): str(maps_dir), "-c", str(input_dir / "reproducibility_config.toml"), - "--no-gpu", ] + + if cmdopt["no-gpu"]: + test_input.append("--no-gpu") + # Run first experiment flag_error = not system("clinicadl " + " ".join(test_input)) assert flag_error diff --git a/tests/test_transfer_learning.py b/tests/test_transfer_learning.py index 95713d7ad..b9c3f999b 100644 --- a/tests/test_transfer_learning.py +++ b/tests/test_transfer_learning.py @@ -1,12 +1,11 @@ import json import os import shutil -from os.path import join from pathlib import Path import pytest -from tests.testing_tools import compare_folders +from .testing_tools import compare_folders, modify_maps # Everything is tested on roi except for cnn --> multicnn (patch) as multicnn is not implemented for roi. @@ -41,7 +40,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): str(caps_roi_path), extract_roi_str, str(labels_path), - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_ae"), "-c", str(config_path), ] @@ -55,7 +54,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): "-c", str(config_path), "--transfer_path", - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_ae"), ] name = "aeTOae" elif test_name == "transfer_ae_cnn": @@ -65,7 +64,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): str(caps_roi_path), extract_roi_str, str(labels_path), - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_ae"), "-c", str(config_path), ] @@ -79,7 +78,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): "-c", str(config_path), "--transfer_path", - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_ae"), ] name = "aeTOcnn" elif test_name == "transfer_cnn_cnn": @@ -89,7 +88,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): str(caps_roi_path), extract_roi_str, str(labels_path), - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_cnn"), "-c", str(config_path), ] @@ -103,7 +102,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): "-c", str(config_path), "--transfer_path", - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_cnn"), ] name = "cnnTOcnn" elif test_name == "transfer_cnn_multicnn": @@ -113,7 +112,7 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): str(caps_roi_path), extract_roi_str, str(labels_path), - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_cnn"), "-c", str(config_path), ] @@ -127,12 +126,17 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): "-c", str(config_path), "--transfer_path", - str(tmp_out_dir), + str(tmp_out_dir / "maps_roi_cnn"), + "--multi_network", ] - name = "cnnTOcnn" + name = "cnnTOmulticnn" else: raise NotImplementedError(f"Test {test_name} is not implemented.") + if cmdopt["no-gpu"]: + source_task.append("--no-gpu") + target_task.append("--no-gpu") + if tmp_out_dir.exists(): shutil.rmtree(tmp_out_dir) if tmp_target_dir.exists(): @@ -148,9 +152,21 @@ def test_transfer_learning(cmdopt, tmp_path, test_name): with open(ref_dir / ("maps_roi_" + name) / "maps.json", "r") as ref: json_data_ref = json.load(ref) - json_data_ref["transfer_path"] = json_data_out["transfer_path"] - json_data_ref["gpu"] = json_data_out["gpu"] + ref_source_dir = Path(json_data_ref["transfer_path"]).parent + json_data_ref["transfer_path"] = str( + tmp_out_dir / Path(json_data_ref["transfer_path"]).relative_to(ref_source_dir) + ) + if cmdopt["no-gpu"] or cmdopt["adapt-base-dir"]: + json_data_ref = modify_maps( + maps=json_data_ref, + base_dir=base_dir, + no_gpu=cmdopt["no-gpu"], + adapt_base_dir=cmdopt["adapt-base-dir"], + ) + # TODO: remove and update data json_data_ref["caps_directory"] = json_data_out["caps_directory"] + json_data_ref["gpu"] = json_data_out["gpu"] + ### assert json_data_out == json_data_ref # ["mode"] == mode assert compare_folders( diff --git a/tests/testing_tools.py b/tests/testing_tools.py index d4cb29c8a..ff7eb97b1 100644 --- a/tests/testing_tools.py +++ b/tests/testing_tools.py @@ -1,7 +1,7 @@ import pathlib from os import PathLike from pathlib import Path -from typing import Dict, List +from typing import Any, Dict, List def ignore_pattern(file_path: pathlib.Path, ignore_pattern_list: List[str]) -> bool: @@ -166,3 +166,63 @@ def clean_folder(path, recreate=True): rmtree(abs_path) if recreate: makedirs(abs_path) + + +def modify_maps( + maps: Dict[str, Any], + base_dir: Path, + no_gpu: bool = False, + adapt_base_dir: bool = False, +) -> Dict[str, Any]: + """ + Modifies a MAPS dictionary if the user passed --no-gpu or --adapt-base-dir flags. + + Parameters + ---------- + maps : Dict[str, Any] + The MAPS dictionary. + base_dir : Path + The base directory, where CI data are stored. + no_gpu : bool (optional, default=False) + Whether the user activated the --no-gpu flag. + adapt_base_dir : bool (optional, default=False) + Whether the user activated the --adapt-base-dir flag. + + Returns + ------- + Dict[str, Any] + The modified MAPS dictionary. + """ + if no_gpu: + maps["gpu"] = False + if adapt_base_dir: + base_dir = base_dir.resolve() + ref_base_dir = Path(maps["caps_directory"]).parents[2] + maps["caps_directory"] = str( + base_dir / Path(maps["caps_directory"]).relative_to(ref_base_dir) + ) + maps["tsv_path"] = str( + base_dir / Path(maps["tsv_path"]).relative_to(ref_base_dir) + ) + return maps + + +def change_gpu_in_toml(toml_path: Path) -> None: + """ + Changes GPU to false in a TOML config file. + + Parameters + ---------- + toml_path : Path + The TOML file. + """ + import toml + + config = toml.load(toml_path) + try: + config["Computational"]["gpu"] = False + except KeyError: + config["Computational"] = {"gpu": False} + f = open(toml_path, "w") + toml.dump(config, f) + f.close()