From 20161894ea4dbdbcdd87c669112e47dac6d0ad31 Mon Sep 17 00:00:00 2001 From: Yuchen Xiao Date: Sun, 29 Mar 2026 20:36:15 -0400 Subject: [PATCH 1/3] feat: add `pdfbl-cli` CLI to run DiffpyInterpreter --- pyproject.toml | 2 +- src/pdfbl/sequential/diffpy_interpreter.py | 33 +++++++++++++++++--- src/pdfbl/sequential/pdfbl_sequential_app.py | 9 +++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c829688..6cf8842 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [project.scripts] -pdfbl-sequential = "pdfbl.sequential.pdfbl_sequential_app:main" +pdfbl-cli = "pdfbl.sequential.pdfbl_sequential_app:main" [tool.setuptools.dynamic] dependencies = {file = ["requirements/pip.txt"]} diff --git a/src/pdfbl/sequential/diffpy_interpreter.py b/src/pdfbl/sequential/diffpy_interpreter.py index ddf25aa..b5f17ef 100644 --- a/src/pdfbl/sequential/diffpy_interpreter.py +++ b/src/pdfbl/sequential/diffpy_interpreter.py @@ -1,3 +1,4 @@ +import json from pathlib import Path import yaml @@ -13,7 +14,7 @@ ; Command: - LoadCommand | SetCommand | CreateCommand + LoadCommand | SetCommand | CreateCommand | SaveCommand ; LoadCommand: @@ -29,6 +30,10 @@ 'create' 'equation' 'variables' value+=Value[eolterm] ; +SaveCommand: + 'save to' source=STRING +; + VariableBlock: 'variables:' '---' content=/[\s\S]*?(?=---)/ '---' ; @@ -53,6 +58,7 @@ def __init__(self): "LoadCommand": self.load_command_processor, "VariableBlock": self.variable_block_processor, "CreateCommand": self.create_command_processor, + "SaveCommand": self.save_command_processor, } ) self.inputs = {} @@ -136,6 +142,9 @@ def create_command_processor(self, command): v for v in command.value if isinstance(v, str) ] + def save_command_processor(self, command): + self.inputs["result_path"] = command.source + def configure_adapter(self): self.pdfadapter.initialize_profile( self.inputs["profile_path"], **self.inputs["profiles_config"] @@ -170,8 +179,23 @@ def run(self): least_squares( self.pdfadapter.recipe.residual, self.pdfadapter.recipe.values ) + if "result_path" in self.inputs: + with open(self.inputs["result_path"], "w") as f: + json.dump(self.pdfadapter.get_results(), f, indent=4) return self.pdfadapter.get_results() + def run_app(self, args): + dpin_path = Path(args.input_file) + if not dpin_path.exists(): + raise FileNotFoundError( + f"{str(dpin_path)} not Found. Please check if this file " + "exists and provide the correct path to it." + ) + dsl_code = dpin_path.read_text() + self.interpret(dsl_code) + self.configure_adapter() + self.run() + if __name__ == "__main__": interpreter = DiffpyInterpreter() @@ -184,13 +208,14 @@ def run(self): set exp_ni calculation_range as 1.5 50 0.01 create equation variables s0 set equation as "s0*G1" +save to "results.json" variables: --- -- G1_a: 3.52 +- G1.a: 3.52 - s0: 0.4 -- G1_Uiso_0: 0.005 -- G1_delta2: 2 +- G1.Uiso_0: 0.005 +- G1.delta2: 2 - qdamp: 0.04 - qbroad: 0.02 --- diff --git a/src/pdfbl/sequential/pdfbl_sequential_app.py b/src/pdfbl/sequential/pdfbl_sequential_app.py index 677d861..787447b 100644 --- a/src/pdfbl/sequential/pdfbl_sequential_app.py +++ b/src/pdfbl/sequential/pdfbl_sequential_app.py @@ -1,6 +1,7 @@ import argparse from pdfbl.sequential import __version__ +from pdfbl.sequential.diffpy_interpreter import DiffpyInterpreter def main(): @@ -22,4 +23,10 @@ def main(): version=f"pdfbl.sequential {__version__}", help="Show the version of pdfbl.sequential and exit.", ) - parser.parse_args() + subparsers = parser.add_subparsers(dest="subcommand") + run_parser = subparsers.add_parser("run") + run_parser.add_argument("input_file", help="Input .dp-in file.") + run_parser.set_defaults(func=DiffpyInterpreter().run_app) + args = parser.parse_args() + if hasattr(args, "func"): + args.func(args) From 78e7cc66eb1ae66d72001fd7cb042379ca607e67 Mon Sep 17 00:00:00 2001 From: Yuchen Xiao Date: Sun, 29 Mar 2026 21:05:23 -0400 Subject: [PATCH 2/3] chore: fix according to copilot's review --- src/pdfbl/sequential/diffpy_interpreter.py | 4 ++-- src/pdfbl/sequential/pdfbl_sequential_app.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pdfbl/sequential/diffpy_interpreter.py b/src/pdfbl/sequential/diffpy_interpreter.py index b5f17ef..934506d 100644 --- a/src/pdfbl/sequential/diffpy_interpreter.py +++ b/src/pdfbl/sequential/diffpy_interpreter.py @@ -31,7 +31,7 @@ ; SaveCommand: - 'save to' source=STRING + 'save' 'to' source=STRING ; VariableBlock: @@ -188,7 +188,7 @@ def run_app(self, args): dpin_path = Path(args.input_file) if not dpin_path.exists(): raise FileNotFoundError( - f"{str(dpin_path)} not Found. Please check if this file " + f"{str(dpin_path)} not found. Please check if this file " "exists and provide the correct path to it." ) dsl_code = dpin_path.read_text() diff --git a/src/pdfbl/sequential/pdfbl_sequential_app.py b/src/pdfbl/sequential/pdfbl_sequential_app.py index 29da3cf..2c673d4 100644 --- a/src/pdfbl/sequential/pdfbl_sequential_app.py +++ b/src/pdfbl/sequential/pdfbl_sequential_app.py @@ -31,3 +31,6 @@ def main(): args = parser.parse_args() if hasattr(args, "func"): args.func(args) + else: + parser.print_help() + parser.exit() From 78f4b19fdec775f13a8b27ad82f4bdc3ef30e899 Mon Sep 17 00:00:00 2001 From: Yuchen Xiao Date: Sun, 29 Mar 2026 22:03:38 -0400 Subject: [PATCH 3/3] chore: rename the command as `pdfbl` --- pyproject.toml | 2 +- src/pdfbl/sequential/pdfbl_sequential_app.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6cf8842..4e1e5b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ exclude = [] # exclude packages matching these glob patterns (empty by default) namespaces = false # to disable scanning PEP 420 namespaces (true by default) [project.scripts] -pdfbl-cli = "pdfbl.sequential.pdfbl_sequential_app:main" +pdfbl = "pdfbl.sequential.pdfbl_sequential_app:main" [tool.setuptools.dynamic] dependencies = {file = ["requirements/pip.txt"]} diff --git a/src/pdfbl/sequential/pdfbl_sequential_app.py b/src/pdfbl/sequential/pdfbl_sequential_app.py index 2c673d4..963ffbc 100644 --- a/src/pdfbl/sequential/pdfbl_sequential_app.py +++ b/src/pdfbl/sequential/pdfbl_sequential_app.py @@ -9,8 +9,8 @@ def main(): Examples -------- - >>> pdfbl-cli --version - >>> pdfbl-cli run input.dp-in + >>> pdfbl --version + >>> pdfbl run input.dp-in """ parser = argparse.ArgumentParser( description=( @@ -21,8 +21,8 @@ def main(): parser.add_argument( "--version", action="version", - version=f"pdfbl.sequential {__version__}", - help="Show the version of pdfbl.sequential and exit.", + version=f"pdfbl {__version__}", + help="Show the version of pdfbl and exit.", ) subparsers = parser.add_subparsers(dest="subcommand") run_parser = subparsers.add_parser("run")