From 22eb07888a162ca7a688dedfd6c5daa196975995 Mon Sep 17 00:00:00 2001 From: Yuchen Xiao Date: Mon, 5 Oct 2026 15:42:32 -0400 Subject: [PATCH] feat: evaluate model with placeholder profile --- .../apps/refinebase/refinement_server.py | 43 ++++++++++++++++++- .../apps/refinebase/refinement_session.py | 27 +++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/diffpy/apps/refinebase/refinement_server.py b/src/diffpy/apps/refinebase/refinement_server.py index d70c77a..2971006 100644 --- a/src/diffpy/apps/refinebase/refinement_server.py +++ b/src/diffpy/apps/refinebase/refinement_server.py @@ -300,9 +300,39 @@ async def set_model_equation( async def get_model_evaluation( model_name: Annotated[str, "Name of the parametric model"], data_path: Annotated[str, "Path to the data to retrieve"], + xmin: Annotated[ + float | None, + ( + "Minimum x value for the evaluation " + "if the profile is not set for the model" + ), + ] = None, + xmax: Annotated[ + float | None, + ( + "Maximum x value for the evaluation " + "if the profile is not set for the model" + ), + ] = None, + dx: Annotated[ + float | None, + ( + "Step size for the evaluation " + "if the profile is not set for the model" + ), + ] = None, + xname: Annotated[ + str, + ( + "Name of the x variable for the evaluation " + "if the profile is not set for the model" + ), + ] = "r", ) -> str: """Get the current evaluation of a parametric model.""" - evaluation = session.get_model_evaluation(model_name=model_name).tolist() + evaluation = session.get_model_evaluation( + model_name=model_name, xmin=xmin, xmax=xmax, dx=dx, xname=xname + ).tolist() with open(data_path, "w") as f: json.dump(evaluation, f) return ( @@ -311,6 +341,17 @@ async def get_model_evaluation( ) +@mcp.tool() +@tool_errors +async def set_model_profile( + model_name: Annotated[str, "Name of the parametric model"], + profile_name: Annotated[str, "Name of the profile to set on the model"], +) -> str: + """Set the profile for a parametric model in the refinement session.""" + session.set_model_profile(model_name, profile_name) + return f"Profile {profile_name} set for model {model_name} successfully." + + @mcp.tool() @tool_errors async def get_model_residual( diff --git a/src/diffpy/apps/refinebase/refinement_session.py b/src/diffpy/apps/refinebase/refinement_session.py index 6e820a4..79195e3 100644 --- a/src/diffpy/apps/refinebase/refinement_session.py +++ b/src/diffpy/apps/refinebase/refinement_session.py @@ -247,13 +247,36 @@ def get_model_residual(self, model_name: str): ) return model.residual() - def get_model_evaluation(self, model_name: str): + def get_model_evaluation( + self, model_name: str, xmin=None, xmax=None, dx=None, xname="r" + ): model = self._get_model(model_name) if not hasattr(model, "evaluate"): raise ValueError( f"Model '{model_name}' does not have an evaluate method." ) - return model.evaluate() + if not ( + hasattr(model, "calc_obj") + and hasattr(model.calc_obj, "profile") + and model.calc_obj.profile is not None + ): + profile = Profile() + if isinstance(model.calc_obj, FitContribution): + profile.set_observed_profile( + xobs=numpy.arange(xmin, xmax, dx), + yobs=numpy.zeros_like(numpy.arange(xmin, xmax, dx)), + xname=xname, + ) + else: + # PDFGenerator uses profile.x, so it doesn't accept xname + profile.set_observed_profile( + xobs=numpy.arange(xmin, xmax, dx), + yobs=numpy.zeros_like(numpy.arange(xmin, xmax, dx)), + ) + model.set_profile(profile) + ycalc = model.evaluate() + model.calc_obj.profile = None + return ycalc def constrain_pdf_model_space_group_symmetry( self, model_name, space_group=None