{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "de0888bd", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:50.317368Z", "iopub.status.busy": "2026-01-06T13:54:50.317273Z", "iopub.status.idle": "2026-01-06T13:54:50.321013Z", "shell.execute_reply": "2026-01-06T13:54:50.320563Z" }, "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": [ "# Structure Refinement: PbSO4, NPD + XRD\n", "\n", "This example demonstrates a more advanced use of the EasyDiffraction\n", "library by explicitly creating and configuring sample models and\n", "experiments before adding them to a project. It could be more suitable\n", "for users who are interested in creating custom workflows. This\n", "tutorial provides minimal explanation and is intended for users\n", "already familiar with EasyDiffraction.\n", "\n", "The tutorial covers a Rietveld refinement of PbSO4 crystal structure\n", "based on the joint fit of both X-ray and neutron diffraction data." ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "## Import Library" ] }, { "cell_type": "code", "execution_count": 2, "id": "2", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:50.323876Z", "iopub.status.busy": "2026-01-06T13:54:50.323674Z", "iopub.status.idle": "2026-01-06T13:54:54.487720Z", "shell.execute_reply": "2026-01-06T13:54:54.487182Z" } }, "outputs": [], "source": [ "from easydiffraction import ExperimentFactory\n", "from easydiffraction import Project\n", "from easydiffraction import SampleModelFactory\n", "from easydiffraction import download_data" ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "## Define Sample Model\n", "\n", "This section shows how to add sample models and modify their\n", "parameters.\n", "\n", "#### Create Sample Model" ] }, { "cell_type": "code", "execution_count": 3, "id": "4", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.490419Z", "iopub.status.busy": "2026-01-06T13:54:54.489978Z", "iopub.status.idle": "2026-01-06T13:54:54.504244Z", "shell.execute_reply": "2026-01-06T13:54:54.502519Z" } }, "outputs": [], "source": [ "model = SampleModelFactory.create(name='pbso4')" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "#### Set Space Group" ] }, { "cell_type": "code", "execution_count": 4, "id": "6", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.507728Z", "iopub.status.busy": "2026-01-06T13:54:54.507506Z", "iopub.status.idle": "2026-01-06T13:54:54.515595Z", "shell.execute_reply": "2026-01-06T13:54:54.512965Z" } }, "outputs": [], "source": [ "model.space_group.name_h_m = 'P n m a'" ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "#### Set Unit Cell" ] }, { "cell_type": "code", "execution_count": 5, "id": "8", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.519819Z", "iopub.status.busy": "2026-01-06T13:54:54.519271Z", "iopub.status.idle": "2026-01-06T13:54:54.527192Z", "shell.execute_reply": "2026-01-06T13:54:54.526044Z" } }, "outputs": [], "source": [ "model.cell.length_a = 8.47\n", "model.cell.length_b = 5.39\n", "model.cell.length_c = 6.95" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "#### Set Atom Sites" ] }, { "cell_type": "code", "execution_count": 6, "id": "10", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.540013Z", "iopub.status.busy": "2026-01-06T13:54:54.539181Z", "iopub.status.idle": "2026-01-06T13:54:54.572543Z", "shell.execute_reply": "2026-01-06T13:54:54.560222Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "model.atom_sites.add(\n", " label='Pb',\n", " type_symbol='Pb',\n", " fract_x=0.1876,\n", " fract_y=0.25,\n", " fract_z=0.167,\n", " wyckoff_letter='c',\n", " b_iso=1.37,\n", ")\n", "model.atom_sites.add(\n", " label='S',\n", " type_symbol='S',\n", " fract_x=0.0654,\n", " fract_y=0.25,\n", " fract_z=0.684,\n", " wyckoff_letter='c',\n", " b_iso=0.3777,\n", ")\n", "model.atom_sites.add(\n", " label='O1',\n", " type_symbol='O',\n", " fract_x=0.9082,\n", " fract_y=0.25,\n", " fract_z=0.5954,\n", " wyckoff_letter='c',\n", " b_iso=1.9764,\n", ")\n", "model.atom_sites.add(\n", " label='O2',\n", " type_symbol='O',\n", " fract_x=0.1935,\n", " fract_y=0.25,\n", " fract_z=0.5432,\n", " wyckoff_letter='c',\n", " b_iso=1.4456,\n", ")\n", "model.atom_sites.add(\n", " label='O3',\n", " type_symbol='O',\n", " fract_x=0.0811,\n", " fract_y=0.0272,\n", " fract_z=0.8086,\n", " wyckoff_letter='d',\n", " b_iso=1.2822,\n", ")" ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "## Define Experiments\n", "\n", "This section shows how to add experiments, configure their parameters,\n", "and link the sample models defined in the previous step.\n", "\n", "### Experiment 1: npd\n", "\n", "#### Download Data" ] }, { "cell_type": "code", "execution_count": 7, "id": "12", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.577079Z", "iopub.status.busy": "2026-01-06T13:54:54.576048Z", "iopub.status.idle": "2026-01-06T13:54:54.814566Z", "shell.execute_reply": "2026-01-06T13:54:54.810683Z" } }, "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;36m13\u001b[0m: PbSO4, D1A \u001b[1m(\u001b[0mILL\u001b[1m)\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "βœ… Data #\u001b[1;36m13\u001b[0m downloaded to \u001b[32m'data/ed-13.dat'\u001b[0m\n" ] } ], "source": [ "data_path1 = download_data(id=13, destination='data')" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "#### Create Experiment" ] }, { "cell_type": "code", "execution_count": 8, "id": "14", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:54.822450Z", "iopub.status.busy": "2026-01-06T13:54:54.821181Z", "iopub.status.idle": "2026-01-06T13:54:55.367372Z", "shell.execute_reply": "2026-01-06T13:54:55.366756Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mData loaded successfully\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Experiment πŸ”¬ \u001b[32m'npd'\u001b[0m. Number of data points: \u001b[1;36m1801\u001b[0m\n" ] } ], "source": [ "expt1 = ExperimentFactory.create(\n", " name='npd',\n", " data_path=data_path1,\n", " radiation_probe='neutron',\n", ")" ] }, { "cell_type": "markdown", "id": "15", "metadata": {}, "source": [ "#### Set Instrument" ] }, { "cell_type": "code", "execution_count": 9, "id": "16", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.370756Z", "iopub.status.busy": "2026-01-06T13:54:55.370363Z", "iopub.status.idle": "2026-01-06T13:54:55.382422Z", "shell.execute_reply": "2026-01-06T13:54:55.379280Z" } }, "outputs": [], "source": [ "expt1.instrument.setup_wavelength = 1.91\n", "expt1.instrument.calib_twotheta_offset = -0.1406" ] }, { "cell_type": "markdown", "id": "17", "metadata": {}, "source": [ "#### Set Peak Profile" ] }, { "cell_type": "code", "execution_count": 10, "id": "18", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.387201Z", "iopub.status.busy": "2026-01-06T13:54:55.386349Z", "iopub.status.idle": "2026-01-06T13:54:55.397476Z", "shell.execute_reply": "2026-01-06T13:54:55.395107Z" } }, "outputs": [], "source": [ "expt1.peak.broad_gauss_u = 0.139\n", "expt1.peak.broad_gauss_v = -0.412\n", "expt1.peak.broad_gauss_w = 0.386\n", "expt1.peak.broad_lorentz_x = 0\n", "expt1.peak.broad_lorentz_y = 0.088" ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "#### Set Background" ] }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ "Select the background type." ] }, { "cell_type": "code", "execution_count": 11, "id": "21", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.404412Z", "iopub.status.busy": "2026-01-06T13:54:55.403152Z", "iopub.status.idle": "2026-01-06T13:54:55.412299Z", "shell.execute_reply": "2026-01-06T13:54:55.411466Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mBackground type for experiment \u001b[0m\u001b[32m'npd'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "line-segment\n" ] } ], "source": [ "expt1.background_type = 'line-segment'" ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "Add background points." ] }, { "cell_type": "code", "execution_count": 12, "id": "23", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.417840Z", "iopub.status.busy": "2026-01-06T13:54:55.417214Z", "iopub.status.idle": "2026-01-06T13:54:55.431510Z", "shell.execute_reply": "2026-01-06T13:54:55.428475Z" } }, "outputs": [], "source": [ "for id, x, y in [\n", " ('1', 11.0, 206.1624),\n", " ('2', 15.0, 194.75),\n", " ('3', 20.0, 194.505),\n", " ('4', 30.0, 188.4375),\n", " ('5', 50.0, 207.7633),\n", " ('6', 70.0, 201.7002),\n", " ('7', 120.0, 244.4525),\n", " ('8', 153.0, 226.0595),\n", "]:\n", " expt1.background.add(id=id, x=x, y=y)" ] }, { "cell_type": "markdown", "id": "24", "metadata": {}, "source": [ "#### Set Linked Phases" ] }, { "cell_type": "code", "execution_count": 13, "id": "25", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.438470Z", "iopub.status.busy": "2026-01-06T13:54:55.437507Z", "iopub.status.idle": "2026-01-06T13:54:55.444248Z", "shell.execute_reply": "2026-01-06T13:54:55.443132Z" } }, "outputs": [], "source": [ "expt1.linked_phases.add(id='pbso4', scale=1.5)" ] }, { "cell_type": "markdown", "id": "26", "metadata": {}, "source": [ "### Experiment 2: xrd\n", "\n", "#### Download Data" ] }, { "cell_type": "code", "execution_count": 14, "id": "27", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.450071Z", "iopub.status.busy": "2026-01-06T13:54:55.448670Z", "iopub.status.idle": "2026-01-06T13:54:55.607618Z", "shell.execute_reply": "2026-01-06T13:54:55.607262Z" } }, "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;36m16\u001b[0m: PbSO4, laboratory X-ray\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "βœ… Data #\u001b[1;36m16\u001b[0m downloaded to \u001b[32m'data/ed-16.dat'\u001b[0m\n" ] } ], "source": [ "data_path2 = download_data(id=16, destination='data')" ] }, { "cell_type": "markdown", "id": "28", "metadata": {}, "source": [ "#### Create Experiment" ] }, { "cell_type": "code", "execution_count": 15, "id": "29", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:55.610508Z", "iopub.status.busy": "2026-01-06T13:54:55.610346Z", "iopub.status.idle": "2026-01-06T13:54:56.445057Z", "shell.execute_reply": "2026-01-06T13:54:56.437823Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mData loaded successfully\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Experiment πŸ”¬ \u001b[32m'xrd'\u001b[0m. Number of data points: \u001b[1;36m3601\u001b[0m\n" ] } ], "source": [ "expt2 = ExperimentFactory.create(\n", " name='xrd',\n", " data_path=data_path2,\n", " radiation_probe='xray',\n", ")" ] }, { "cell_type": "markdown", "id": "30", "metadata": {}, "source": [ "#### Set Instrument" ] }, { "cell_type": "code", "execution_count": 16, "id": "31", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.449677Z", "iopub.status.busy": "2026-01-06T13:54:56.448754Z", "iopub.status.idle": "2026-01-06T13:54:56.458668Z", "shell.execute_reply": "2026-01-06T13:54:56.455849Z" } }, "outputs": [], "source": [ "expt2.instrument.setup_wavelength = 1.540567\n", "expt2.instrument.calib_twotheta_offset = -0.05181" ] }, { "cell_type": "markdown", "id": "32", "metadata": {}, "source": [ "#### Set Peak Profile" ] }, { "cell_type": "code", "execution_count": 17, "id": "33", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.475336Z", "iopub.status.busy": "2026-01-06T13:54:56.475119Z", "iopub.status.idle": "2026-01-06T13:54:56.496049Z", "shell.execute_reply": "2026-01-06T13:54:56.492393Z" } }, "outputs": [], "source": [ "expt2.peak.broad_gauss_u = 0.304138\n", "expt2.peak.broad_gauss_v = -0.112622\n", "expt2.peak.broad_gauss_w = 0.021272\n", "expt2.peak.broad_lorentz_x = 0\n", "expt2.peak.broad_lorentz_y = 0.057691" ] }, { "cell_type": "markdown", "id": "34", "metadata": {}, "source": [ "#### Set Background" ] }, { "cell_type": "markdown", "id": "35", "metadata": {}, "source": [ "Select background type." ] }, { "cell_type": "code", "execution_count": 18, "id": "36", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.502396Z", "iopub.status.busy": "2026-01-06T13:54:56.501587Z", "iopub.status.idle": "2026-01-06T13:54:56.511111Z", "shell.execute_reply": "2026-01-06T13:54:56.508705Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mBackground type for experiment \u001b[0m\u001b[32m'xrd'\u001b[0m\u001b[1;34m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "chebyshev polynomial\n" ] } ], "source": [ "expt2.background_type = 'chebyshev polynomial'" ] }, { "cell_type": "markdown", "id": "37", "metadata": {}, "source": [ "Add background points." ] }, { "cell_type": "code", "execution_count": 19, "id": "38", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.519463Z", "iopub.status.busy": "2026-01-06T13:54:56.515562Z", "iopub.status.idle": "2026-01-06T13:54:56.530960Z", "shell.execute_reply": "2026-01-06T13:54:56.528792Z" } }, "outputs": [], "source": [ "for id, x, y in [\n", " ('1', 0, 119.195),\n", " ('2', 1, 6.221),\n", " ('3', 2, -45.725),\n", " ('4', 3, 8.119),\n", " ('5', 4, 54.552),\n", " ('6', 5, -20.661),\n", "]:\n", " expt2.background.add(id=id, order=x, coef=y)" ] }, { "cell_type": "markdown", "id": "39", "metadata": {}, "source": [ "#### Set Linked Phases" ] }, { "cell_type": "code", "execution_count": 20, "id": "40", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.540512Z", "iopub.status.busy": "2026-01-06T13:54:56.539922Z", "iopub.status.idle": "2026-01-06T13:54:56.548407Z", "shell.execute_reply": "2026-01-06T13:54:56.547061Z" } }, "outputs": [], "source": [ "expt2.linked_phases.add(id='pbso4', scale=0.001)" ] }, { "cell_type": "markdown", "id": "41", "metadata": {}, "source": [ "## Define Project\n", "\n", "The project object is used to manage sample models, experiments, and\n", "analysis.\n", "\n", "#### Create Project" ] }, { "cell_type": "code", "execution_count": 21, "id": "42", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.556225Z", "iopub.status.busy": "2026-01-06T13:54:56.554431Z", "iopub.status.idle": "2026-01-06T13:54:56.812924Z", "shell.execute_reply": "2026-01-06T13:54:56.812224Z" } }, "outputs": [], "source": [ "project = Project()" ] }, { "cell_type": "markdown", "id": "43", "metadata": {}, "source": [ "#### Add Sample Model" ] }, { "cell_type": "code", "execution_count": 22, "id": "44", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.835803Z", "iopub.status.busy": "2026-01-06T13:54:56.834641Z", "iopub.status.idle": "2026-01-06T13:54:56.843702Z", "shell.execute_reply": "2026-01-06T13:54:56.842380Z" } }, "outputs": [], "source": [ "project.sample_models.add(sample_model=model)" ] }, { "cell_type": "markdown", "id": "45", "metadata": {}, "source": [ "#### Add Experiments" ] }, { "cell_type": "code", "execution_count": 23, "id": "46", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.848703Z", "iopub.status.busy": "2026-01-06T13:54:56.847196Z", "iopub.status.idle": "2026-01-06T13:54:56.861432Z", "shell.execute_reply": "2026-01-06T13:54:56.859705Z" } }, "outputs": [], "source": [ "project.experiments.add(experiment=expt1)\n", "project.experiments.add(experiment=expt2)" ] }, { "cell_type": "markdown", "id": "47", "metadata": {}, "source": [ "## Perform Analysis\n", "\n", "This section outlines the analysis process, including how to configure\n", "calculation and fitting engines.\n", "\n", "#### Set Calculator" ] }, { "cell_type": "code", "execution_count": 24, "id": "48", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.868857Z", "iopub.status.busy": "2026-01-06T13:54:56.866081Z", "iopub.status.idle": "2026-01-06T13:54:56.878585Z", "shell.execute_reply": "2026-01-06T13:54:56.876946Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCurrent calculator changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "cryspy\n" ] } ], "source": [ "project.analysis.current_calculator = 'cryspy'" ] }, { "cell_type": "markdown", "id": "49", "metadata": {}, "source": [ "#### Set Fit Mode" ] }, { "cell_type": "code", "execution_count": 25, "id": "50", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.882165Z", "iopub.status.busy": "2026-01-06T13:54:56.881652Z", "iopub.status.idle": "2026-01-06T13:54:56.894275Z", "shell.execute_reply": "2026-01-06T13:54:56.890232Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCurrent fit mode changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "joint\n" ] } ], "source": [ "project.analysis.fit_mode = 'joint'" ] }, { "cell_type": "markdown", "id": "51", "metadata": {}, "source": [ "#### Set Minimizer" ] }, { "cell_type": "code", "execution_count": 26, "id": "52", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.896760Z", "iopub.status.busy": "2026-01-06T13:54:56.896548Z", "iopub.status.idle": "2026-01-06T13:54:56.902168Z", "shell.execute_reply": "2026-01-06T13:54:56.900904Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mCurrent minimizer changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "lmfit \u001b[1m(\u001b[0mleastsq\u001b[1m)\u001b[0m\n" ] } ], "source": [ "project.analysis.current_minimizer = 'lmfit (leastsq)'" ] }, { "cell_type": "markdown", "id": "53", "metadata": {}, "source": [ "#### Set Fitting Parameters\n", "\n", "Set sample model parameters to be optimized." ] }, { "cell_type": "code", "execution_count": 27, "id": "54", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.906089Z", "iopub.status.busy": "2026-01-06T13:54:56.905883Z", "iopub.status.idle": "2026-01-06T13:54:56.910603Z", "shell.execute_reply": "2026-01-06T13:54:56.908675Z" } }, "outputs": [], "source": [ "model.cell.length_a.free = True\n", "model.cell.length_b.free = True\n", "model.cell.length_c.free = True" ] }, { "cell_type": "markdown", "id": "55", "metadata": {}, "source": [ "Set experiment parameters to be optimized." ] }, { "cell_type": "code", "execution_count": 28, "id": "56", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.914254Z", "iopub.status.busy": "2026-01-06T13:54:56.914023Z", "iopub.status.idle": "2026-01-06T13:54:56.920171Z", "shell.execute_reply": "2026-01-06T13:54:56.917155Z" } }, "outputs": [], "source": [ "expt1.linked_phases['pbso4'].scale.free = True\n", "\n", "expt1.instrument.calib_twotheta_offset.free = True\n", "\n", "expt1.peak.broad_gauss_u.free = True\n", "expt1.peak.broad_gauss_v.free = True\n", "expt1.peak.broad_gauss_w.free = True\n", "expt1.peak.broad_lorentz_y.free = True" ] }, { "cell_type": "code", "execution_count": 29, "id": "57", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.928014Z", "iopub.status.busy": "2026-01-06T13:54:56.927655Z", "iopub.status.idle": "2026-01-06T13:54:56.932743Z", "shell.execute_reply": "2026-01-06T13:54:56.931766Z" } }, "outputs": [], "source": [ "expt2.linked_phases['pbso4'].scale.free = True\n", "\n", "expt2.instrument.calib_twotheta_offset.free = True\n", "\n", "expt2.peak.broad_gauss_u.free = True\n", "expt2.peak.broad_gauss_v.free = True\n", "expt2.peak.broad_gauss_w.free = True\n", "expt2.peak.broad_lorentz_y.free = True\n", "\n", "for term in expt2.background:\n", " term.coef.free = True" ] }, { "cell_type": "markdown", "id": "58", "metadata": {}, "source": [ "#### Perform Fit" ] }, { "cell_type": "code", "execution_count": 30, "id": "59", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:54:56.934693Z", "iopub.status.busy": "2026-01-06T13:54:56.934566Z", "iopub.status.idle": "2026-01-06T13:55:21.091086Z", "shell.execute_reply": "2026-01-06T13:55:21.090120Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;34mUsing all experiments πŸ”¬ \u001b[0m\u001b[1;34m[\u001b[0m\u001b[32m'npd'\u001b[0m\u001b[1;34m, \u001b[0m\u001b[32m'xrd'\u001b[0m\u001b[1;34m]\u001b[0m\u001b[1;34m for \u001b[0m\u001b[32m'joint'\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 [%]
1137.01
22516.3056.0% ↓
313616.21
\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;36m16.21\u001b[0m at iteration \u001b[1;36m135\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;36m22.42\u001b[0m seconds\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "πŸ“ Goodness-of-fit \u001b[1m(\u001b[0mreduced χ²\u001b[1m)\u001b[0m: \u001b[1;36m16.21\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "πŸ“ R-factor \u001b[1m(\u001b[0mRf\u001b[1m)\u001b[0m: \u001b[1;36m13.18\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "πŸ“ R-factor squared \u001b[1m(\u001b[0mRfΒ²\u001b[1m)\u001b[0m: \u001b[1;36m17.19\u001b[0m%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "πŸ“ Weighted R-factor \u001b[1m(\u001b[0mwR\u001b[1m)\u001b[0m: \u001b[1;36m17.09\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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
1pbso4celllength_a8.47008.46930.0002Γ…0.01 % ↓
2pbso4celllength_b5.39005.39120.0001Γ…0.02 % ↑
3pbso4celllength_c6.95006.95040.0002Γ…0.01 % ↑
4npdlinked_phasespbso4scale1.50001.46220.00492.52 % ↓
5npdpeakbroad_gauss_u0.13900.29010.0350degΒ²108.67 % ↑
6npdpeakbroad_gauss_v-0.4120-0.63900.0531degΒ²55.10 % ↑
7npdpeakbroad_gauss_w0.38600.45520.0186degΒ²17.92 % ↑
8npdpeakbroad_lorentz_y0.08800.09310.0034deg5.76 % ↑
9npdinstrumenttwotheta_offset-0.1406-0.13850.0019deg1.47 % ↓
10xrdlinked_phasespbso4scale0.00100.00100.00001.52 % ↓
11xrdpeakbroad_gauss_u0.30410.57240.0196degΒ²88.21 % ↑
12xrdpeakbroad_gauss_v-0.1126-0.27990.0142degΒ²148.57 % ↑
13xrdpeakbroad_gauss_w0.02130.04520.0024degΒ²112.27 % ↑
14xrdpeakbroad_lorentz_y0.05770.05870.0014deg1.75 % ↑
15xrdinstrumenttwotheta_offset-0.0518-0.06370.0009deg22.93 % ↑
16xrdbackground1coef119.195085.85871.329327.97 % ↓
17xrdbackground2coef6.2210-19.31121.8805410.42 % ↓
18xrdbackground3coef-45.72505.36581.7778111.74 % ↓
19xrdbackground4coef8.119011.88421.747246.37 % ↑
20xrdbackground5coef54.552018.55601.567065.98 % ↓
21xrdbackground6coef-20.6610-6.40931.535968.98 % ↓
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.analysis.fit()\n", "project.analysis.show_fit_results()" ] }, { "cell_type": "markdown", "id": "60", "metadata": {}, "source": [ "#### Plot Measured vs Calculated" ] }, { "cell_type": "code", "execution_count": 31, "id": "61", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:55:21.101733Z", "iopub.status.busy": "2026-01-06T13:55:21.099700Z", "iopub.status.idle": "2026-01-06T13:55:21.448607Z", "shell.execute_reply": "2026-01-06T13:55:21.447205Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.plot_meas_vs_calc(expt_name='npd', x_min=35.5, x_max=38.3, show_residual=True)" ] }, { "cell_type": "code", "execution_count": 32, "id": "62", "metadata": { "execution": { "iopub.execute_input": "2026-01-06T13:55:21.454648Z", "iopub.status.busy": "2026-01-06T13:55:21.454124Z", "iopub.status.idle": "2026-01-06T13:55:22.289499Z", "shell.execute_reply": "2026-01-06T13:55:22.288491Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.plot_meas_vs_calc(expt_name='xrd', x_min=29.0, x_max=30.4, show_residual=True)" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-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 }