diff --git a/news/add-cli.rst b/news/add-cli.rst new file mode 100644 index 0000000..08e9cbd --- /dev/null +++ b/news/add-cli.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add CLI interface to run DSL input file + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index c829688..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-sequential = "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/diffpy_interpreter.py b/src/pdfbl/sequential/diffpy_interpreter.py index ddf25aa..934506d 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..963ffbc 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(): @@ -8,7 +9,8 @@ def main(): Examples -------- - >>> pdfbl-cli --version + >>> pdfbl --version + >>> pdfbl run input.dp-in """ parser = argparse.ArgumentParser( description=( @@ -19,7 +21,16 @@ 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.", ) - 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) + else: + parser.print_help() + parser.exit()