From ad4cf6d37e5e29f97bdd7f6ff4523d39f1426726 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 12 Nov 2025 13:29:46 -0500 Subject: [PATCH 1/3] linefit tutorial --- docs/source/img/linefitfig1.png | Bin 0 -> 13189 bytes docs/source/img/linefitfig2.png | Bin 0 -> 29176 bytes docs/source/img/linefitfig3.png | Bin 0 -> 29663 bytes docs/source/index.rst | 1 + docs/source/writing-script.rst | 424 ++++++++++++++++++++++++++++++++ 5 files changed, 425 insertions(+) create mode 100644 docs/source/img/linefitfig1.png create mode 100644 docs/source/img/linefitfig2.png create mode 100644 docs/source/img/linefitfig3.png create mode 100644 docs/source/writing-script.rst diff --git a/docs/source/img/linefitfig1.png b/docs/source/img/linefitfig1.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1916dbc08c25c52dcaf82b3fe74920444c02a2 GIT binary patch literal 13189 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 literal 0 HcmV?d00001 diff --git a/docs/source/img/linefitfig2.png b/docs/source/img/linefitfig2.png new file mode 100644 index 0000000000000000000000000000000000000000..b6078590f39968532e27d767bad2953606d46e9f GIT binary patch literal 29176 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 literal 0 HcmV?d00001 diff --git a/docs/source/img/linefitfig3.png b/docs/source/img/linefitfig3.png new file mode 100644 index 0000000000000000000000000000000000000000..e5189bf3117e96b8e75bad10bf2e076cb17f8c6a GIT binary patch literal 29663 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 Command-Line Interface + Tutorial diffpy.cmi Script Package API .. toctree:: diff --git a/docs/source/writing-script.rst b/docs/source/writing-script.rst new file mode 100644 index 0000000..51cadbc --- /dev/null +++ b/docs/source/writing-script.rst @@ -0,0 +1,424 @@ +================================ +Writing a script with diffpy.cmi +================================ + +This guide provides a step-by-step walkthrough for creating a basic script using the ``diffpy.cmi`` framework. +We will follow the ``linefit`` example so you can familiarize yourself with the structure of a CMI script. + +If you would like, copy the ``linefit`` example to your current working directory by running, + +.. code-block:: bash + + cmi copy linefit + +To demonstrate how to fit data in ``diffpy.cmi``, we will start by trying to fit a simple line to some synthetic data. + +First, lets install the ``plotting`` pack if you haven't already done so. + +.. code-block:: bash + + cmi install plotting + +Now, open up a new Python script and start by importing the necessary modules, + +.. code-block:: python + + from __future__ import print_function + + import matplotlib.pyplot as plt + import numpy as np + from scipy.optimize import leastsq + + from diffpy.srfit.fitbase import ( + FitContribution, + FitRecipe, + FitResults, + Profile, + ) + +Generate Synthetic Data +----------------------- + +Let's generate some synthetic data to fit, This data will be a simple line with some added noise, + +.. code-block:: python + + # Generate synthetic data + xobs = np.arange(-10, 10.1) + sigma_yobs = 0.3 * np.ones_like(xobs) * np.random.randn(xobs.size) # random error + yobs = 0.5 * xobs + 3 + sigma_yobs + +Lets now visualize the data by plotting it, + +.. code-block:: python + + plt.figure(figsize=(10, 6)) + plt.plot(xobs, yobs, marker='o', linestyle="none", label="Observed Data") + plt.legend() + plt.show() + +You should see a scatter plot that looks something like this, + +.. image:: /img/linefitfig1.png + :alt: Scatter plot of synthetic data + :align: center + :width: 400px + +Great, now lets begin setting up our fitting framework. We will start by creating a ``Profile`` to hold our data. +This is done to encapsulate the observed data so that it can be used in the fitting process. + +.. code-block:: python + + # Create a Profile to hold the data + linedata = Profile() + linedata.setObservedProfile(xobs, yobs, sigma_yobs) + +``FitContribution`` +------------------- + +Now it's time to define our model in a ``FitContribution``. +A ``FitContribution`` is a container that holds the model function and its associated parameters. + +Setting Fit Equation +^^^^^^^^^^^^^^^^^^^^^^ + +In this case, our model is a simple linear function defined by the equation ``y = Ax + B``, + +.. code-block:: python + + # Define a FitContribution: linear model A*x + B + linefit = FitContribution("linefit") + linefit.setProfile(linedata) + linefit.setEquation("A * x + B") + +To see the parameters we just created, we can print them out, + +.. code-block:: python + + linefit.show() + +This should output something like, + +.. code-block:: bash + + Parameters + ------------------------------------------------------------------------------ + x [-10. -9. -8. -7. -6. -5. -4. -3. -2. -1. 0. 1. 2. 3. + y [-1.8053485 -1.56263035 -1.11627164 -0.4137478 0.68210214 0.58758801 + dy [0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 + B None + A None + +Initialize Fitting Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Note that ``A`` and ``B`` are set to ``None`` since we haven't assigned them any initial values yet. +To do that, we can set them like this, + +.. code-block:: python + + linefit.A = 3 + linefit.B = 5 + print("Initial A value:", linefit.A.value) + print("Initial B value:", linefit.B.value) + +This should output, + +.. code-block:: bash + + Initial A value: 3 + Initial B value: 5 + +``FitRecipe`` +------------- + +Now that we have our model defined and initlialized, we can create a ``FitRecipe``. +The ``FitRecipe`` is the main container that holds all the ``FitContributions`` +and manages the fitting process. + +.. code-block:: python + + # Create a FitRecipe to manage fitting + recipe = FitRecipe() + +Adding ``FitContribution`` to ``FitRecipe`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We can now add our ``linefit`` contribution to the recipe and print out the parameters, + +.. code-block:: python + + recipe.clearFitHooks() + recipe.addContribution(linefit) + recipe.show() + +This should output something like, + +.. code-block:: bash + + Parameters + ------------------------------------------------------------------------------ + linefit.x [-10. -9. -8. -7. -6. -5. -4. -3. -2. -1. 0. 1. 2. + linefit.y [-1.67605745 -1.19031421 -1.40162608 -0.90829441 0.38607679 0.44 + linefit.dy [0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0 + linefit.B 5 + linefit.A 3 + +Now you can see that the parameters are prefixed with ``linefit.``, +indicating they belong to the ``linefit`` contribution. Also, note that ``A`` and ``B`` now +have initial values assigned. + +Add Variables to Fit +-------------------- + +With everything set up, we can now mark the parameters we want to refine during the fitting process. +This is done using the ``.addVar()`` method of the ``FitRecipe``, + +.. code-block:: python + + recipe.addVar(recipe.linefit.A) + recipe.addVar(recipe.linefit.B) + +To see the variables that will be refined, we can print them out, + +.. code-block:: python + + print("recipe.A =", recipe.A) + print("recipe.A.value =", recipe.A.value) + print("recipe.values =", recipe.values) + print("recipe.names =", recipe.names) + print("recipe.residual() =", recipe.residual()) + +This should output something like, + +.. code-block:: bash + + recipe.A = ParameterProxy(A) + recipe.A.value = 3 + recipe.values = [3 5] + recipe.names = ['A', 'B'] + recipe.residual() = [-78.18212598 -67.62039727 -60.63792074 -52.12278541 -41.97888213 + -34.76069913 -27.49568671 -17.88327019 -10.00997001 -1.21702776 + 6.79454602 15.44637505 21.39664018 32.98689369 40.26685555 + 47.96728622 57.81169457 65.48416201 73.74878531 81.40669851 + 90.08765793] + +The ``recipe.residual()`` method computes the difference between the observed data and the model prediction. +As you can see, the residuals are quite large at this point since we haven't performed any fitting yet. + +To better visualize the residuals, we can plot them, + +.. code-block:: python + + ycalc = linefit.A.value * xobs + linefit.B.value + + plt.figure(figsize=(10, 6)) + plt.plot(xobs, yobs, marker='o', linestyle='None', label="Observed Data") + plt.plot(xobs, ycalc, label="Calculated Fit: Ax + B") + plt.legend() + plt.show() + +You should see a plot that looks something like this, + +.. image:: /img/linefitfig2.png + :alt: Plot of observed data and initial fit + :align: center + :width: 400px + +As you can see, the initial fit is quite poor, which is expected since we haven't refined the parameters yet. +So... lets refine them! + +Perform the Least-Squares Fit +----------------------------- + +Now we are ready to perform the least squares fitting using the ``leastsq`` function from ``scipy.optimize``. +The ``leastsq`` function minimizes the sum of squares between the observed data and the model prediction +by adjusting the parameters we marked for refinement. The least-squares algorithm is given by, + +.. math:: + + \text{minimize} \sum_{i} \left( y_{\text{obs}, i} - y_{\text{calc}, i} \right)^2 + +This is what is known as the **objective function**. The objective function is a function that +you want to minimize (or maximize) during the fitting process. In this case, +the squared difference between the calculated and observed values is what the algorithm will minimize. +In theory, our objective function could be anything. You could even customize your own! +But for now, we will use least-squares to optimize our fit. + +To perform a least-squares regression, we pass the residuals +(``recipe.residual``), which represent the differences to minimize, +as a function of the current parameter values (``recipe.values``) to ``leastsq``. + +.. code-block:: python + + leastsq(recipe.residual, recipe.values) + print("After leastsq:", recipe.names, "-->", recipe.values) + linefit.show() + +This should output something like, + +.. code-block:: bash + + After leastsq: ['A', 'B'] --> [0.51240164 3.00692156] + Parameters + ------------------------------------------------------------------------------ + x [-10. -9. -8. -7. -6. -5. -4. -3. -2. -1. 0. 1. 2. 3. + y [-2.33763938 -1.9018065 -0.9653354 -0.63162421 0.22997984 -0.17955301 + dy [0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 + A 0.512401638015315 + B 3.006921559716823 + +You can see that the parameters ``A`` and ``B`` have been updated to values that better fit the data. +Lets print the residual sum of squares to see how well the fit performed, + +.. code-block:: python + + print("recipe.residual() =", recipe.residual()) + +This should output something like, + +.. code-block:: bash + + recipe.residual() = [ 0.83916097 0.6429651 -0.76778838 -0.89453514 0.42300657 0.97663332 + -1.50946072 -0.21983212 -0.3464077 -1.84471305 -0.11995115 1.14584239 + 1.04321154 0.92606764 0.53831321 -0.06905766 -0.02106872 -0.78551651 + 1.3405239 -0.01692016 -1.28047336] + +As you can see, the residuals have significantly decreased, indicating a much better fit to the data. + +Lets visualize the final fit by plotting the observed data and the fitted line, + +.. code-block:: python + + ycalc = linefit.A.value * xobs + linefit.B.value + + plt.figure(figsize=(10, 6)) + plt.plot(xobs, yobs, marker='o', linestyle='None', label="Observed Data") + plt.plot(xobs, ycalc, label="Fitted Line: Ax + B") + plt.legend() + plt.show() + +You should see a plot that looks something like this, + +.. image:: /img/linefitfig3.png + :alt: Plot of observed data and final fitted line + :align: center + :width: 400px + +Wow! Look at that fit! + +``FitResults`` +-------------- + +To summarize the fitting results, we can create a ``FitResults`` object and pass our recipe to it, + +.. code-block:: python + + # Create FitResults to summarize the fit + results = FitResults(recipe) + print(results) + +This should output something like, + +.. code-block:: bash + + Overall + ------------------------------------------------------------------------------ + Residual 12.59360793 + Contributions 12.59360793 + Restraints 0.00000000 + Chi2 12.59360793 + Reduced Chi2 0.66282147 + Rw 0.05372518 + + Variables + ------------------------------------------------------------------------------ + A 5.18663792e-01 +/- 1.08112496e-02 + B 2.96331208e+00 +/- 6.54653670e-02 + + Variable Correlations greater than 25% + ------------------------------------------------------------------------------ + No correlations greater than 25% + +The value ``Rw`` is a measure of the quality of the fit, with lower values indicating a better fit. + +How to Fix Parameters +--------------------- + +.. note:: + + Because in this example we are fitting a simple line with only two parameters, + we can select any values for ``A`` and ``B`` and still get a good fit. However, + we demonstrate how to fix parameters for educational purposes. + +There are two ways to fix parameters in ``diffpy.cmi``, the first one is by +using the ``.fix()`` method on a parameter, + +.. code-block:: python + + recipe.fix(B=0) + print("Free:", recipe.names, "-->", recipe.values) + print("Fixed:", recipe.fixednames, "-->", recipe.fixedvalues) + +This should output something like, + +.. code-block:: bash + + Free: ['A'] --> [0.51315825] + Fixed: ['B'] --> [0] + +The other way to fix parameters is by setting ``fixed=True`` when adding the variable +with ``.addVar()`` to the recipe, + +.. code-block:: python + + recipe.addVar(recipe.linefit.B, fixed=True) + print("Free:", recipe.names, "-->", recipe.values) + print("Fixed:", recipe.fixednames, "-->", recipe.fixedvalues) + +This should output something like, + +.. code-block:: bash + + Free: ['A'] --> [0.49144738] + Fixed: ['B'] --> [5] + +Tips for Fitting Data +------------------------- + +Before we wrap up this tutorial, +here are some tips on selecting and refining parameters for fitting. + +Selecting Good Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Because the ``leastsq`` regressor is a local optimization, you typically need to provide good starting values +for the parameters. The process of finding good starting values is an art which will be carefully crafted +over time as you gain experience with fitting data. Use your scientific intuition to +select good starting values! + + +Refining Strategy +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Oftentimes, you need to fix certain parameters during the fitting process to find a solution that +better fits your data. This is a common practice in data fitting to improve the stability of the fit. + +Typically, the process goes like this: + +.. admonition:: Refining Strategy + + 1. **Good initial guess:** Start with good initial guesses for all parameters. + 2. **Refine on Parameters:** Refine all (or a subset of) parameters. If you see large correlations or instability, + try again with a different initial guess or a different subset of parameters. + 3. **Fixing Parameters:** Fix some parameters based on the results from step 2. + 4. **Refine again:** Refine the remaining free parameters. + +This process is where you spend most of your time when fitting data. + +Words of Encouragement +^^^^^^^^^^^^^^^^^^^^^^^^ + +Remember, all the computer knows how to do is minimize a value. +It has no understanding of the physical meaning of the parameters. +That is why we need smart people like yourself to guide the fitting process! From c367394e815fa887fb6bbe02cd2e306f35df3725 Mon Sep 17 00:00:00 2001 From: Caden Myers Date: Wed, 12 Nov 2025 13:30:26 -0500 Subject: [PATCH 2/3] news --- news/linefit-tutorial.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 news/linefit-tutorial.rst diff --git a/news/linefit-tutorial.rst b/news/linefit-tutorial.rst new file mode 100644 index 0000000..5b3d9e4 --- /dev/null +++ b/news/linefit-tutorial.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add tutorial on `linefit` to documentation. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* From 2d45d1ff36d7a5adedc2c01d7feecf16d7b6112f Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Wed, 12 Nov 2025 13:40:45 -0500 Subject: [PATCH 3/3] Remove unnecessary future import in script Removed the import of print_function from future module. --- docs/source/writing-script.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/writing-script.rst b/docs/source/writing-script.rst index 51cadbc..d667303 100644 --- a/docs/source/writing-script.rst +++ b/docs/source/writing-script.rst @@ -23,8 +23,6 @@ Now, open up a new Python script and start by importing the necessary modules, .. code-block:: python - from __future__ import print_function - import matplotlib.pyplot as plt import numpy as np from scipy.optimize import leastsq