diff --git a/news/wavelength-config.rst b/news/wavelength-config.rst new file mode 100644 index 0000000..ba90ac7 --- /dev/null +++ b/news/wavelength-config.rst @@ -0,0 +1,23 @@ +**Added:** + +* Functionality to allow users to specify wavelength or anode type in a diffpy config file. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/labpdfproc/tools.py b/src/diffpy/labpdfproc/tools.py index 3850673..75b34ff 100644 --- a/src/diffpy/labpdfproc/tools.py +++ b/src/diffpy/labpdfproc/tools.py @@ -7,6 +7,7 @@ XQUANTITIES, ) from diffpy.utils.tools import ( + _load_config, check_and_build_global_config, compute_mud, get_package_info, @@ -159,6 +160,33 @@ def set_input_lists(args): return args +def _load_wavelength_from_config_file(args): + """Load wavelength and anode type from config files. + It takes cli inputs first, and local config, and then global config. + + Parameters + ---------- + args : argparse.Namespace + The arguments from the parser. + + Returns + ------- + args : argparse.Namespace + The updated arguments with the updated wavelength and anode type. + """ + if args.wavelength or args.anode_type: + return args + global_config = _load_config(Path().home() / "diffpyconfig.json") + local_config = _load_config(Path().cwd() / "diffpyconfig.json") + if local_config: + args.wavelength = local_config.get("wavelength") + args.anode_type = local_config.get("anode_type") + elif global_config: + args.wavelength = global_config.get("wavelength") + args.anode_type = global_config.get("anode_type") + return args + + def set_wavelength(args): """Set the wavelength based on the given anode_type or wavelength. @@ -185,7 +213,7 @@ def set_wavelength(args): args : argparse.Namespace The updated arguments with the wavelength. """ - # first load values from config file + args = _load_wavelength_from_config_file(args) if args.wavelength is None and args.anode_type is None: if args.xtype not in ANGLEQUANTITIES: raise ValueError( diff --git a/tests/conftest.py b/tests/conftest.py index 2dcb4a5..63d4646 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -60,6 +60,7 @@ def user_filesystem(tmp_path): f.write(f"{str(input_dir.resolve() / 'good_data.txt')}\n") home_config_data = { + "wavelength": 0.3, "owner_name": "home_username", "owner_email": "home@email.com", "owner_orcid": "home_orcid", diff --git a/tests/test_tools.py b/tests/test_tools.py index e6f2269..ac5cfa5 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -1,3 +1,4 @@ +import json import os import re from pathlib import Path @@ -6,6 +7,7 @@ from diffpy.labpdfproc.labpdfprocapp import get_args from diffpy.labpdfproc.tools import ( + _load_wavelength_from_config_file, known_sources, load_metadata, load_package_info, @@ -195,6 +197,121 @@ def test_set_output_directory_bad(user_filesystem): assert not Path(actual_args.output_directory).is_dir() +@pytest.mark.parametrize( + "inputs, expected", + [ + # Test when only a home config file exists (no local config file), + # expect to return args if wavelength or anode type is specified, + # otherwise update args with values from the home config file. + # C1: no args, expect to update arg values from home config + ([""], {"wavelength": 0.3, "anode_type": None}), + # C2: wavelength provided, expect to return args unchanged + (["--wavelength", "0.25"], {"wavelength": 0.25, "anode_type": None}), + # C3: anode type provided, expect to return args unchanged + (["--anode-type", "Mo"], {"wavelength": None, "anode_type": "Mo"}), + # C4: both wavelength and anode type provided, + # expect to return args unchanged + ( + ["--wavelength", "0.7", "--anode-type", "Mo"], + {"wavelength": 0.7, "anode_type": "Mo"}, + ), + ], +) +def test_load_wavelength_from_config_file_with_home_conf_file( + mocker, user_filesystem, inputs, expected +): + cwd = Path(user_filesystem) + home_dir = cwd / "home_dir" + mocker.patch("pathlib.Path.home", lambda _: home_dir) + os.chdir(cwd) + + cli_inputs = ["2.5", "data.xy"] + inputs + actual_args = get_args(cli_inputs) + actual_args = _load_wavelength_from_config_file(actual_args) + assert actual_args.wavelength == expected["wavelength"] + assert actual_args.anode_type == expected["anode_type"] + + +@pytest.mark.parametrize( + "inputs, expected", + [ + # Test when a local config file exists, + # expect to return args if wavelength or anode type is specified, + # otherwise update args with values from the home config file. + # Results should be the same whether if the home config exists. + # C1: no args, expect to update arg values from local config + ([""], {"wavelength": 0.6, "anode_type": None}), + # C2: wavelength provided, expect to return args unchanged + (["--wavelength", "0.25"], {"wavelength": 0.25, "anode_type": None}), + # C3: anode type provided, expect to return args unchanged + (["--anode-type", "Mo"], {"wavelength": None, "anode_type": "Mo"}), + # C4: both wavelength and anode type provided, + # expect to return args unchanged + ( + ["--wavelength", "0.7", "--anode-type", "Mo"], + {"wavelength": 0.7, "anode_type": "Mo"}, + ), + ], +) +def test_load_wavelength_from_config_file_with_local_conf_file( + mocker, user_filesystem, inputs, expected +): + cwd = Path(user_filesystem) + home_dir = cwd / "home_dir" + mocker.patch("pathlib.Path.home", lambda _: home_dir) + os.chdir(cwd) + local_config_data = {"wavelength": 0.6} + with open(cwd / "diffpyconfig.json", "w") as f: + json.dump(local_config_data, f) + + cli_inputs = ["2.5", "data.xy"] + inputs + actual_args = get_args(cli_inputs) + actual_args = _load_wavelength_from_config_file(actual_args) + assert actual_args.wavelength == expected["wavelength"] + assert actual_args.anode_type == expected["anode_type"] + + # remove home config file, expect the same results + confile = home_dir / "diffpyconfig.json" + os.remove(confile) + assert actual_args.wavelength == expected["wavelength"] + assert actual_args.anode_type == expected["anode_type"] + + +@pytest.mark.parametrize( + "inputs, expected", + [ + # Test when no config files exist, + # expect to return args without modification. + # C1: no args + ([""], {"wavelength": None, "anode_type": None}), + # C1: wavelength provided + (["--wavelength", "0.25"], {"wavelength": 0.25, "anode_type": None}), + # C2: anode type provided + (["--anode-type", "Mo"], {"wavelength": None, "anode_type": "Mo"}), + # C4: both wavelength and anode type provided + ( + ["--wavelength", "0.7", "--anode-type", "Mo"], + {"wavelength": 0.7, "anode_type": "Mo"}, + ), + ], +) +def test_load_wavelength_from_config_file_without_conf_files( + mocker, user_filesystem, inputs, expected +): + cwd = Path(user_filesystem) + home_dir = cwd / "home_dir" + mocker.patch("pathlib.Path.home", lambda _: home_dir) + os.chdir(cwd) + confile = home_dir / "diffpyconfig.json" + os.remove(confile) + + cli_inputs = ["2.5", "data.xy"] + inputs + actual_args = get_args(cli_inputs) + actual_args = _load_wavelength_from_config_file(actual_args) + assert actual_args.wavelength == expected["wavelength"] + assert actual_args.anode_type == expected["anode_type"] + + @pytest.mark.parametrize( "inputs, expected", [