From 4d64525e8550ee745f7f84e54df079dd9c719aae Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Fri, 4 Jul 2025 15:14:38 +0800 Subject: [PATCH 1/2] feat: add applymud subcommand --- news/applymud.rst | 23 ++++++++ src/diffpy/labpdfproc/labpdfprocapp.py | 81 +++++++++++++++++--------- src/diffpy/labpdfproc/tools.py | 1 + tests/test_tools.py | 35 ++++++----- 4 files changed, 96 insertions(+), 44 deletions(-) create mode 100644 news/applymud.rst diff --git a/news/applymud.rst b/news/applymud.rst new file mode 100644 index 0000000..0d81363 --- /dev/null +++ b/news/applymud.rst @@ -0,0 +1,23 @@ +**Added:** + +* new subcommand ``applymud`` to run the original absorption correction process through CLI. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/labpdfproc/labpdfprocapp.py b/src/diffpy/labpdfproc/labpdfprocapp.py index 9acfaaa..d73caab 100644 --- a/src/diffpy/labpdfproc/labpdfprocapp.py +++ b/src/diffpy/labpdfproc/labpdfprocapp.py @@ -73,6 +73,7 @@ def _define_arguments(): "If the specified directory doesn't exist it will be created." ), "default": None, + "widget": "DirChooser", }, { "name": ["-x", "--xtype"], @@ -158,7 +159,7 @@ def _define_arguments(): return args -def _add_mud_selection_group(p, is_gui=False): +def _add_mud_selection_group(p, use_gui=False): """Current Options: 1. Manually enter muD (`--mud`). 2. Estimate from a z-scan file (`-z` or `--z-scan-file`). @@ -173,7 +174,7 @@ def _add_mud_selection_group(p, is_gui=False): "--mud", type=float, help="Enter the mu*D value manually.", - **({"widget": "DecimalField"} if is_gui else {}), + **({"widget": "DecimalField"} if use_gui else {}), ) g.add_argument( "-z", @@ -183,7 +184,7 @@ def _add_mud_selection_group(p, is_gui=False): "Specify the path to the file " "used to compute the mu*D value." ), - **({"widget": "FileChooser"} if is_gui else {}), + **({"widget": "FileChooser"} if use_gui else {}), ) g.add_argument( "-d", @@ -207,39 +208,50 @@ def _add_mud_selection_group(p, is_gui=False): return p -def get_args(override_cli_inputs=None): - p = ArgumentParser() - p = _add_mud_selection_group(p, is_gui=False) +def _register_applymud_subparser(subp, use_gui=False): + applymudp = subp.add_parser( + "applymud", help="Apply absorption correction." + ) + _add_mud_selection_group(applymudp, use_gui=use_gui) for arg in _define_arguments(): - kwargs = { - key: value - for key, value in arg.items() - if key != "name" and key != "widget" - } - p.add_argument(*arg["name"], **kwargs) - args = p.parse_args(override_cli_inputs) - return args + names = arg["name"] + options = {k: v for k, v in arg.items() if k != "name"} + if not use_gui and "widget" in options: + options.pop("widget") + applymudp.add_argument(*names, **options) -@Gooey(required_cols=1, optional_cols=2, program_name="labpdfproc GUI") -def gooey_parser(): - p = GooeyParser() - p = _add_mud_selection_group(p, is_gui=True) - for arg in _define_arguments(): - kwargs = {key: value for key, value in arg.items() if key != "name"} - p.add_argument(*arg["name"], **kwargs) +def create_parser(use_gui=False): + p = GooeyParser() if use_gui else ArgumentParser() + subp = p.add_subparsers(title="subcommand", dest="subcommand") + _register_applymud_subparser(subp, use_gui) + return p + + +@Gooey( + required_cols=1, + optional_cols=1, + show_sidebar=True, + program_name="labpdfproc GUI", +) +def _get_args_gui(): + p = create_parser(use_gui=True) args = p.parse_args() return args -def main(): - args = ( - gooey_parser() - if len(sys.argv) == 1 or "--gui" in sys.argv - else get_args() - ) - args = preprocessing_args(args) +def _get_args_cli(override_cli_inputs=None): + p = create_parser(use_gui=False) + args = p.parse_args(override_cli_inputs) + return args + +def get_args(override_cli_inputs=None, use_gui=False): + return _get_args_gui() if use_gui else _get_args_cli(override_cli_inputs) + + +def applymud(args): + args = preprocessing_args(args) for filepath in args.input_paths: outfilestem = filepath.stem + "_corrected" corrfilestem = filepath.stem + "_cve" @@ -286,5 +298,18 @@ def main(): absorption_correction.dump(f"{corrfile}", xtype=args.xtype) +def run_subcommand(args): + if args.subcommand == "applymud": + return applymud(args) + else: + raise ValueError(f"Unknown subcommand: {args.subcommand}") + + +def main(): + use_gui = len(sys.argv) == 1 or "--gui" in sys.argv + args = get_args(use_gui=use_gui) + return run_subcommand(args) + + if __name__ == "__main__": main() diff --git a/src/diffpy/labpdfproc/tools.py b/src/diffpy/labpdfproc/tools.py index 5bbce31..ee5c6e8 100644 --- a/src/diffpy/labpdfproc/tools.py +++ b/src/diffpy/labpdfproc/tools.py @@ -45,6 +45,7 @@ "wavelength", "theoretical_from_density", "theoretical_from_packing", + "subcommand", ] diff --git a/tests/test_tools.py b/tests/test_tools.py index a007e8c..e2028e9 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -115,7 +115,7 @@ def test_set_input_lists(inputs, expected, user_filesystem): base_dir.resolve() / expected_path for expected_path in expected ] - cli_inputs = inputs + ["--mud", "2.5"] + cli_inputs = ["applymud"] + inputs + ["--mud", "2.5"] actual_args = get_args(cli_inputs) actual_args = set_input_lists(actual_args) assert sorted(actual_args.input_paths) == sorted(expected_paths) @@ -161,7 +161,7 @@ def test_set_input_lists(inputs, expected, user_filesystem): def test_set_input_files_bad(inputs, expected_error_msg, user_filesystem): base_dir = Path(user_filesystem) os.chdir(base_dir) - cli_inputs = inputs + ["--mud", "2.5"] + cli_inputs = ["applymud"] + inputs + ["--mud", "2.5"] actual_args = get_args(cli_inputs) with pytest.raises(FileNotFoundError, match=re.escape(expected_error_msg)): actual_args = set_input_lists(actual_args) @@ -179,7 +179,7 @@ def test_set_input_files_bad(inputs, expected_error_msg, user_filesystem): def test_set_output_directory(inputs, expected, user_filesystem): os.chdir(user_filesystem) expected_output_directory = Path(user_filesystem) / expected[0] - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = set_output_directory(actual_args) assert actual_args.output_directory == expected_output_directory @@ -190,6 +190,7 @@ def test_set_output_directory(inputs, expected, user_filesystem): def test_set_output_directory_bad(user_filesystem): os.chdir(user_filesystem) cli_inputs = [ + "applymud", "data.xy", "--mud", "2.5", @@ -235,7 +236,7 @@ def test_load_wavelength_from_config_file_with_home_conf_file( mocker.patch("pathlib.Path.home", lambda _: home_dir) os.chdir(cwd) - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = load_wavelength_from_config_file(actual_args) assert actual_args.wavelength == expected["wavelength"] @@ -278,7 +279,7 @@ def test_load_wavelength_from_config_file_with_local_conf_file( with open(cwd / "diffpyconfig.json", "w") as f: json.dump(local_config_data, f) - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = load_wavelength_from_config_file(actual_args) assert actual_args.wavelength == expected["wavelength"] @@ -321,7 +322,7 @@ def test_load_wavelength_from_config_file_without_conf_files( confile = home_dir / "diffpyconfig.json" os.remove(confile) - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = load_wavelength_from_config_file(actual_args) assert actual_args.wavelength == expected["wavelength"] @@ -380,7 +381,7 @@ def test_load_wavelength_from_config_file_without_conf_files( ], ) def test_set_wavelength(inputs, expected): - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = set_wavelength(actual_args) assert actual_args.wavelength == expected["wavelength"] @@ -419,7 +420,7 @@ def test_set_wavelength(inputs, expected): ], ) def test_set_wavelength_bad(inputs, expected_error_msg): - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) with pytest.raises(ValueError, match=re.escape(expected_error_msg)): actual_args = set_wavelength(actual_args) @@ -435,14 +436,14 @@ def test_set_wavelength_bad(inputs, expected_error_msg): ], ) def test_set_xtype(inputs, expected_xtype): - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = set_xtype(actual_args) assert actual_args.xtype == expected_xtype def test_set_xtype_bad(): - cli_inputs = ["data.xy", "--mud", "2.5", "--xtype", "invalid"] + cli_inputs = ["applymud", "data.xy", "--mud", "2.5", "--xtype", "invalid"] actual_args = get_args(cli_inputs) with pytest.raises( ValueError, @@ -474,7 +475,7 @@ def test_set_xtype_bad(): def test_set_mud(user_filesystem, inputs, expected_mud): cwd = Path(user_filesystem) os.chdir(cwd) - cli_inputs = ["data.xy"] + inputs + cli_inputs = ["applymud", "data.xy"] + inputs actual_args = get_args(cli_inputs) actual_args = set_mud(actual_args) assert actual_args.mud == pytest.approx(expected_mud, rel=1e-4, abs=0.1) @@ -550,7 +551,7 @@ def test_set_mud_bad(user_filesystem, inputs, expected): expected_error, expected_error_msg = expected cwd = Path(user_filesystem) os.chdir(cwd) - cli_inputs = ["data.xy"] + inputs + cli_inputs = ["applymud", "data.xy"] + inputs actual_args = get_args(cli_inputs) with pytest.raises(expected_error, match=re.escape(expected_error_msg)): actual_args = set_mud(actual_args) @@ -577,12 +578,12 @@ def test_set_mud_bad(user_filesystem, inputs, expected): ], ) def test_load_user_metadata(inputs, expected): - expected_args = get_args(["data.xy", "--mud", "2.5"]) + expected_args = get_args(["applymud", "data.xy", "--mud", "2.5"]) for expected_pair in expected: setattr(expected_args, expected_pair[0], expected_pair[1]) delattr(expected_args, "user_metadata") - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) actual_args = load_user_metadata(actual_args) assert actual_args == expected_args @@ -618,7 +619,7 @@ def test_load_user_metadata(inputs, expected): ], ) def test_load_user_metadata_bad(inputs, expected_error_msg): - cli_inputs = ["data.xy", "--mud", "2.5"] + inputs + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] + inputs actual_args = get_args(cli_inputs) with pytest.raises(ValueError, match=re.escape(expected_error_msg)): actual_args = load_user_metadata(actual_args) @@ -681,6 +682,7 @@ def test_load_user_info(monkeypatch, inputs, expected, user_filesystem): os.chdir(cwd) cli_inputs = [ + "applymud", "data.xy", "--mud", "2.5", @@ -705,7 +707,7 @@ def test_load_package_info(mocker): "3.3.0" if package_name == "diffpy.utils" else "1.2.3" ), ) - cli_inputs = ["data.xy", "--mud", "2.5"] + cli_inputs = ["applymud", "data.xy", "--mud", "2.5"] actual_args = get_args(cli_inputs) actual_args = load_package_info(actual_args) assert actual_args.package_info == { @@ -731,6 +733,7 @@ def test_load_metadata(mocker, user_filesystem): ), ) cli_inputs = [ + "applymud", ".", "--mud", "2.5", From 928cdc622a596654bea0f49f990705d64dfcb0a6 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Fri, 4 Jul 2025 15:44:26 +0800 Subject: [PATCH 2/2] fix: update workflows for renamed test file --- .github/workflows/matrix-and-codecov-on-merge-to-main.yml | 2 +- .github/workflows/tests-on-pr.yml | 2 +- news/applymud.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml index c55e217..3114aa2 100644 --- a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml +++ b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml @@ -44,7 +44,7 @@ jobs: - name: Install diffpy.labpdfproc and requirements run: | - conda install --file requirements/test.txt + conda install --file requirements/tests.txt conda install --file requirements/conda.txt pip install gooey python -m pip install . --no-deps diff --git a/.github/workflows/tests-on-pr.yml b/.github/workflows/tests-on-pr.yml index 80a58ec..db5cacf 100644 --- a/.github/workflows/tests-on-pr.yml +++ b/.github/workflows/tests-on-pr.yml @@ -34,7 +34,7 @@ jobs: - name: Install diffpy.labpdfproc and requirements run: | - conda install --file requirements/test.txt + conda install --file requirements/tests.txt conda install --file requirements/conda.txt pip install gooey python -m pip install . --no-deps diff --git a/news/applymud.rst b/news/applymud.rst index 0d81363..e618a21 100644 --- a/news/applymud.rst +++ b/news/applymud.rst @@ -4,7 +4,7 @@ **Changed:** -* +* GitHub workflows for renamed test file. **Deprecated:**