{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "efbc786f", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:07.719190Z", "iopub.status.busy": "2026-01-06T13:53:07.719038Z", "iopub.status.idle": "2026-01-06T13:53:07.724173Z", "shell.execute_reply": "2026-01-06T13:53:07.723195Z" }, "tags": [ "hide-in-docs" ] }, "outputs": [], "source": [ "# Check if the easydiffraction library is installed.\n", "# If not, install it with the 'visualization' extras.\n", "# Needed when running remotely (e.g. Colab) where the lib is absent.\n", "import builtins\n", "import importlib.util\n", "\n", "if (hasattr(builtins, '__IPYTHON__') and\n", " importlib.util.find_spec('easydiffraction') is None):\n", " !pip install 'easydiffraction[visualization]==0.10.1'" ] }, { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Fitting Powder Diffraction data\n", "\n", "This notebook guides you through the Rietveld refinement of crystal\n", "structures using simulated powder diffraction data. It consists of two\n", "parts:\n", "- Introduction: A simple reference fit using silicon (Si) crystal\n", " structure.\n", "- Exercise: A more complex fit using La₀.₅Ba₀.₅CoO₃ (LBCO) crystal\n", " structure.\n", "\n", "## 🛠️ Import Library\n", "\n", "We start by importing the necessary library for the analysis. In this\n", "notebook, we use the EasyDiffraction library. As mentioned in the\n", "introduction to EasyScience, EasyDiffraction is built on that\n", "framework and offers a high-level interface focused specifically for\n", "diffraction analysis.\n", "\n", "This notebook is self-contained and designed for hands-on learning.\n", "However, if you're interested in exploring more advanced features or\n", "learning about additional capabilities of the EasyDiffraction library,\n", "please refer to the official documentation:\n", "https://docs.easydiffraction.org/lib\n", "\n", "Depending on your requirements, you may choose to import only specific\n", "classes. However, for the sake of simplicity in this notebook, we will\n", "import the entire library." ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/first-steps/#importing-easydiffraction)\n", "for more details about importing the EasyDiffraction library and its\n", "components." ] }, { "cell_type": "code", "execution_count": 2, "id": "2", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:07.726909Z", "iopub.status.busy": "2026-01-06T13:53:07.726738Z", "iopub.status.idle": "2026-01-06T13:53:11.617322Z", "shell.execute_reply": "2026-01-06T13:53:11.609538Z" } }, "outputs": [], "source": [ "import easydiffraction as ed" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "## 📘 Introduction: Simple Reference Fit – Si\n", "\n", "Before diving into the more complex fitting exercise with the\n", "La₀.₅Ba₀.₅CoO₃ (LBCO) crystal structure, let's start with a simpler\n", "example using the silicon (Si) crystal structure. This will help us\n", "understand the basic concepts and steps involved in fitting a crystal\n", "structure using powder diffraction data.\n", "\n", "For this part of the notebook, we will use the powder diffraction data\n", "previously simulated using the Si crystal structure.\n", "\n", "### 📦 Create a Project – 'reference'\n", "\n", "In EasyDiffraction, a project serves as a container for all\n", "information related to the analysis of a specific experiment or set of\n", "experiments. It enables you to organize your data, experiments, sample\n", "models, and fitting parameters in a structured manner. You can think\n", "of it as a folder containing all the essential details about your\n", "analysis. The project also allows us to visualize both the measured\n", "and calculated diffraction patterns, among other things." ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/project/)\n", "for more details about creating a project and its purpose in the\n", "analysis workflow." ] }, { "cell_type": "code", "execution_count": 3, "id": "5", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:11.622960Z", "iopub.status.busy": "2026-01-06T13:53:11.622405Z", "iopub.status.idle": "2026-01-06T13:53:11.931832Z", "shell.execute_reply": "2026-01-06T13:53:11.930185Z" } }, "outputs": [], "source": [ "project_1 = ed.Project(name='reference')" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "You can set the title and description of the project to provide\n", "context and information about the analysis being performed. This is\n", "useful for documentation purposes and helps others (or yourself in the\n", "future) understand the purpose of the project at a glance." ] }, { "cell_type": "code", "execution_count": 4, "id": "7", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:11.937225Z", "iopub.status.busy": "2026-01-06T13:53:11.937009Z", "iopub.status.idle": "2026-01-06T13:53:11.964673Z", "shell.execute_reply": "2026-01-06T13:53:11.947667Z" } }, "outputs": [], "source": [ "project_1.info.title = 'Reference Silicon Fit'\n", "project_1.info.description = 'Fitting simulated powder diffraction pattern of Si.'" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "### 🔬 Create an Experiment\n", "\n", "An experiment represents a specific diffraction measurement performed\n", "on a specific sample using a particular instrument. It contains\n", "details about the measured data, instrument parameters, and other\n", "relevant information." ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/)\n", "for more details about experiments and their purpose in the analysis\n", "workflow." ] }, { "cell_type": "code", "execution_count": 5, "id": "10", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:11.977006Z", "iopub.status.busy": "2026-01-06T13:53:11.976021Z", "iopub.status.idle": "2026-01-06T13:53:11.982707Z", "shell.execute_reply": "2026-01-06T13:53:11.980995Z" } }, "outputs": [], "source": [ "data_dir = 'data'\n", "file_name = 'reduced_Si.xye'\n", "si_xye_path = f'{data_dir}/{file_name}'" ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "Uncomment the following cell if your data reduction failed and the\n", "reduced data file is missing. In this case, you can download our\n", "pre-generated reduced data file from the EasyDiffraction repository.\n", "The `download_data` function will not overwrite an existing file\n", "unless you set `overwrite=True`, so it's safe to run even if the\n", "file is already present." ] }, { "cell_type": "code", "execution_count": 6, "id": "12", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:11.989255Z", "iopub.status.busy": "2026-01-06T13:53:11.988337Z", "iopub.status.idle": "2026-01-06T13:53:12.262448Z", "shell.execute_reply": "2026-01-06T13:53:12.261982Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mGetting data\u001b[0m\u001b[1;34m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Data #\u001b[1;36m17\u001b[0m: Si, McStas simulation, DMSC Summer School \u001b[1;36m2025\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Data #\u001b[1;36m17\u001b[0m downloaded to \u001b[32m'data/ed-17.xye'\u001b[0m\n" ] } ], "source": [ "si_xye_path = ed.download_data(id=17, destination=data_dir)" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "Now we can create the experiment and load the measured data. In this\n", "case, the experiment is defined as a powder diffraction measurement\n", "using time-of-flight neutrons. The measured data is loaded from a file\n", "containing the reduced diffraction pattern of Si from the data\n", "reduction notebook." ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#defining-an-experiment-manually)\n", "for more details about different types of experiments." ] }, { "cell_type": "code", "execution_count": 7, "id": "15", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.265591Z", "iopub.status.busy": "2026-01-06T13:53:12.265373Z", "iopub.status.idle": "2026-01-06T13:53:12.633119Z", "shell.execute_reply": "2026-01-06T13:53:12.631877Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mData loaded successfully\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Experiment 🔬 \u001b[32m'sim_si'\u001b[0m. Number of data points: \u001b[1;36m900\u001b[0m\n" ] } ], "source": [ "project_1.experiments.add(\n", " name='sim_si',\n", " data_path=si_xye_path,\n", " sample_form='powder',\n", " beam_mode='time-of-flight',\n", " radiation_probe='neutron',\n", ")" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "#### Inspect Measured Data\n", "\n", "After creating the experiment, we can examine the measured data. The\n", "measured data consists of a diffraction pattern having time-of-flight\n", "(TOF) values and corresponding intensities. The TOF values are given\n", "in microseconds (μs), and the intensities are in arbitrary units.\n", "\n", "The data is stored in XYE format, a simple text format containing\n", "three columns: TOF, intensity, and intensity error (if available)." ] }, { "cell_type": "markdown", "id": "17", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#measured-data-category)\n", "for more details about the measured data and its format.\n", "\n", "To visualize the measured data, we can use the `plot_meas` method of\n", "the project. Before plotting, we need to set the plotting engine to\n", "'plotly', which provides interactive visualizations." ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://easyscience.github.io/diffraction-lib/user-guide/first-steps/#supported-plotters)\n", "for more details about setting the plotting engine." ] }, { "cell_type": "code", "execution_count": 8, "id": "19", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.636850Z", "iopub.status.busy": "2026-01-06T13:53:12.636405Z", "iopub.status.idle": "2026-01-06T13:53:12.640259Z", "shell.execute_reply": "2026-01-06T13:53:12.639479Z" } }, "outputs": [], "source": [ "# Keep the auto-selected engine. Alternatively, you can uncomment the\n", "# line below to explicitly set the engine to the required one.\n", "# project.plotter.engine = 'plotly'" ] }, { "cell_type": "code", "execution_count": 9, "id": "20", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.645133Z", "iopub.status.busy": "2026-01-06T13:53:12.643076Z", "iopub.status.idle": "2026-01-06T13:53:12.849888Z", "shell.execute_reply": "2026-01-06T13:53:12.847710Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warning: No linked phases defined. Returning empty pattern.\n" ] }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas(expt_name='sim_si')" ] }, { "cell_type": "markdown", "id": "21", "metadata": {}, "source": [ "If you zoom in on the highest TOF peak (around 120,000 μs), you will\n", "notice that it has a broad and unusual shape. This distortion, along\n", "with additional effects on the low TOF peaks, is most likely an\n", "artifact related to the simplifications made during the simulation\n", "and/or reduction process and is currently under investigation.\n", "However, this is outside the scope of this school. Therefore, we will\n", "simply exclude both the low and high TOF regions from the analysis by\n", "adding an excluded regions to the experiment.\n", "\n", "In real experiments, it is often necessary to exclude certain regions\n", "from the measured data. For example, the direct beam can significantly\n", "increase the background at very low angles, making those parts of the\n", "diffractogram unreliable. Additionally, sample environment components\n", "may introduce unwanted peaks. In such cases, excluding specific\n", "regions is often simpler and more effective than modeling them with an\n", "additional sample phase." ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#excluded-regions-category)\n", "for more details about excluding regions from the measured data." ] }, { "cell_type": "code", "execution_count": 10, "id": "23", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.858411Z", "iopub.status.busy": "2026-01-06T13:53:12.858130Z", "iopub.status.idle": "2026-01-06T13:53:12.862906Z", "shell.execute_reply": "2026-01-06T13:53:12.861954Z" } }, "outputs": [], "source": [ "project_1.experiments['sim_si'].excluded_regions.add(id='1', start=0, end=55000)\n", "project_1.experiments['sim_si'].excluded_regions.add(id='2', start=105500, end=200000)" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "To visualize the effect of excluding the high TOF region, we can plot\n", "the measured data again. The excluded region will be omitted from the\n", "plot and is not used in the fitting process." ] }, { "cell_type": "code", "execution_count": 11, "id": "25", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.864766Z", "iopub.status.busy": "2026-01-06T13:53:12.864647Z", "iopub.status.idle": "2026-01-06T13:53:12.923402Z", "shell.execute_reply": "2026-01-06T13:53:12.916556Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warning: No linked phases defined. Returning empty pattern.\n" ] }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas(expt_name='sim_si')" ] }, { "cell_type": "markdown", "id": "26", "metadata": {}, "source": [ "#### Set Instrument Parameters\n", "\n", "After the experiment is created and measured data is loaded, we need\n", "to set the instrument parameters.\n", "\n", "In this type of experiment, the instrument parameters define how the\n", "measured data is converted between d-spacing and time-of-flight (TOF)\n", "during the data reduction process as well as the angular position of\n", "the detector. So, we put values based on those from the reduction.\n", "These values can be found in the header of the corresponding .XYE\n", "file. Their names are `two_theta` and `DIFC`, which stand for the\n", "two-theta angle and the linear conversion factor from d-spacing to\n", "TOF, respectively.\n", "\n", "You can set them manually, but it is more convenient to use the\n", "`get_value_from_xye_header` function from the EasyDiffraction library." ] }, { "cell_type": "markdown", "id": "27", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#instrument-category)\n", "for more details about the instrument parameters." ] }, { "cell_type": "code", "execution_count": 12, "id": "28", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.944710Z", "iopub.status.busy": "2026-01-06T13:53:12.944530Z", "iopub.status.idle": "2026-01-06T13:53:12.969852Z", "shell.execute_reply": "2026-01-06T13:53:12.962199Z" } }, "outputs": [], "source": [ "project_1.experiments['sim_si'].instrument.setup_twotheta_bank = ed.get_value_from_xye_header(\n", " si_xye_path, 'two_theta'\n", ")\n", "project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear = ed.get_value_from_xye_header(\n", " si_xye_path, 'DIFC'\n", ")" ] }, { "cell_type": "markdown", "id": "29", "metadata": {}, "source": [ "Before proceeding, let's take a quick look at the concept of\n", "parameters in EasyDiffraction, which is similar to the parameter\n", "concept in EasyScience. The current version of EasyDiffraction is\n", "transitioning to reuse the parameter system from EasyScience.\n", "\n", "That is, every parameter is an object, which has different attributes,\n", "such as `value`, `units`, etc. To display the parameter of interest,\n", "you can simply print the parameter object.\n", "\n", "For example, to display the linear conversion factor from d-spacing to\n", "TOF, which is the `calib_d_to_tof_linear` parameter, you can do the\n", "following:" ] }, { "cell_type": "code", "execution_count": 13, "id": "30", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:12.978966Z", "iopub.status.busy": "2026-01-06T13:53:12.978583Z", "iopub.status.idle": "2026-01-06T13:53:13.004068Z", "shell.execute_reply": "2026-01-06T13:53:13.003305Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "print(project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear)" ] }, { "cell_type": "markdown", "id": "31", "metadata": {}, "source": [ "The `value` attribute represents the current value of the parameter as\n", "a float. You can access it directly by using the `value` attribute of\n", "the parameter. This is useful when you want to use the parameter value\n", "in calculations or when you want to assign it to another parameter.\n", "For example, to get only the value of the same parameter as floating\n", "point number, but not the whole object, you can do the following:" ] }, { "cell_type": "code", "execution_count": 14, "id": "32", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.011213Z", "iopub.status.busy": "2026-01-06T13:53:13.011024Z", "iopub.status.idle": "2026-01-06T13:53:13.023478Z", "shell.execute_reply": "2026-01-06T13:53:13.015942Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "61445.893309194034\n" ] } ], "source": [ "print(project_1.experiments['sim_si'].instrument.calib_d_to_tof_linear.value)" ] }, { "cell_type": "markdown", "id": "33", "metadata": {}, "source": [ "Note that to set the value of the parameter, you can simply assign a\n", "new value to the parameter object without using the `value` attribute,\n", "as we did above." ] }, { "cell_type": "markdown", "id": "34", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/parameters/)\n", "for more details about parameters in EasyDiffraction and their\n", "attributes." ] }, { "cell_type": "markdown", "id": "35", "metadata": {}, "source": [ "#### Set Peak Profile Parameters\n", "\n", "The next set of parameters is needed to define the peak profile used\n", "in the fitting process. The peak profile describes the shape of the\n", "diffraction peaks. They include parameters for the broadening and\n", "asymmetry of the peaks.\n", "\n", "There are several commonly used peak profile functions:\n", "- **Gaussian**: Describes peaks with a symmetric bell-shaped curve,\n", " often used when instrumental broadening dominates. [Click for more\n", " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/Gaussian.html)\n", "- **Lorentzian**: Produces narrower central peaks with longer tails,\n", " frequently used to model size broadening effects. [Click for more\n", " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/Lorentzian.html)\n", "- **Pseudo-Voigt**: A linear combination of Gaussian and Lorentzian\n", " components, providing flexibility to represent real diffraction\n", " peaks. [Click for more\n", " details.](https://mantidproject.github.io/docs-versioned/v6.1.0/fitting/fitfunctions/PseudoVoigt.html)\n", "- **Pseudo-Voigt convoluted with Ikeda-Carpenter**: Incorporates the\n", " asymmetry introduced by the neutron pulse shape in time-of-flight\n", " instruments. This is a common choice for TOF neutron powder\n", " diffraction data. [Click for more\n", " details.](https://docs.mantidproject.org/v6.1.0/fitting/fitfunctions/IkedaCarpenterPV.html)\n", "\n", "Here, we use a pseudo-Voigt peak profile function with Ikeda-Carpenter\n", "asymmetry.\n", "\n", "The parameter values are typically determined experimentally on the\n", "same instrument and under the same configuration as the data being\n", "analyzed, using measurements of a standard sample. In our case, the Si\n", "sample serves as this standard reference. We will refine the peak\n", "profile parameters here, and these refined values will be used as\n", "starting points for the more complex fit in the next part of the\n", "notebook. For this initial fit, we will provide reasonable physical\n", "guesses as starting values." ] }, { "cell_type": "markdown", "id": "36", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#peak-category)\n", "for more details about the peak profile types." ] }, { "cell_type": "code", "execution_count": 15, "id": "37", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.030750Z", "iopub.status.busy": "2026-01-06T13:53:13.029462Z", "iopub.status.idle": "2026-01-06T13:53:13.044499Z", "shell.execute_reply": "2026-01-06T13:53:13.043227Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mPeak profile type for experiment \u001b[0m\u001b[32m'sim_si'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "pseudo-voigt * ikeda-carpenter\n" ] } ], "source": [ "project_1.experiments['sim_si'].peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_0 = 69498\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_1 = -55578\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_2 = 14560\n", "project_1.experiments['sim_si'].peak.broad_mix_beta_0 = 0.0019\n", "project_1.experiments['sim_si'].peak.broad_mix_beta_1 = 0.0137\n", "project_1.experiments['sim_si'].peak.asym_alpha_0 = -0.0055\n", "project_1.experiments['sim_si'].peak.asym_alpha_1 = 0.0147" ] }, { "cell_type": "markdown", "id": "38", "metadata": {}, "source": [ "#### Set Background\n", "\n", "The background of the diffraction pattern represents the portion of\n", "the pattern that is not related to the crystal structure of the\n", "sample. It's rather represents noise and other sources of scattering\n", "that can affect the measured intensities. This includes contributions\n", "from the instrument, the sample holder, the sample environment, and\n", "other sources of incoherent scattering.\n", "\n", "The background can be modeled in various ways. In this example, we\n", "will use a simple line segment background, which is a common approach\n", "for powder diffraction data. The background intensity at any point is\n", "defined by linear interpolation between neighboring points. The\n", "background points are selected to span the range of the diffraction\n", "pattern while avoiding the peaks.\n", "\n", "We will add several background points at specific TOF values (in μs)\n", "and corresponding intensity values. These points are chosen to\n", "represent the background level in the diffraction pattern free from\n", "any peaks.\n", "\n", "The background points are added using the `add` method of the\n", "`background` object. The `x` parameter represents the TOF value, and\n", "the `y` parameter represents the intensity value at that TOF.\n", "\n", "Let's set all the background points at a constant value of 0.01, which\n", "can be roughly estimated by the eye, and we will refine them later\n", "during the fitting process." ] }, { "cell_type": "markdown", "id": "39", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#background-category)\n", "for more details about the background and its types." ] }, { "cell_type": "code", "execution_count": 16, "id": "40", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.051826Z", "iopub.status.busy": "2026-01-06T13:53:13.049779Z", "iopub.status.idle": "2026-01-06T13:53:13.072931Z", "shell.execute_reply": "2026-01-06T13:53:13.071134Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mBackground type for experiment \u001b[0m\u001b[32m'sim_si'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "line-segment\n" ] } ], "source": [ "project_1.experiments['sim_si'].background_type = 'line-segment'\n", "project_1.experiments['sim_si'].background.add(id='1', x=50000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='2', x=60000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='3', x=70000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='4', x=80000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='5', x=90000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='6', x=100000, y=0.01)\n", "project_1.experiments['sim_si'].background.add(id='7', x=110000, y=0.01)" ] }, { "cell_type": "markdown", "id": "41", "metadata": {}, "source": [ "### 🧩 Create a Sample Model – Si\n", "\n", "After setting up the experiment, we need to create a sample model that\n", "describes the crystal structure of the sample being analyzed.\n", "\n", "In this case, we will create a sample model for silicon (Si) with a\n", "cubic crystal structure. The sample model contains information about\n", "the space group, lattice parameters, atomic positions of the atoms in\n", "the unit cell, atom types, occupancies and atomic displacement\n", "parameters. The sample model is essential for the fitting process, as\n", "it is used to calculate the expected diffraction pattern.\n", "\n", "EasyDiffraction refines the crystal structure of the sample, but does\n", "not solve it. Therefore, we need a good starting point with reasonable\n", "structural parameters.\n", "\n", "Here, we define the Si structure as a cubic structure. As this is a\n", "cubic structure, we only need to define the single lattice parameter,\n", "which is the length of the unit cell edge. The Si crystal structure\n", "has a single atom in the unit cell, which is located at the origin (0,\n", "0, 0) of the unit cell. The symmetry of this site is defined by the\n", "Wyckoff letter 'a'. The atomic displacement parameter defines the\n", "thermal vibrations of the atoms in the unit cell and is presented as\n", "an isotropic parameter (B_iso).\n", "\n", "Sometimes, the initial crystal structure parameters can be obtained\n", "from one of the crystallographic databases, like for example the\n", "Crystallography Open Database (COD). In this case, we use the COD\n", "entry for silicon as a reference for the initial crystal structure\n", "model: https://www.crystallography.net/cod/4507226.html\n", "\n", "Usually, the crystal structure parameters are provided in a CIF file\n", "format, which is a standard format for crystallographic data. An\n", "example of a CIF file for silicon is shown below. The CIF file\n", "contains the space group information, unit cell parameters, and atomic\n", "positions." ] }, { "cell_type": "markdown", "id": "42", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/data-format/)\n", "for more details about the CIF format and its use in EasyDiffraction." ] }, { "cell_type": "markdown", "id": "43", "metadata": {}, "source": [ "```\n", "data_si\n", "\n", "_space_group.name_H-M_alt \"F d -3 m\"\n", "_space_group.IT_coordinate_system_code 2\n", "\n", "_cell.length_a 5.43\n", "_cell.length_b 5.43\n", "_cell.length_c 5.43\n", "_cell.angle_alpha 90.0\n", "_cell.angle_beta 90.0\n", "_cell.angle_gamma 90.0\n", "\n", "loop_\n", "_atom_site.label\n", "_atom_site.type_symbol\n", "_atom_site.fract_x\n", "_atom_site.fract_y\n", "_atom_site.fract_z\n", "_atom_site.wyckoff_letter\n", "_atom_site.occupancy\n", "_atom_site.ADP_type\n", "_atom_site.B_iso_or_equiv\n", "Si Si 0 0 0 a 1.0 Biso 0.89\n", "```" ] }, { "cell_type": "markdown", "id": "44", "metadata": {}, "source": [ "As with adding the experiment in the previous step, we will create a\n", "default sample model and then modify its parameters to match the Si\n", "structure." ] }, { "cell_type": "markdown", "id": "45", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/model/)\n", "for more details about sample models and their purpose in the data\n", "analysis workflow." ] }, { "cell_type": "markdown", "id": "46", "metadata": {}, "source": [ "#### Add Sample Model" ] }, { "cell_type": "code", "execution_count": 17, "id": "47", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.078487Z", "iopub.status.busy": "2026-01-06T13:53:13.076915Z", "iopub.status.idle": "2026-01-06T13:53:13.086265Z", "shell.execute_reply": "2026-01-06T13:53:13.084011Z" } }, "outputs": [], "source": [ "project_1.sample_models.add(name='si')" ] }, { "cell_type": "markdown", "id": "48", "metadata": {}, "source": [ "#### Set Space Group" ] }, { "cell_type": "markdown", "id": "49", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/model/#space-group-category)\n", "for more details about the space group." ] }, { "cell_type": "code", "execution_count": 18, "id": "50", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.088595Z", "iopub.status.busy": "2026-01-06T13:53:13.088053Z", "iopub.status.idle": "2026-01-06T13:53:13.098185Z", "shell.execute_reply": "2026-01-06T13:53:13.094025Z" } }, "outputs": [], "source": [ "project_1.sample_models['si'].space_group.name_h_m = 'F d -3 m'\n", "project_1.sample_models['si'].space_group.it_coordinate_system_code = '2'" ] }, { "cell_type": "markdown", "id": "51", "metadata": {}, "source": [ "#### Set Lattice Parameters" ] }, { "cell_type": "markdown", "id": "52", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/model/#cell-category)\n", "for more details about the unit cell parameters." ] }, { "cell_type": "code", "execution_count": 19, "id": "53", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.104121Z", "iopub.status.busy": "2026-01-06T13:53:13.103677Z", "iopub.status.idle": "2026-01-06T13:53:13.108905Z", "shell.execute_reply": "2026-01-06T13:53:13.105994Z" } }, "outputs": [], "source": [ "project_1.sample_models['si'].cell.length_a = 5.43" ] }, { "cell_type": "markdown", "id": "54", "metadata": {}, "source": [ "#### Set Atom Sites" ] }, { "cell_type": "markdown", "id": "55", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/model/#atom-sites-category)\n", "for more details about the atom sites category." ] }, { "cell_type": "code", "execution_count": 20, "id": "56", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.113161Z", "iopub.status.busy": "2026-01-06T13:53:13.112827Z", "iopub.status.idle": "2026-01-06T13:53:13.116796Z", "shell.execute_reply": "2026-01-06T13:53:13.116285Z" } }, "outputs": [], "source": [ "project_1.sample_models['si'].atom_sites.add(\n", " label='Si',\n", " type_symbol='Si',\n", " fract_x=0,\n", " fract_y=0,\n", " fract_z=0,\n", " wyckoff_letter='a',\n", " b_iso=0.89,\n", ")" ] }, { "cell_type": "markdown", "id": "57", "metadata": {}, "source": [ "### 🔗 Assign Sample Model to Experiment\n", "\n", "Now we need to assign, or link, this sample model to the experiment\n", "created above. This linked crystallographic phase will be used to\n", "calculate the expected diffraction pattern based on the crystal\n", "structure defined in the sample model." ] }, { "cell_type": "markdown", "id": "58", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/experiment/#linked-phases-category)\n", "for more details about linking a sample model to an experiment." ] }, { "cell_type": "code", "execution_count": 21, "id": "59", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.118447Z", "iopub.status.busy": "2026-01-06T13:53:13.118337Z", "iopub.status.idle": "2026-01-06T13:53:13.127775Z", "shell.execute_reply": "2026-01-06T13:53:13.124401Z" } }, "outputs": [], "source": [ "project_1.experiments['sim_si'].linked_phases.add(id='si', scale=1.0)" ] }, { "cell_type": "markdown", "id": "60", "metadata": {}, "source": [ "### 🚀 Analyze and Fit the Data\n", "\n", "After setting up the experiment and sample model, we can now analyze\n", "the measured diffraction pattern and perform the fit. Building on the\n", "analogies from the EasyScience library and the previous notebooks, we\n", "can say that all the parameters we introduced earlier — those defining\n", "the sample model (crystal structure parameters) and the experiment\n", "(instrument, background, and peak profile parameters) — together form\n", "the complete set of parameters that can be refined during the fitting\n", "process.\n", "\n", "Unlike in the previous analysis notebooks, we will not create a\n", "**math_model** object here. The mathematical model used to calculate\n", "the expected diffraction pattern is already defined in the library and\n", "will be applied automatically during the fitting process." ] }, { "cell_type": "markdown", "id": "61", "metadata": { "title": "**Reminder:**" }, "source": [ "\n", "The fitting process involves comparing the measured diffraction\n", "pattern with the calculated diffraction pattern based on the sample\n", "model and instrument parameters. The goal is to adjust the parameters\n", "of the sample model and the experiment to minimize the difference\n", "between the measured and calculated diffraction patterns. This is done\n", "by refining the parameters of the sample model and the instrument\n", "settings to achieve a better fit." ] }, { "cell_type": "markdown", "id": "62", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/analysis/#minimization-optimization)\n", "for more details about the fitting process in EasyDiffraction." ] }, { "cell_type": "markdown", "id": "63", "metadata": {}, "source": [ "#### Set Fit Parameters\n", "\n", "To perform the fit, we need to specify the refinement parameters.\n", "These are the parameters that will be adjusted during the fitting\n", "process to minimize the difference between the measured and calculated\n", "diffraction patterns. This is done by setting the `free` attribute of\n", "the corresponding parameters to `True`.\n", "\n", "Note: setting `param.free = True` is equivalent to using `param.fixed\n", "= False` in the EasyScience library.\n", "\n", "We will refine the scale factor of the Si phase, the intensities of\n", "the background points as well as the peak profile parameters. The\n", "structure parameters of the Si phase will not be refined, as this\n", "sample is considered a reference sample with known parameters." ] }, { "cell_type": "code", "execution_count": 22, "id": "64", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.129932Z", "iopub.status.busy": "2026-01-06T13:53:13.129807Z", "iopub.status.idle": "2026-01-06T13:53:13.134768Z", "shell.execute_reply": "2026-01-06T13:53:13.134286Z" } }, "outputs": [], "source": [ "project_1.experiments['sim_si'].linked_phases['si'].scale.free = True\n", "\n", "for line_segment in project_1.experiments['sim_si'].background:\n", " line_segment.y.free = True\n", "\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_0.free = True\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_1.free = True\n", "project_1.experiments['sim_si'].peak.broad_gauss_sigma_2.free = True\n", "project_1.experiments['sim_si'].peak.broad_mix_beta_0.free = True\n", "project_1.experiments['sim_si'].peak.broad_mix_beta_1.free = True\n", "project_1.experiments['sim_si'].peak.asym_alpha_0.free = True\n", "project_1.experiments['sim_si'].peak.asym_alpha_1.free = True" ] }, { "cell_type": "markdown", "id": "65", "metadata": {}, "source": [ "#### Show Free Parameters\n", "\n", "We can check which parameters are free to be refined by calling the\n", "`show_free_params` method of the `analysis` object of the project." ] }, { "cell_type": "markdown", "id": "66", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://easyscience.github.io/diffraction-lib/user-guide/first-steps/#available-parameters)\n", "for more details on how to\n", "- show all parameters of the project,\n", "- show all fittable parameters, and\n", "- show only free parameters of the project." ] }, { "cell_type": "code", "execution_count": 23, "id": "67", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.136489Z", "iopub.status.busy": "2026-01-06T13:53:13.136375Z", "iopub.status.idle": "2026-01-06T13:53:13.568945Z", "shell.execute_reply": "2026-01-06T13:53:13.568397Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFree parameters for both sample models \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🧩 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\u001b[1;34m and experiments \u001b[0m\u001b[1;34m(\u001b[0m\u001b[1;34m🔬 data blocks\u001b[0m\u001b[1;34m)\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparametervalueuncertaintyminmaxunits
1sim_silinked_phasessiscale1.00000-infinf
2sim_sipeakgauss_sigma_069498.00000-infinfµs²
3sim_sipeakgauss_sigma_1-55578.00000-infinfµs/Å
4sim_sipeakgauss_sigma_214560.00000-infinfµs²/Ų
5sim_sipeakmix_beta_00.00190-infinfdeg
6sim_sipeakmix_beta_10.01370-infinfdeg
7sim_sipeakasym_alpha_0-0.00550-infinf
8sim_sipeakasym_alpha_10.01470-infinf
9sim_sibackground1y0.01000-infinf
10sim_sibackground2y0.01000-infinf
11sim_sibackground3y0.01000-infinf
12sim_sibackground4y0.01000-infinf
13sim_sibackground5y0.01000-infinf
14sim_sibackground6y0.01000-infinf
15sim_sibackground7y0.01000-infinf
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.analysis.show_free_params()" ] }, { "cell_type": "markdown", "id": "68", "metadata": {}, "source": [ "#### Visualize Diffraction Patterns\n", "\n", "Before performing the fit, we can visually compare the measured\n", "diffraction pattern with the calculated diffraction pattern based on\n", "the initial parameters of the sample model and the instrument. This\n", "provides an indication of how well the initial parameters match the\n", "measured data. The `plot_meas_vs_calc` method of the project allows\n", "this comparison." ] }, { "cell_type": "code", "execution_count": 24, "id": "69", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.572248Z", "iopub.status.busy": "2026-01-06T13:53:13.572011Z", "iopub.status.idle": "2026-01-06T13:53:13.815810Z", "shell.execute_reply": "2026-01-06T13:53:13.810821Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas_vs_calc(expt_name='sim_si')" ] }, { "cell_type": "markdown", "id": "70", "metadata": {}, "source": [ "#### Run Fitting\n", "\n", "We can now perform the fit using the `fit` method of the `analysis`\n", "object of the project." ] }, { "cell_type": "markdown", "id": "71", "metadata": {}, "source": [ "📖 See\n", "[documentation](https://docs.easydiffraction.org/lib/user-guide/analysis-workflow/analysis/#perform-fit)\n", "for more details about the fitting process." ] }, { "cell_type": "code", "execution_count": 25, "id": "72", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:13.820445Z", "iopub.status.busy": "2026-01-06T13:53:13.819644Z", "iopub.status.idle": "2026-01-06T13:53:17.697449Z", "shell.execute_reply": "2026-01-06T13:53:17.696893Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing experiment 🔬 \u001b[0m\u001b[32m'sim_si'\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'single'\u001b[0m\u001b[1;34m fitting\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🚀 Starting fit process with \u001b[32m'lmfit \u001b[0m\u001b[32m(\u001b[0m\u001b[32mleastsq\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m change:\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 iterationχ²improvement [%]
1133.88
2194.1187.9% ↓
3352.3343.4% ↓
41162.31
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "🏆 Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m2.31\u001b[0m at iteration \u001b[1;36m115\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit results\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Success: \u001b[3;92mTrue\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⏱️ Fitting time: \u001b[1;36m2.86\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m2.31\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m6.87\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor squared \u001b[1m(\u001b[0mRf²\u001b[1m)\u001b[0m: \u001b[1;36m5.52\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m5.60\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Fitted parameters:\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1sim_silinked_phasessiscale1.00001.45400.007145.40 % ↑
2sim_sipeakgauss_sigma_069498.000087503.66037064.8898µs²25.91 % ↑
3sim_sipeakgauss_sigma_1-55578.0000-66953.22388731.0313µs/Å20.47 % ↑
4sim_sipeakgauss_sigma_214560.000016276.47952444.4594µs²/Ų11.79 % ↑
5sim_sipeakmix_beta_00.00190.00080.0001deg58.68 % ↓
6sim_sipeakmix_beta_10.01370.01900.0010deg38.42 % ↑
7sim_sipeakasym_alpha_0-0.0055-0.00660.000520.30 % ↑
8sim_sipeakasym_alpha_10.01470.01590.00077.87 % ↑
9sim_sibackground1y0.0100-0.00940.0068193.92 % ↓
10sim_sibackground2y0.01000.00510.001449.32 % ↓
11sim_sibackground3y0.01000.02250.0016125.05 % ↑
12sim_sibackground4y0.01000.02420.0014142.07 % ↑
13sim_sibackground5y0.01000.02470.0010147.08 % ↑
14sim_sibackground6y0.01000.02260.0017125.88 % ↑
15sim_sibackground7y0.01000.01920.004091.73 % ↑
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.analysis.fit()\n", "project_1.analysis.show_fit_results()" ] }, { "cell_type": "markdown", "id": "73", "metadata": {}, "source": [ "#### Check Fit Results\n", "\n", "You can see that the agreement between the measured and calculated\n", "diffraction patterns is now much improved and that the intensities of\n", "the calculated peaks align much better with the measured peaks. To\n", "check the quality of the fit numerically, we can look at the\n", "goodness-of-fit χ² value and the reliability R-factors. The χ² value\n", "is a measure of how well the calculated diffraction pattern matches\n", "the measured pattern, and it is calculated as the sum of the squared\n", "differences between the measured and calculated intensities, divided\n", "by the number of data points. Ideally, the χ² value should be close to\n", "1, indicating a good fit." ] }, { "cell_type": "markdown", "id": "74", "metadata": {}, "source": [ "#### Visualize Fit Results\n", "\n", "After the fit is completed, we can plot the comparison between the\n", "measured and calculated diffraction patterns again to see how well the\n", "fit improved the agreement between the two. The calculated diffraction\n", "pattern is now based on the refined parameters." ] }, { "cell_type": "code", "execution_count": 26, "id": "75", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:17.699656Z", "iopub.status.busy": "2026-01-06T13:53:17.699509Z", "iopub.status.idle": "2026-01-06T13:53:17.854719Z", "shell.execute_reply": "2026-01-06T13:53:17.854369Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas_vs_calc(expt_name='sim_si')" ] }, { "cell_type": "markdown", "id": "76", "metadata": {}, "source": [ "#### TOF vs d-spacing\n", "\n", "The diffraction pattern is typically analyzed and plotted in the\n", "time-of-flight (TOF) axis, which represents the time it takes for\n", "neutrons to travel from the sample to the detector. However, it is\n", "sometimes more convenient to visualize the diffraction pattern in the\n", "d-spacing axis, which represents the distance between planes in the\n", "crystal lattice.\n", "\n", "The conversion from d-spacing to TOF was already introduced in the\n", "data reduction notebook. As a reminder, the two are related through\n", "the instrument calibration parameters according to the equation:\n", "\n", "$$ \\text{TOF} = \\text{offset} + \\text{linear} \\cdot d + \\text{quad}\n", "\\cdot d^{2}, $$\n", "\n", "where `offset`, `linear`, and `quad` are calibration parameters.\n", "\n", "In our case, only the `linear` term is used (the\n", "`calib_d_to_tof_linear` parameter we set earlier). The `offset` and\n", "`quad` terms were not part of the data reduction and are therefore set\n", "to 0 by default.\n", "\n", "The `plot_meas_vs_calc` method of the project allows us to plot the\n", "measured and calculated diffraction patterns in the d-spacing axis by\n", "setting the `d_spacing` parameter to `True`." ] }, { "cell_type": "code", "execution_count": 27, "id": "77", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:17.856660Z", "iopub.status.busy": "2026-01-06T13:53:17.856528Z", "iopub.status.idle": "2026-01-06T13:53:18.019896Z", "shell.execute_reply": "2026-01-06T13:53:18.019142Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas_vs_calc(expt_name='sim_si', d_spacing=True)" ] }, { "cell_type": "markdown", "id": "78", "metadata": {}, "source": [ "As you can see, the calculated diffraction pattern now matches the\n", "measured pattern much more closely. Typically, additional experimental\n", "parameters are included in the refinement process to further improve\n", "the fit. In this example, the structural parameters are not refined\n", "because the Si crystal structure is a well-known standard reference\n", "used to calibrate both the instrument and the experimental setup. The\n", "refined experimental parameters obtained here will then be applied\n", "when fitting the crystal structures of other materials.\n", "\n", "In the next part of the notebook, we will move to a more advanced case\n", "and fit a more complex crystal structure: La₀.₅Ba₀.₅CoO₃ (LBCO).\n", "\n", "#### Save Project\n", "\n", "Before moving on, we can save the project to disk for later use. This\n", "will preserve the entire project structure, including experiments,\n", "sample models, and fitting results. The project is saved into a\n", "directory specified by the `dir_path` attribute of the project object." ] }, { "cell_type": "code", "execution_count": 28, "id": "79", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.023743Z", "iopub.status.busy": "2026-01-06T13:53:18.022030Z", "iopub.status.idle": "2026-01-06T13:53:18.077352Z", "shell.execute_reply": "2026-01-06T13:53:18.077035Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mSaving project 📦 \u001b[0m\u001b[32m'reference'\u001b[0m\u001b[1;34m to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[35m/Users/runner/work/diffraction-lib/diffraction-lib/tutorials/\u001b[0m\u001b[95mpowder_diffraction_Si\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 project.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 sample_models\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 si.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 experiments\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 sim_si.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 analysis.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "└── 📄 summary.cif\n" ] } ], "source": [ "project_1.save_as(dir_path='powder_diffraction_Si')" ] }, { "cell_type": "markdown", "id": "80", "metadata": {}, "source": [ "## 💪 Exercise: Complex Fit – LBCO\n", "\n", "Now that you have a basic understanding of the fitting process, we\n", "will undertake a more complex fit of the La₀.₅Ba₀.₅CoO₃ (LBCO) crystal\n", "structure using simulated powder diffraction data from the data\n", "reduction notebook.\n", "\n", "You can use the same approach as in the previous part of the notebook,\n", "but this time we will refine a more complex crystal structure LBCO\n", "with multiple atoms in the unit cell.\n", "\n", "### 📦 Exercise 1: Create a Project\n", "\n", "Create a new project for the LBCO fit." ] }, { "cell_type": "markdown", "id": "81", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "82", "metadata": {}, "source": [ "You can use the same approach as in the previous part of the notebook,\n", "but this time we will create a new project for the LBCO fit." ] }, { "cell_type": "markdown", "id": "83", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 29, "id": "84", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.079081Z", "iopub.status.busy": "2026-01-06T13:53:18.078965Z", "iopub.status.idle": "2026-01-06T13:53:18.095778Z", "shell.execute_reply": "2026-01-06T13:53:18.095273Z" } }, "outputs": [], "source": [ "project_2 = ed.Project(name='main')\n", "project_2.info.title = 'La0.5Ba0.5CoO3 Fit'\n", "project_2.info.description = 'Fitting simulated powder diffraction pattern of La0.5Ba0.5CoO3.'" ] }, { "cell_type": "markdown", "id": "85", "metadata": {}, "source": [ "### 🔬 Exercise 2: Define an Experiment\n", "\n", "#### Exercise 2.1: Create an Experiment\n", "\n", "Create an experiment within the new project and load the reduced\n", "diffraction pattern for LBCO." ] }, { "cell_type": "markdown", "id": "86", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "87", "metadata": {}, "source": [ "You can use the same approach as in the previous part of the notebook,\n", "but this time you need to use the data file for LBCO." ] }, { "cell_type": "markdown", "id": "88", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 30, "id": "89", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.097707Z", "iopub.status.busy": "2026-01-06T13:53:18.097524Z", "iopub.status.idle": "2026-01-06T13:53:18.365758Z", "shell.execute_reply": "2026-01-06T13:53:18.365418Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mGetting data\u001b[0m\u001b[1;34m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Data #\u001b[1;36m18\u001b[0m: La0.5Ba0.5CoO3 + Si, McStas simulation, DMSC Summer School \u001b[1;36m2025\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Data #\u001b[1;36m18\u001b[0m downloaded to \u001b[32m'data/ed-18.xye'\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mData loaded successfully\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Experiment 🔬 \u001b[32m'sim_lbco'\u001b[0m. Number of data points: \u001b[1;36m900\u001b[0m\n" ] } ], "source": [ "data_dir = 'data'\n", "file_name = 'reduced_LBCO.xye'\n", "lbco_xye_path = f'{data_dir}/{file_name}'\n", "\n", "# Uncomment the following line if your data reduction failed and the\n", "# reduced data file is missing.\n", "lbco_xye_path = ed.download_data(id=18, destination=data_dir)\n", "\n", "project_2.experiments.add(\n", " name='sim_lbco',\n", " data_path=lbco_xye_path,\n", " sample_form='powder',\n", " beam_mode='time-of-flight',\n", " radiation_probe='neutron',\n", ")" ] }, { "cell_type": "markdown", "id": "90", "metadata": {}, "source": [ "#### Exercise 2.1: Inspect Measured Data\n", "\n", "Check the measured data of the LBCO experiment. Are there any peaks\n", "with the shape similar to those excluded in the Si fit? If so, exclude\n", "them from this analysis as well." ] }, { "cell_type": "markdown", "id": "91", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "92", "metadata": {}, "source": [ "You can use the `plot_meas` method of the project to visualize the\n", "measured diffraction pattern. You can also use the `excluded_regions`\n", "attribute of the experiment to exclude specific regions from the\n", "analysis as we did in the previous part of the notebook." ] }, { "cell_type": "markdown", "id": "93", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 31, "id": "94", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.367268Z", "iopub.status.busy": "2026-01-06T13:53:18.367138Z", "iopub.status.idle": "2026-01-06T13:53:18.411835Z", "shell.execute_reply": "2026-01-06T13:53:18.411457Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Warning: No linked phases defined. Returning empty pattern.\n" ] }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Warning: No linked phases defined. Returning empty pattern.\n" ] }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas(expt_name='sim_lbco')\n", "\n", "project_2.experiments['sim_lbco'].excluded_regions.add(id='1', start=0, end=55000)\n", "project_2.experiments['sim_lbco'].excluded_regions.add(id='2', start=105500, end=200000)\n", "\n", "project_2.plot_meas(expt_name='sim_lbco')" ] }, { "cell_type": "markdown", "id": "95", "metadata": {}, "source": [ "#### Exercise 2.2: Set Instrument Parameters\n", "\n", "Set the instrument parameters for the LBCO experiment." ] }, { "cell_type": "markdown", "id": "96", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "97", "metadata": {}, "source": [ "Use the values from the data reduction process for the LBCO and\n", "follow the same approach as in the previous part of the notebook." ] }, { "cell_type": "markdown", "id": "98", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 32, "id": "99", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.413487Z", "iopub.status.busy": "2026-01-06T13:53:18.413351Z", "iopub.status.idle": "2026-01-06T13:53:18.420576Z", "shell.execute_reply": "2026-01-06T13:53:18.419882Z" } }, "outputs": [], "source": [ "project_2.experiments['sim_lbco'].instrument.setup_twotheta_bank = ed.get_value_from_xye_header(\n", " lbco_xye_path, 'two_theta'\n", ")\n", "project_2.experiments['sim_lbco'].instrument.calib_d_to_tof_linear = ed.get_value_from_xye_header(\n", " lbco_xye_path, 'DIFC'\n", ")" ] }, { "cell_type": "markdown", "id": "100", "metadata": {}, "source": [ "#### Exercise 2.3: Set Peak Profile Parameters\n", "\n", "Set the peak profile parameters for the LBCO experiment." ] }, { "cell_type": "markdown", "id": "101", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "102", "metadata": {}, "source": [ "Use the values from the\n", "previous part of the notebook. You can either manually copy the values\n", "from the Si fit or use the `value` attribute of the parameters from\n", "the Si experiment to set the initial values for the LBCO experiment.\n", "This will help us to have a good starting point for the fit." ] }, { "cell_type": "markdown", "id": "103", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 33, "id": "104", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.422812Z", "iopub.status.busy": "2026-01-06T13:53:18.422669Z", "iopub.status.idle": "2026-01-06T13:53:18.433002Z", "shell.execute_reply": "2026-01-06T13:53:18.432335Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mPeak profile type for experiment \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "pseudo-voigt * ikeda-carpenter\n" ] } ], "source": [ "# # Create a reference to the peak profile parameters from the Si\n", "sim_si_peak = project_1.experiments['sim_si'].peak\n", "project_2.experiments['sim_lbco'].peak_profile_type = 'pseudo-voigt * ikeda-carpenter'\n", "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_0 = sim_si_peak.broad_gauss_sigma_0.value\n", "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_1 = sim_si_peak.broad_gauss_sigma_1.value\n", "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_2 = sim_si_peak.broad_gauss_sigma_2.value\n", "project_2.experiments['sim_lbco'].peak.broad_mix_beta_0 = sim_si_peak.broad_mix_beta_0.value\n", "project_2.experiments['sim_lbco'].peak.broad_mix_beta_1 = sim_si_peak.broad_mix_beta_1.value\n", "project_2.experiments['sim_lbco'].peak.asym_alpha_0 = sim_si_peak.asym_alpha_0.value\n", "project_2.experiments['sim_lbco'].peak.asym_alpha_1 = sim_si_peak.asym_alpha_1.value" ] }, { "cell_type": "markdown", "id": "105", "metadata": {}, "source": [ "#### Exercise 2.4: Set Background\n", "\n", "Set the background points for the LBCO experiment. What would you\n", "suggest as the initial intensity value for the background points?" ] }, { "cell_type": "markdown", "id": "106", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "107", "metadata": {}, "source": [ "Use the same approach as in the previous part of the notebook, but\n", "this time you need to set the background points for the LBCO\n", "experiment. You can zoom in on the measured diffraction pattern to\n", "determine the approximate background level." ] }, { "cell_type": "markdown", "id": "108", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 34, "id": "109", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.435309Z", "iopub.status.busy": "2026-01-06T13:53:18.435057Z", "iopub.status.idle": "2026-01-06T13:53:18.441854Z", "shell.execute_reply": "2026-01-06T13:53:18.441008Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mBackground type for experiment \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "line-segment\n" ] } ], "source": [ "project_2.experiments['sim_lbco'].background_type = 'line-segment'\n", "project_2.experiments['sim_lbco'].background.add(id='1', x=50000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='2', x=60000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='3', x=70000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='4', x=80000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='5', x=90000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='6', x=100000, y=0.2)\n", "project_2.experiments['sim_lbco'].background.add(id='7', x=110000, y=0.2)" ] }, { "cell_type": "markdown", "id": "110", "metadata": {}, "source": [ "### 🧩 Exercise 3: Define a Sample Model – LBCO\n", "\n", "The LBSO structure is not as simple as the Si model, as it contains\n", "multiple atoms in the unit cell. It is not in COD, so we give you the\n", "structural parameters in CIF format to create the sample model.\n", "\n", "Note that those parameters are not necessarily the most accurate ones,\n", "but they are a good starting point for the fit. The aim of the study\n", "is to refine the LBCO lattice parameters." ] }, { "cell_type": "markdown", "id": "111", "metadata": {}, "source": [ "```\n", "data_lbco\n", "\n", "_space_group.name_H-M_alt \"P m -3 m\"\n", "_space_group.IT_coordinate_system_code 1\n", "\n", "_cell.length_a 3.89\n", "_cell.length_b 3.89\n", "_cell.length_c 3.89\n", "_cell.angle_alpha 90.0\n", "_cell.angle_beta 90.0\n", "_cell.angle_gamma 90.0\n", "\n", "loop_\n", "_atom_site.label\n", "_atom_site.type_symbol\n", "_atom_site.fract_x\n", "_atom_site.fract_y\n", "_atom_site.fract_z\n", "_atom_site.wyckoff_letter\n", "_atom_site.occupancy\n", "_atom_site.ADP_type\n", "_atom_site.B_iso_or_equiv\n", "La La 0.0 0.0 0.0 a 0.5 Biso 0.95\n", "Ba Ba 0.0 0.0 0.0 a 0.5 Biso 0.95\n", "Co Co 0.5 0.5 0.5 b 1.0 Biso 0.80\n", "O O 0.0 0.5 0.5 c 1.0 Biso 1.66\n", "```" ] }, { "cell_type": "markdown", "id": "112", "metadata": {}, "source": [ "Note that the `occupancy` of the La and Ba atoms is 0.5\n", "and those atoms are located in the same position (0, 0, 0) in the unit\n", "cell. This means that an extra attribute `occupancy` needs to be set\n", "for those atoms later in the sample model.\n", "\n", "We model the La/Ba site using the virtual crystal approximation. In\n", "this approach, the scattering is taken as a weighted average of La and\n", "Ba. This reproduces the average diffraction pattern well but does not\n", "capture certain real-world effects.\n", "\n", "The edge cases are:\n", "- **Random distribution**. La and Ba atoms are placed randomly. The\n", " Bragg peaks still match the average structure, but the pattern also\n", " shows extra background (diffuse scattering) between the peaks, but\n", " this is usually neglected in the analysis.\n", "- **Perfect ordering**. La and Ba arrange themselves in a regular\n", " pattern, creating a larger repeating unit. This gives rise to extra\n", " peaks (\"superlattice reflections\") and changes the intensity of\n", " some existing peaks.\n", "- **Virtual crystal approximation (our model)**. We replace the site\n", " with a single \"virtual atom\" that averages La and Ba. This gives\n", " the correct average Bragg peaks but leaves out the extra background\n", " of the random case and the extra peaks of the ordered case." ] }, { "cell_type": "markdown", "id": "113", "metadata": {}, "source": [ "#### Exercise 3.1: Create Sample Model\n", "\n", "Add a sample model for LBCO to the project. The sample model\n", "parameters will be set in the next exercises." ] }, { "cell_type": "markdown", "id": "114", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "115", "metadata": {}, "source": [ "You can use the same approach as in the previous part of the notebook,\n", "but this time you need to use the model name corresponding to the LBCO\n", "structure, e.g. 'lbco'." ] }, { "cell_type": "markdown", "id": "116", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 35, "id": "117", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.443931Z", "iopub.status.busy": "2026-01-06T13:53:18.443801Z", "iopub.status.idle": "2026-01-06T13:53:18.450539Z", "shell.execute_reply": "2026-01-06T13:53:18.449320Z" } }, "outputs": [], "source": [ "project_2.sample_models.add(name='lbco')" ] }, { "cell_type": "markdown", "id": "118", "metadata": {}, "source": [ "#### Exercise 3.2: Set Space Group\n", "\n", "Set the space group for the LBCO sample model." ] }, { "cell_type": "markdown", "id": "119", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "120", "metadata": {}, "source": [ "Use the space group name and IT coordinate system code from the CIF\n", "data." ] }, { "cell_type": "markdown", "id": "121", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 36, "id": "122", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.453425Z", "iopub.status.busy": "2026-01-06T13:53:18.453125Z", "iopub.status.idle": "2026-01-06T13:53:18.456198Z", "shell.execute_reply": "2026-01-06T13:53:18.455472Z" } }, "outputs": [], "source": [ "project_2.sample_models['lbco'].space_group.name_h_m = 'P m -3 m'\n", "project_2.sample_models['lbco'].space_group.it_coordinate_system_code = '1'" ] }, { "cell_type": "markdown", "id": "123", "metadata": {}, "source": [ "#### Exercise 3.3: Set Lattice Parameters\n", "\n", "Set the lattice parameters for the LBCO sample model." ] }, { "cell_type": "markdown", "id": "124", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "125", "metadata": {}, "source": [ "Use the lattice parameters from the CIF data." ] }, { "cell_type": "markdown", "id": "126", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 37, "id": "127", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.462365Z", "iopub.status.busy": "2026-01-06T13:53:18.462194Z", "iopub.status.idle": "2026-01-06T13:53:18.465510Z", "shell.execute_reply": "2026-01-06T13:53:18.464705Z" } }, "outputs": [], "source": [ "project_2.sample_models['lbco'].cell.length_a = 3.88" ] }, { "cell_type": "markdown", "id": "128", "metadata": {}, "source": [ "#### Exercise 3.4: Set Atom Sites\n", "\n", "Set the atom sites for the LBCO sample model." ] }, { "cell_type": "markdown", "id": "129", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "130", "metadata": {}, "source": [ "Use the atom sites from the CIF data. You can use the `add` method of\n", "the `atom_sites` attribute of the sample model to add the atom sites." ] }, { "cell_type": "markdown", "id": "131", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 38, "id": "132", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.467724Z", "iopub.status.busy": "2026-01-06T13:53:18.467592Z", "iopub.status.idle": "2026-01-06T13:53:18.476262Z", "shell.execute_reply": "2026-01-06T13:53:18.475718Z" } }, "outputs": [], "source": [ "project_2.sample_models['lbco'].atom_sites.add(\n", " label='La',\n", " type_symbol='La',\n", " fract_x=0,\n", " fract_y=0,\n", " fract_z=0,\n", " wyckoff_letter='a',\n", " b_iso=0.95,\n", " occupancy=0.5,\n", ")\n", "project_2.sample_models['lbco'].atom_sites.add(\n", " label='Ba',\n", " type_symbol='Ba',\n", " fract_x=0,\n", " fract_y=0,\n", " fract_z=0,\n", " wyckoff_letter='a',\n", " b_iso=0.95,\n", " occupancy=0.5,\n", ")\n", "project_2.sample_models['lbco'].atom_sites.add(\n", " label='Co',\n", " type_symbol='Co',\n", " fract_x=0.5,\n", " fract_y=0.5,\n", " fract_z=0.5,\n", " wyckoff_letter='b',\n", " b_iso=0.80,\n", ")\n", "project_2.sample_models['lbco'].atom_sites.add(\n", " label='O',\n", " type_symbol='O',\n", " fract_x=0,\n", " fract_y=0.5,\n", " fract_z=0.5,\n", " wyckoff_letter='c',\n", " b_iso=1.66,\n", ")" ] }, { "cell_type": "markdown", "id": "133", "metadata": {}, "source": [ "### 🔗 Exercise 4: Assign Sample Model to Experiment\n", "\n", "Now assign the LBCO sample model to the experiment created above." ] }, { "cell_type": "markdown", "id": "134", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "135", "metadata": {}, "source": [ "Use the `linked_phases` attribute of the experiment to link the sample\n", "model." ] }, { "cell_type": "markdown", "id": "136", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 39, "id": "137", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.478476Z", "iopub.status.busy": "2026-01-06T13:53:18.478278Z", "iopub.status.idle": "2026-01-06T13:53:18.485346Z", "shell.execute_reply": "2026-01-06T13:53:18.484623Z" } }, "outputs": [], "source": [ "project_2.experiments['sim_lbco'].linked_phases.add(id='lbco', scale=1.0)" ] }, { "cell_type": "markdown", "id": "138", "metadata": {}, "source": [ "### 🚀 Exercise 5: Analyze and Fit the Data\n", "\n", "#### Exercise 5.1: Set Fit Parameters\n", "\n", "Select the initial set of parameters to be refined during the fitting\n", "process." ] }, { "cell_type": "markdown", "id": "139", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "140", "metadata": {}, "source": [ "You can start with the scale factor and the background points, as in\n", "the Si fit." ] }, { "cell_type": "markdown", "id": "141", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 40, "id": "142", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.488277Z", "iopub.status.busy": "2026-01-06T13:53:18.488111Z", "iopub.status.idle": "2026-01-06T13:53:18.494927Z", "shell.execute_reply": "2026-01-06T13:53:18.494474Z" } }, "outputs": [], "source": [ "project_2.experiments['sim_lbco'].linked_phases['lbco'].scale.free = True\n", "\n", "for line_segment in project_2.experiments['sim_lbco'].background:\n", " line_segment.y.free = True" ] }, { "cell_type": "markdown", "id": "143", "metadata": {}, "source": [ "#### Exercise 5.2: Run Fitting\n", "\n", "Visualize the measured and calculated diffraction patterns before\n", "fitting and then run the fitting process." ] }, { "cell_type": "markdown", "id": "144", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "145", "metadata": {}, "source": [ "Use the `plot_meas_vs_calc` method of the project to visualize the\n", "measured and calculated diffraction patterns before fitting. Then, use\n", "the `fit` method of the `analysis` object of the project to perform\n", "the fitting process." ] }, { "cell_type": "markdown", "id": "146", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 41, "id": "147", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:18.496938Z", "iopub.status.busy": "2026-01-06T13:53:18.496829Z", "iopub.status.idle": "2026-01-06T13:53:20.721107Z", "shell.execute_reply": "2026-01-06T13:53:20.720645Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing experiment 🔬 \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'single'\u001b[0m\u001b[1;34m fitting\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🚀 Starting fit process with \u001b[32m'lmfit \u001b[0m\u001b[32m(\u001b[0m\u001b[32mleastsq\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m change:\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 iterationχ²improvement [%]
11115.86
21270.2639.4% ↓
32270.26
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "🏆 Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m70.26\u001b[0m at iteration \u001b[1;36m12\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit results\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Success: \u001b[3;92mTrue\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⏱️ Fitting time: \u001b[1;36m0.93\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m70.26\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m38.27\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor squared \u001b[1m(\u001b[0mRf²\u001b[1m)\u001b[0m: \u001b[1;36m64.53\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m66.00\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Fitted parameters:\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1sim_lbcolinked_phaseslbcoscale1.00002.58640.1352158.64 % ↑
2sim_lbcobackground1y0.20000.29740.189348.69 % ↑
3sim_lbcobackground2y0.20000.27450.038737.23 % ↑
4sim_lbcobackground3y0.20000.28050.025140.25 % ↑
5sim_lbcobackground4y0.20000.23590.019317.93 % ↑
6sim_lbcobackground5y0.20000.26430.013832.15 % ↑
7sim_lbcobackground6y0.20000.25110.016025.54 % ↑
8sim_lbcobackground7y0.20000.21170.05765.86 % ↑
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n", "\n", "project_2.analysis.fit()\n", "project_2.analysis.show_fit_results()" ] }, { "cell_type": "markdown", "id": "148", "metadata": {}, "source": [ "#### Exercise 5.3: Find the Misfit in the Fit\n", "\n", "Visualize the measured and calculated diffraction patterns after the\n", "fit. As you can see, the fit shows noticeable discrepancies. If you\n", "zoom in on different regions of the pattern, you will observe that all\n", "the calculated peaks are shifted to the left.\n", "\n", "What could be the reason for the misfit?" ] }, { "cell_type": "markdown", "id": "149", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "150", "metadata": {}, "source": [ "Consider the following options:\n", "1. The conversion parameters from TOF to d-spacing are not correct.\n", "2. The lattice parameters of the LBCO phase are not correct.\n", "3. The peak profile parameters are not correct.\n", "4. The background points are not correct." ] }, { "cell_type": "markdown", "id": "151", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "markdown", "id": "152", "metadata": {}, "source": [ "\n", "1. ❌ The conversion parameters from TOF to d-spacing were set based\n", "on the data reduction step. While they are specific to each dataset\n", "and thus differ from those used for the Si data, the full reduction\n", "workflow has already been validated with the Si fit. Therefore, they\n", "are not the cause of the misfit in this case.\n", "2. ✅ The lattice parameters of the LBCO phase were set based on the\n", "CIF data, which is a good starting point, but they are not necessarily\n", "as accurate as needed for the fit. The lattice parameters may need to\n", "be refined.\n", "3. ❌ The peak profile parameters do not change the position of the\n", "peaks, but rather their shape.\n", "4. ❌ The background points affect the background level, but not the\n", "peak positions." ] }, { "cell_type": "code", "execution_count": 42, "id": "153", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:20.723069Z", "iopub.status.busy": "2026-01-06T13:53:20.722933Z", "iopub.status.idle": "2026-01-06T13:53:20.965492Z", "shell.execute_reply": "2026-01-06T13:53:20.965075Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas_vs_calc(expt_name='sim_lbco')" ] }, { "cell_type": "markdown", "id": "154", "metadata": {}, "source": [ "#### Exercise 5.4: Refine the LBCO Lattice Parameter\n", "\n", "To improve the fit, refine the lattice parameters of the LBCO phase." ] }, { "cell_type": "markdown", "id": "155", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "156", "metadata": {}, "source": [ "To achieve this, we will set the `free` attribute of the `length_a`\n", "parameter of the LBCO cell to `True`.\n", "\n", "LBCO has a cubic crystal structure (space group `P m -3 m`), which\n", "means that `length_b` and `length_c` are constrained to be equal to\n", "`length_a`. Therefore, only `length_a` needs to be refined; the other\n", "two will be updated automatically. All cell angles are fixed at 90°,\n", "so they do not require refinement." ] }, { "cell_type": "markdown", "id": "157", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 43, "id": "158", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:20.972075Z", "iopub.status.busy": "2026-01-06T13:53:20.971430Z", "iopub.status.idle": "2026-01-06T13:53:24.412148Z", "shell.execute_reply": "2026-01-06T13:53:24.411558Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing experiment 🔬 \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'single'\u001b[0m\u001b[1;34m fitting\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🚀 Starting fit process with \u001b[32m'lmfit \u001b[0m\u001b[32m(\u001b[0m\u001b[32mleastsq\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m change:\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 iterationχ²improvement [%]
1170.43
21311.6183.5% ↓
3235.0756.3% ↓
4334.844.6% ↓
5654.84
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "🏆 Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m4.84\u001b[0m at iteration \u001b[1;36m53\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit results\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Success: \u001b[3;92mTrue\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⏱️ Fitting time: \u001b[1;36m2.13\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m4.84\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m6.85\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor squared \u001b[1m(\u001b[0mRf²\u001b[1m)\u001b[0m: \u001b[1;36m6.43\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m5.67\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Fitted parameters:\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.88003.89220.0001Å0.31 % ↑
2sim_lbcolinked_phaseslbcoscale2.58644.87050.046488.31 % ↑
3sim_lbcobackground1y0.29740.27450.04977.70 % ↓
4sim_lbcobackground2y0.27450.25860.01015.77 % ↓
5sim_lbcobackground3y0.28050.25920.00667.58 % ↓
6sim_lbcobackground4y0.23590.24120.00512.27 % ↑
7sim_lbcobackground5y0.26430.24550.00367.10 % ↓
8sim_lbcobackground6y0.25110.23790.00425.25 % ↓
9sim_lbcobackground7y0.21170.20920.01511.20 % ↓
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.sample_models['lbco'].cell.length_a.free = True\n", "\n", "project_2.analysis.fit()\n", "project_2.analysis.show_fit_results()\n", "\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco')" ] }, { "cell_type": "markdown", "id": "159", "metadata": {}, "source": [ "One of the main goals of this study was to refine the lattice\n", "parameter of the LBCO phase. As shown in the updated fit results, the\n", "overall fit has improved significantly, even though the change in cell\n", "length is less than 1% of the initial value. This demonstrates how\n", "even a small adjustment to the lattice parameter can have a\n", "substantial impact on the quality of the fit." ] }, { "cell_type": "markdown", "id": "160", "metadata": {}, "source": [ "#### Exercise 5.5: Visualize the Fit Results in d-spacing\n", "\n", "Plot measured vs calculated diffraction patterns in d-spacing instead\n", "of TOF." ] }, { "cell_type": "markdown", "id": "161", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "162", "metadata": {}, "source": [ "Use the `plot_meas_vs_calc` method of the project and set the\n", "`d_spacing` parameter to `True`." ] }, { "cell_type": "markdown", "id": "163", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 44, "id": "164", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:24.414377Z", "iopub.status.busy": "2026-01-06T13:53:24.414240Z", "iopub.status.idle": "2026-01-06T13:53:24.610749Z", "shell.execute_reply": "2026-01-06T13:53:24.610289Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', d_spacing=True)" ] }, { "cell_type": "markdown", "id": "165", "metadata": {}, "source": [ "#### Exercise 5.6: Refine the Peak Profile Parameters\n", "\n", "As you can see, the fit is now relatively good and the peak positions\n", "are much closer to the measured data.\n", "\n", "The peak profile parameters were not refined, and their starting\n", "values were set based on the previous fit of the Si standard sample.\n", "Although these starting values are reasonable and provide a good\n", "starting point for the fit, they are not necessarily optimal for the\n", "LBCO phase. This can be seen while inspecting the individual peaks in\n", "the diffraction pattern. For example, the calculated curve does not\n", "perfectly describe the peak at about 1.38 Å, as can be seen below:" ] }, { "cell_type": "code", "execution_count": 45, "id": "166", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:24.612538Z", "iopub.status.busy": "2026-01-06T13:53:24.612435Z", "iopub.status.idle": "2026-01-06T13:53:24.793475Z", "shell.execute_reply": "2026-01-06T13:53:24.792985Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', d_spacing=True, x_min=1.35, x_max=1.40)" ] }, { "cell_type": "markdown", "id": "167", "metadata": {}, "source": [ "The peak profile parameters are determined based on both the\n", "instrument and the sample characteristics, so they can vary when\n", "analyzing different samples on the same instrument. Therefore, it is\n", "better to refine them as well.\n", "\n", "Select the peak profile parameters to be refined during the fitting\n", "process." ] }, { "cell_type": "markdown", "id": "168", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "169", "metadata": {}, "source": [ "You can set the `free` attribute of the peak profile parameters to\n", "`True` to allow the fitting process to adjust them. You can use the\n", "same approach as in the previous part of the notebook, but this time\n", "you will refine the peak profile parameters of the LBCO phase." ] }, { "cell_type": "markdown", "id": "170", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 46, "id": "171", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:24.795307Z", "iopub.status.busy": "2026-01-06T13:53:24.795132Z", "iopub.status.idle": "2026-01-06T13:53:33.326530Z", "shell.execute_reply": "2026-01-06T13:53:33.324754Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing experiment 🔬 \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'single'\u001b[0m\u001b[1;34m fitting\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🚀 Starting fit process with \u001b[32m'lmfit \u001b[0m\u001b[32m(\u001b[0m\u001b[32mleastsq\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m change:\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 iterationχ²improvement [%]
114.92
2204.518.3% ↓
33274.49
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "🏆 Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m4.49\u001b[0m at iteration \u001b[1;36m326\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit results\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Success: \u001b[3;92mTrue\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⏱️ Fitting time: \u001b[1;36m7.35\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m4.49\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m5.67\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor squared \u001b[1m(\u001b[0mRf²\u001b[1m)\u001b[0m: \u001b[1;36m4.91\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m4.13\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Fitted parameters:\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.89223.89150.0003Å0.02 % ↓
2sim_lbcolinked_phaseslbcoscale4.87054.82950.04650.84 % ↓
3sim_lbcopeakgauss_sigma_087503.660390223.677315782.1219µs²3.11 % ↑
4sim_lbcopeakgauss_sigma_1-66953.2238-80933.702919529.4986µs/Å20.88 % ↑
5sim_lbcopeakgauss_sigma_216276.479521634.70786015.0274µs²/Ų32.92 % ↑
6sim_lbcopeakmix_beta_00.00080.00230.0005deg193.55 % ↑
7sim_lbcopeakmix_beta_10.01900.01240.0021deg34.83 % ↓
8sim_lbcopeakasym_alpha_0-0.0066-0.00480.001728.16 % ↓
9sim_lbcopeakasym_alpha_10.01590.01370.002313.62 % ↓
10sim_lbcobackground1y0.27450.27500.04790.18 % ↑
11sim_lbcobackground2y0.25860.26060.00980.76 % ↑
12sim_lbcobackground3y0.25920.25920.00640.03 % ↓
13sim_lbcobackground4y0.24120.24390.00501.12 % ↑
14sim_lbcobackground5y0.24550.24580.00350.09 % ↑
15sim_lbcobackground6y0.23790.23870.00400.35 % ↑
16sim_lbcobackground7y0.20920.20840.01460.35 % ↓
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_0.free = True\n", "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_1.free = True\n", "project_2.experiments['sim_lbco'].peak.broad_gauss_sigma_2.free = True\n", "project_2.experiments['sim_lbco'].peak.broad_mix_beta_0.free = True\n", "project_2.experiments['sim_lbco'].peak.broad_mix_beta_1.free = True\n", "project_2.experiments['sim_lbco'].peak.asym_alpha_0.free = True\n", "project_2.experiments['sim_lbco'].peak.asym_alpha_1.free = True\n", "\n", "project_2.analysis.fit()\n", "project_2.analysis.show_fit_results()\n", "\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco', d_spacing=True, x_min=1.35, x_max=1.40)" ] }, { "cell_type": "markdown", "id": "172", "metadata": {}, "source": [ "#### Exercise 5.7: Find Undefined Features\n", "\n", "After refining the lattice parameter and the peak profile parameters,\n", "the fit is significantly improved, but inspect the diffraction pattern\n", "again. Are you noticing anything undefined?" ] }, { "cell_type": "markdown", "id": "173", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "174", "metadata": {}, "source": [ "While the fit is now significantly better, there are still some\n", "unexplained peaks in the diffraction pattern. These peaks are not\n", "accounted for by the LBCO phase. For example, if you zoom in on the\n", "region around 1.6 Å (or 95,000 μs), you will notice that the rightmost\n", "peak is not explained by the LBCO phase at all." ] }, { "cell_type": "markdown", "id": "175", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 47, "id": "176", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:33.329571Z", "iopub.status.busy": "2026-01-06T13:53:33.329390Z", "iopub.status.idle": "2026-01-06T13:53:33.516076Z", "shell.execute_reply": "2026-01-06T13:53:33.515671Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x_min=1.53, x_max=1.7, d_spacing=True)" ] }, { "cell_type": "markdown", "id": "177", "metadata": {}, "source": [ "#### Exercise 5.8: Identify the Cause of the Unexplained Peaks\n", "\n", "Analyze the residual peaks that remain after refining the LBCO phase\n", "and the peak-profile parameters. Based on their positions and\n", "characteristics, decide which potential cause best explains the\n", "misfit." ] }, { "cell_type": "markdown", "id": "178", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "179", "metadata": {}, "source": [ "Consider the following options:\n", "1. The LBCO phase is not correctly modeled.\n", "2. The LBCO phase is not the only phase present in the sample.\n", "3. The data reduction process introduced artifacts.\n", "4. The studied sample is not LBCO, but rather a different phase." ] }, { "cell_type": "markdown", "id": "180", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "markdown", "id": "181", "metadata": {}, "source": [ "1. ❌ In principle, this could be the case, as sometimes the presence\n", "of extra peaks in the diffraction pattern can indicate lower symmetry\n", "than the one used in the model, or that the model is not complete.\n", "However, in this case, the LBCO phase is correctly modeled based on\n", "the CIF data.\n", "2. ✅ The unexplained peaks are due to the presence of an impurity\n", "phase in the sample, which is not included in the current model.\n", "3. ❌ The data reduction process is not likely to introduce such\n", "specific peaks, as it is tested and verified in the previous part of\n", "the notebook.\n", "4. ❌ This could also be the case in real experiments, but in this\n", "case, we know that the sample is LBCO, as it was simulated based on\n", "the CIF data." ] }, { "cell_type": "markdown", "id": "182", "metadata": {}, "source": [ "#### Exercise 5.9: Identify the impurity phase\n", "\n", "Use the positions of the unexplained peaks to identify the most likely\n", "secondary phase present in the sample." ] }, { "cell_type": "markdown", "id": "183", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "184", "metadata": {}, "source": [ "Check the positions of the unexplained peaks in the diffraction\n", "pattern. Compare them with the known diffraction patterns in the\n", "previous part of the notebook." ] }, { "cell_type": "markdown", "id": "185", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "markdown", "id": "186", "metadata": {}, "source": [ "The unexplained peaks are likely due to the presence of a small amount\n", "of Si in the LBCO sample. In real experiments, it might happen, e.g.,\n", "because the sample holder was not cleaned properly after the Si\n", "experiment.\n", "\n", "You can visalize both the patterns of the Si and LBCO phases to\n", "confirm this hypothesis." ] }, { "cell_type": "code", "execution_count": 48, "id": "187", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:33.518228Z", "iopub.status.busy": "2026-01-06T13:53:33.518073Z", "iopub.status.idle": "2026-01-06T13:53:33.872654Z", "shell.execute_reply": "2026-01-06T13:53:33.872248Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_1.plot_meas_vs_calc(expt_name='sim_si', x_min=1, x_max=1.7, d_spacing=True)\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x_min=1, x_max=1.7, d_spacing=True)" ] }, { "cell_type": "markdown", "id": "188", "metadata": {}, "source": [ "#### Exercise 5.10: Create a Second Sample Model – Si as Impurity\n", "\n", "Create a second sample model for the Si phase, which is the impurity\n", "phase identified in the previous step. Link this sample model to the\n", "LBCO experiment." ] }, { "cell_type": "markdown", "id": "189", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "190", "metadata": {}, "source": [ "You can use the same approach as in the previous part of the notebook,\n", "but this time you need to create a sample model for Si and link it to\n", "the LBCO experiment." ] }, { "cell_type": "markdown", "id": "191", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 49, "id": "192", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:33.876619Z", "iopub.status.busy": "2026-01-06T13:53:33.876341Z", "iopub.status.idle": "2026-01-06T13:53:33.888512Z", "shell.execute_reply": "2026-01-06T13:53:33.887575Z" } }, "outputs": [], "source": [ "# Set Space Group\n", "project_2.sample_models.add(name='si')\n", "project_2.sample_models['si'].space_group.name_h_m = 'F d -3 m'\n", "project_2.sample_models['si'].space_group.it_coordinate_system_code = '2'\n", "\n", "# Set Lattice Parameters\n", "project_2.sample_models['si'].cell.length_a = 5.43\n", "\n", "# Set Atom Sites\n", "project_2.sample_models['si'].atom_sites.add(\n", " label='Si',\n", " type_symbol='Si',\n", " fract_x=0,\n", " fract_y=0,\n", " fract_z=0,\n", " wyckoff_letter='a',\n", " b_iso=0.89,\n", ")\n", "\n", "# Assign Sample Model to Experiment\n", "project_2.experiments['sim_lbco'].linked_phases.add(id='si', scale=1.0)" ] }, { "cell_type": "markdown", "id": "193", "metadata": {}, "source": [ "#### Exercise 5.11: Refine the Scale of the Si Phase\n", "\n", "Visualize the measured diffraction pattern and the calculated\n", "diffraction pattern. Check if the Si phase is contributing to the\n", "calculated diffraction pattern. Refine the scale factor of the Si\n", "phase to improve the fit." ] }, { "cell_type": "markdown", "id": "194", "metadata": {}, "source": [ "**Hint:**" ] }, { "cell_type": "markdown", "id": "195", "metadata": {}, "source": [ "You can use the `plot_meas_vs_calc` method of the project to visualize\n", "the patterns. Then, set the `free` attribute of the `scale` parameter\n", "of the Si phase to `True` to allow the fitting process to adjust the\n", "scale factor." ] }, { "cell_type": "markdown", "id": "196", "metadata": {}, "source": [ "**Solution:**" ] }, { "cell_type": "code", "execution_count": 50, "id": "197", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:33.890400Z", "iopub.status.busy": "2026-01-06T13:53:33.890275Z", "iopub.status.idle": "2026-01-06T13:53:52.418824Z", "shell.execute_reply": "2026-01-06T13:53:52.417354Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing experiment 🔬 \u001b[0m\u001b[32m'sim_lbco'\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'single'\u001b[0m\u001b[1;34m fitting\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🚀 Starting fit process with \u001b[32m'lmfit \u001b[0m\u001b[32m(\u001b[0m\u001b[32mleastsq\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m change:\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 iterationχ²improvement [%]
112254.38
2211.5699.9% ↓
3391.541.5% ↓
46881.54
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "🏆 Best goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m is \u001b[1;36m1.54\u001b[0m at iteration \u001b[1;36m687\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit results\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Success: \u001b[3;92mTrue\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⏱️ Fitting time: \u001b[1;36m16.03\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m1.54\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m4.64\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 R-factor squared \u001b[1m(\u001b[0mRf²\u001b[1m)\u001b[0m: \u001b[1;36m4.15\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📏 Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m3.67\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Fitted parameters:\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 datablockcategoryentryparameterstartfitteduncertaintyunitschange
1lbcocelllength_a3.89153.89130.0002Å0.01 % ↓
2sim_lbcolinked_phaseslbcoscale4.82954.85480.02740.52 % ↑
3sim_lbcolinked_phasessiscale1.00000.03730.001496.27 % ↓
4sim_lbcopeakgauss_sigma_090223.677389477.67339441.8847µs²0.83 % ↓
5sim_lbcopeakgauss_sigma_1-80933.7029-73469.317911867.0173µs/Å9.22 % ↓
6sim_lbcopeakgauss_sigma_221634.707818331.87053625.2100µs²/Ų15.27 % ↓
7sim_lbcopeakmix_beta_00.00230.00150.0003deg33.08 % ↓
8sim_lbcopeakmix_beta_10.01240.01540.0012deg24.45 % ↑
9sim_lbcopeakasym_alpha_0-0.0048-0.00710.001049.74 % ↑
10sim_lbcopeakasym_alpha_10.01370.01730.001426.55 % ↑
11sim_lbcobackground1y0.27500.27800.02811.10 % ↑
12sim_lbcobackground2y0.26060.25150.00573.48 % ↓
13sim_lbcobackground3y0.25920.25180.00382.85 % ↓
14sim_lbcobackground4y0.24390.24170.00290.89 % ↓
15sim_lbcobackground5y0.24580.24260.00211.29 % ↓
16sim_lbcobackground6y0.23870.22200.00257.00 % ↓
17sim_lbcobackground7y0.20840.23880.008614.56 % ↑
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Before optimizing the parameters, we can visualize the measured\n", "# diffraction pattern and the calculated diffraction pattern based on\n", "# the two phases: LBCO and Si.\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n", "\n", "# As you can see, the calculated pattern is now the sum of both phases,\n", "# and Si peaks are visible in the calculated pattern. However, their\n", "# intensities are much too high. Therefore, we need to refine the scale\n", "# factor of the Si phase.\n", "project_2.experiments['sim_lbco'].linked_phases['si'].scale.free = True\n", "\n", "# Now we can perform the fit with both phases included.\n", "project_2.analysis.fit()\n", "project_2.analysis.show_fit_results()\n", "\n", "# Let's plot the measured diffraction pattern and the calculated\n", "# diffraction pattern both for the full range and for a zoomed-in region\n", "# around the previously unexplained peak near 95,000 μs. The calculated\n", "# pattern will be the sum of the two phases.\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco')\n", "project_2.plot_meas_vs_calc(expt_name='sim_lbco', x_min=88000, x_max=101000)" ] }, { "cell_type": "markdown", "id": "198", "metadata": {}, "source": [ "All previously unexplained peaks are now accounted for in the pattern,\n", "and the fit is improved. Some discrepancies in the peak intensities\n", "remain, but further improvements would require more advanced data\n", "reduction and analysis, which are beyond the scope of this school.\n", "\n", "To review the analysis results, you can generate and print a summary\n", "report using the `show_report()` method, as demonstrated in the cell\n", "below. The report includes parameters related to the sample model and\n", "the experiment, such as the refined unit cell parameter `a` of LBCO.\n", "\n", "Information about the crystal or magnetic structure, along with\n", "experimental details, fitting quality, and other relevant data, is\n", "often submitted to crystallographic journals as part of a scientific\n", "publication. It can also be deposited in crystallographic databases\n", "when relevant." ] }, { "cell_type": "code", "execution_count": 51, "id": "199", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:52.424816Z", "iopub.status.busy": "2026-01-06T13:53:52.424427Z", "iopub.status.idle": "2026-01-06T13:53:53.956485Z", "shell.execute_reply": "2026-01-06T13:53:53.955862Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;32m————————————\u001b[0m\n", "\u001b[1;32mPROJECT INFO\u001b[0m\n", "\u001b[1;32m————————————\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mTitle\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "La0.5Ba0.5CoO3 Fit\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mDescription\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Fitting simulated powder diffraction pattern of\n", "La0.5Ba0.5CoO3.\n", "\u001b[1;32m—————————————————————\u001b[0m\n", "\u001b[1;32mCRYSTALLOGRAPHIC DATA\u001b[0m\n", "\u001b[1;32m—————————————————————\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mPhase datablock\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🧩 lbco\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mSpace group\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "P m \u001b[1;36m-3\u001b[0m m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCell parameters\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 ParameterValue
1a3.89125
2b3.89125
3c3.89125
4alpha90.00000
5beta90.00000
6gamma90.00000
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mAtom sites\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 labeltypexyzoccBiso
1LaLa0.000000.000000.000000.500000.95000
2BaBa0.000000.000000.000000.500000.95000
3CoCo0.500000.500000.500001.000000.80000
4OO0.000000.500000.500001.000001.66000
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mPhase datablock\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🧩 si\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mSpace group\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "F d \u001b[1;36m-3\u001b[0m m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCell parameters\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 ParameterValue
1a5.43000
2b5.43000
3c5.43000
4alpha90.00000
5beta90.00000
6gamma90.00000
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mAtom sites\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 labeltypexyzoccBiso
1SiSi0.125000.125000.125001.000000.89000
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;32m———————————\u001b[0m\n", "\u001b[1;32mEXPERIMENTS\u001b[0m\n", "\u001b[1;32m———————————\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mExperiment datablock\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "🔬 sim_lbco\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mExperiment type\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "powder, neutron, time-of-flight\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mProfile type\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "PeakProfileTypeEnum.PSEUDO_VOIGT_IKEDA_CARPENTER\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;32m———————\u001b[0m\n", "\u001b[1;32mFITTING\u001b[0m\n", "\u001b[1;32m———————\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCalculation engine\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "cryspy\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mMinimization engine\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "lmfit \u001b[1m(\u001b[0mleastsq\u001b[1m)\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mFit quality\u001b[0m\n" ] }, { "data": { "application/javascript": [ "\n", " (function() {\n", " var isDark = false;\n", "\n", " // Check JupyterLab theme\n", " if (document.body.classList.contains('jp-mod-dark') || \n", " document.body.classList.contains('theme-dark') ||\n", " document.body.classList.contains('vscode-dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check theme attribute\n", " var themeAttr = document.body.getAttribute('data-jp-theme-name');\n", " if (themeAttr && themeAttr.includes('dark')) {\n", " isDark = true;\n", " }\n", "\n", " // Check computed background color\n", " var notebookEl = document.querySelector('.jp-Notebook') || \n", " document.querySelector('.notebook_app') ||\n", " document.body;\n", " if (notebookEl) {\n", " var bgColor = window.getComputedStyle(notebookEl).backgroundColor;\n", " var rgb = bgColor.match(/\\d+/g);\n", " if (rgb && rgb.length >= 3) {\n", " var brightness = (parseInt(rgb[0]) + parseInt(rgb[1]) + parseInt(rgb[2])) / 3;\n", " if (brightness < 128) {\n", " isDark = true;\n", " }\n", " }\n", " }\n", "\n", " // Store result\n", " if (typeof IPython !== 'undefined' && IPython.notebook && IPython.notebook.kernel) {\n", " IPython.notebook.kernel.execute('_jupyter_dark_detect_result = ' + isDark);\n", " }\n", " })();\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " if (typeof IPython !== 'undefined' && IPython.notebook) {\n", " IPython.notebook.kernel.execute(\"_jupyter_dark_detect_result = \" + \n", " (document.body.classList.contains('theme-dark') || \n", " document.body.classList.contains('jp-mod-dark') ||\n", " (document.body.getAttribute('data-jp-theme-name') && \n", " document.body.getAttribute('data-jp-theme-name').includes('dark'))));\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 metricvalue
1Goodness-of-fit (reduced χ²)1.54
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project_2.summary.show_report()" ] }, { "cell_type": "markdown", "id": "200", "metadata": {}, "source": [ "Finally, we save the project to disk to preserve the current state of\n", "the analysis." ] }, { "cell_type": "code", "execution_count": 52, "id": "201", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:53:53.958239Z", "iopub.status.busy": "2026-01-06T13:53:53.958116Z", "iopub.status.idle": "2026-01-06T13:53:53.977059Z", "shell.execute_reply": "2026-01-06T13:53:53.976714Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mSaving project 📦 \u001b[0m\u001b[32m'main'\u001b[0m\u001b[1;34m to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[35m/Users/runner/work/diffraction-lib/diffraction-lib/tutorials/\u001b[0m\u001b[95mpowder_diffraction_LBCO_Si\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 project.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 sample_models\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 lbco.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 sample_models\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 si.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 experiments\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 sim_lbco.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 analysis.cif\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "└── 📄 summary.cif\n" ] } ], "source": [ "project_2.save_as(dir_path='powder_diffraction_LBCO_Si')" ] }, { "cell_type": "markdown", "id": "202", "metadata": {}, "source": [ "#### Final Remarks\n", "\n", "In this part of the notebook, you learned how to use EasyDiffraction\n", "to refine lattice parameters of a more complex crystal structure,\n", "La₀.₅Ba₀.₅CoO₃ (LBCO).\n", "\n", "In real experiments, you might also refine\n", "additional parameters, such as atomic positions, occupancies, and\n", "atomic displacement factors, to achieve an even better fit. For our\n", "purposes, we'll stop here, as the goal was to give you a starting\n", "point for analyzing more complex crystal structures with\n", "EasyDiffraction." ] }, { "cell_type": "markdown", "id": "203", "metadata": {}, "source": [ "## 🎁 Bonus\n", "\n", "Congratulations — you've now completed the diffraction data analysis\n", "part of the DMSC Summer School!\n", "\n", "If you'd like to keep exploring, the EasyDiffraction library offers\n", "many additional tutorials and examples on the official documentation\n", "site: 👉 https://docs.easydiffraction.org/lib/tutorials/\n", "\n", "Besides the Python package, EasyDiffraction also comes with a\n", "graphical user interface (GUI) that lets you perform similar analyses\n", "without writing code. To be fair, it's not *quite* feature-complete\n", "compared to the Python library yet — but we're working on it! 🚧\n", "\n", "If you prefer a point-and-click interface over coding, the GUI\n", "provides a user-friendly way to analyze diffraction data. You can\n", "download it as a standalone application here: 👉\n", "https://easydiffraction.org\n", "\n", "We'd love to hear your feedback on EasyDiffraction — both the library\n", "and the GUI! 💬" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "title,tags,-all", "main_language": "python", "notebook_metadata_filter": "-all" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.11" } }, "nbformat": 4, "nbformat_minor": 5 }