{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "0", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:20.099711Z", "iopub.status.busy": "2026-06-30T22:30:20.099403Z", "iopub.status.idle": "2026-06-30T22:30:20.105338Z", "shell.execute_reply": "2026-06-30T22:30:20.104712Z" }, "tags": [ "hide-in-docs" ] }, "outputs": [], "source": [ "# Check whether easydiffraction is installed; install it if needed.\n", "# Required for remote environments such as Google Colab.\n", "import importlib.util\n", "\n", "if importlib.util.find_spec('easydiffraction') is None:\n", " %pip install easydiffraction==0.19.1" ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "# Instrument calibration: BEER at ESS\n", "\n", "This example demonstrates a Rietveld refinement of a duplex steel\n", "structure using time-of-flight neutron powder diffraction data\n", "simulated with McStas.\n", "\n", "Two datasets from two symmetrically positioned banks (S2 and N2) of\n", "the BEER instrument are analyzed in this tutorial." ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "## 🛠️ Import Library" ] }, { "cell_type": "code", "execution_count": 2, "id": "3", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:20.107247Z", "iopub.status.busy": "2026-06-30T22:30:20.107045Z", "iopub.status.idle": "2026-06-30T22:30:23.412572Z", "shell.execute_reply": "2026-06-30T22:30:23.411738Z" } }, "outputs": [], "source": [ "from easydiffraction import ExperimentFactory\n", "from easydiffraction import Project\n", "from easydiffraction import StructureFactory\n", "from easydiffraction import download_data\n", "from easydiffraction import extract_data_paths_from_zip\n", "from easydiffraction import extract_metadata" ] }, { "cell_type": "markdown", "id": "4", "metadata": {}, "source": [ "## 🧩 Define Structures\n", "\n", "This section covers how to add structures and modify their\n", "parameters.\n", "\n", "### Create Ferrite Structure" ] }, { "cell_type": "code", "execution_count": 3, "id": "5", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:23.414775Z", "iopub.status.busy": "2026-06-30T22:30:23.414506Z", "iopub.status.idle": "2026-06-30T22:30:23.421297Z", "shell.execute_reply": "2026-06-30T22:30:23.420227Z" } }, "outputs": [], "source": [ "ferrite = StructureFactory.from_scratch(name='ferrite')\n", "\n", "ferrite.space_group.name_h_m = 'I m -3 m'\n", "ferrite.space_group.coord_system_code = '1'\n", "\n", "ferrite.cell.length_a = 2.886\n", "\n", "ferrite.atom_sites.create(\n", " id='Fe',\n", " type_symbol='Fe',\n", " fract_x=0.0,\n", " fract_y=0.0,\n", " fract_z=0.0,\n", " adp_type='Biso',\n", " adp_iso=1.0,\n", ")" ] }, { "cell_type": "markdown", "id": "6", "metadata": {}, "source": [ "### Create Austenite Structure" ] }, { "cell_type": "code", "execution_count": 4, "id": "7", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:23.422958Z", "iopub.status.busy": "2026-06-30T22:30:23.422748Z", "iopub.status.idle": "2026-06-30T22:30:23.427353Z", "shell.execute_reply": "2026-06-30T22:30:23.426632Z" } }, "outputs": [], "source": [ "austenite = StructureFactory.from_scratch(name='austenite')\n", "\n", "austenite.space_group.name_h_m = 'F m -3 m'\n", "austenite.space_group.coord_system_code = '1'\n", "\n", "austenite.cell.length_a = 3.6468\n", "\n", "austenite.atom_sites.create(\n", " id='Fe',\n", " type_symbol='Fe',\n", " fract_x=0.0,\n", " fract_y=0.0,\n", " fract_z=0.0,\n", " adp_type='Biso',\n", " adp_iso=1.0,\n", ")" ] }, { "cell_type": "markdown", "id": "8", "metadata": {}, "source": [ "## 🔬 Define Experiments\n", "\n", "This section shows how to add experiments, configure their parameters,\n", "and link the structures defined in the previous step.\n", "\n", "### Download Data" ] }, { "cell_type": "code", "execution_count": 5, "id": "9", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:23.429111Z", "iopub.status.busy": "2026-06-30T22:30:23.428941Z", "iopub.status.idle": "2026-06-30T22:30:23.725131Z", "shell.execute_reply": "2026-06-30T22:30:23.724136Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mGetting data\u001b[0m\u001b[1;36m...\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Data \u001b[32m'meas-ferrite-austenite-beer'\u001b[0m: ferrite + austenite, BEER \u001b[1m(\u001b[0mESS\u001b[1m)\u001b[0m, S2 and N2 detector bank datasets\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Data \u001b[32m'meas-ferrite-austenite-beer'\u001b[0m downloaded to \u001b[32m'../../../data/meas-ferrite-austenite-beer.zip'\u001b[0m\n" ] } ], "source": [ "zip_path = download_data('meas-ferrite-austenite-beer', destination='data')\n", "data_paths = extract_data_paths_from_zip(zip_path, destination='data/calibrate-beer-ess')\n", "\n", "data_path_s2 = data_paths[1] # 'Duplex_in_HR_for_IRF_S2.dat'\n", "data_path_n2 = data_paths[0] # 'Duplex_in_HR_for_IRF_N2.dat'" ] }, { "cell_type": "markdown", "id": "10", "metadata": {}, "source": [ "### Create Experiment" ] }, { "cell_type": "code", "execution_count": 6, "id": "11", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:23.727952Z", "iopub.status.busy": "2026-06-30T22:30:23.727054Z", "iopub.status.idle": "2026-06-30T22:30:24.278499Z", "shell.execute_reply": "2026-06-30T22:30:24.277718Z" } }, "outputs": [], "source": [ "expt_s2 = ExperimentFactory.from_data_path(\n", " name='expt_s2',\n", " data_path=data_path_s2,\n", " beam_mode='time-of-flight',\n", ")" ] }, { "cell_type": "code", "execution_count": 7, "id": "12", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.280598Z", "iopub.status.busy": "2026-06-30T22:30:24.280414Z", "iopub.status.idle": "2026-06-30T22:30:24.595772Z", "shell.execute_reply": "2026-06-30T22:30:24.594865Z" } }, "outputs": [], "source": [ "expt_n2 = ExperimentFactory.from_data_path(\n", " name='expt_n2',\n", " data_path=data_path_n2,\n", " beam_mode='time-of-flight',\n", ")" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "### Set Instrument" ] }, { "cell_type": "code", "execution_count": 8, "id": "14", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.597491Z", "iopub.status.busy": "2026-06-30T22:30:24.597303Z", "iopub.status.idle": "2026-06-30T22:30:24.601280Z", "shell.execute_reply": "2026-06-30T22:30:24.600478Z" } }, "outputs": [], "source": [ "expt_s2.instrument.setup_twotheta_bank = extract_metadata(\n", " data_path_s2, r'two_theta\\s*=\\s*(\\d*\\.?\\d+)'\n", ")\n", "expt_s2.instrument.calib_d_to_tof_linear = extract_metadata(\n", " data_path_s2, r'DIFC\\s*=\\s*(\\d*\\.?\\d+)'\n", ")" ] }, { "cell_type": "code", "execution_count": 9, "id": "15", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.602855Z", "iopub.status.busy": "2026-06-30T22:30:24.602645Z", "iopub.status.idle": "2026-06-30T22:30:24.606736Z", "shell.execute_reply": "2026-06-30T22:30:24.605678Z" } }, "outputs": [], "source": [ "expt_n2.instrument.setup_twotheta_bank = extract_metadata(\n", " data_path_n2, r'two_theta\\s*=\\s*(\\d*\\.?\\d+)'\n", ")\n", "expt_n2.instrument.calib_d_to_tof_linear = extract_metadata(\n", " data_path_n2, r'DIFC\\s*=\\s*(\\d*\\.?\\d+)'\n", ")" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "### Set Peak Profile" ] }, { "cell_type": "code", "execution_count": 10, "id": "17", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.608344Z", "iopub.status.busy": "2026-06-30T22:30:24.608169Z", "iopub.status.idle": "2026-06-30T22:30:24.622299Z", "shell.execute_reply": "2026-06-30T22:30:24.621488Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mPeak types\u001b[0m\n" ] }, { "data": { "text/html": [ "
TypeDescription
1pseudo-voigtTOF non-convoluted pseudo-Voigt profile
2*jorgensenTOF Jorgensen profile: back-to-back exponentials ⊗ Gaussian
3jorgensen-von-dreeleTOF Jorgensen-Von Dreele profile: back-to-back exponentials ⊗ pseudo-Voigt
4double-jorgensen-von-dreeleTOF Double-Jorgensen-Von Dreele profile: double back-to-back exponentials ⊗ pseudo-Voigt (Z-Rietveld type0m)
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "expt_s2.peak.show_supported()" ] }, { "cell_type": "code", "execution_count": 11, "id": "18", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.624363Z", "iopub.status.busy": "2026-06-30T22:30:24.624175Z", "iopub.status.idle": "2026-06-30T22:30:24.632856Z", "shell.execute_reply": "2026-06-30T22:30:24.632041Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "⚠️ Switching peak profile type removes these settings: \n", " • decay_beta_0 \n", " • decay_beta_1 \n", " • rise_alpha_0 \n", " • rise_alpha_1 \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⚠️ Switching peak profile type adds these settings with defaults: \n", " • broad_lorentz_gamma_0=0.0 \n", " • broad_lorentz_gamma_1=0.0 \n", " • broad_lorentz_gamma_2=0.0 \n", " • broad_lorentz_size_l=0.0 \n", " • broad_lorentz_strain_l=0.0 \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mPeak profile type for experiment \u001b[0m\u001b[32m'expt_s2'\u001b[0m\u001b[1;36m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "pseudo-voigt\n" ] } ], "source": [ "expt_s2.peak.type = 'pseudo-voigt'" ] }, { "cell_type": "code", "execution_count": 12, "id": "19", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.634413Z", "iopub.status.busy": "2026-06-30T22:30:24.634241Z", "iopub.status.idle": "2026-06-30T22:30:24.637681Z", "shell.execute_reply": "2026-06-30T22:30:24.636875Z" } }, "outputs": [], "source": [ "expt_s2.peak.broad_gauss_sigma_0 = 300\n", "expt_s2.peak.broad_gauss_sigma_1 = 1200\n", "expt_s2.peak.broad_gauss_sigma_2 = 900" ] }, { "cell_type": "code", "execution_count": 13, "id": "20", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.639303Z", "iopub.status.busy": "2026-06-30T22:30:24.639084Z", "iopub.status.idle": "2026-06-30T22:30:24.647259Z", "shell.execute_reply": "2026-06-30T22:30:24.646486Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "⚠️ Switching peak profile type removes these settings: \n", " • decay_beta_0 \n", " • decay_beta_1 \n", " • rise_alpha_0 \n", " • rise_alpha_1 \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "⚠️ Switching peak profile type adds these settings with defaults: \n", " • broad_lorentz_gamma_0=0.0 \n", " • broad_lorentz_gamma_1=0.0 \n", " • broad_lorentz_gamma_2=0.0 \n", " • broad_lorentz_size_l=0.0 \n", " • broad_lorentz_strain_l=0.0 \n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mPeak profile type for experiment \u001b[0m\u001b[32m'expt_n2'\u001b[0m\u001b[1;36m changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "pseudo-voigt\n" ] } ], "source": [ "expt_n2.peak.type = 'pseudo-voigt'" ] }, { "cell_type": "code", "execution_count": 14, "id": "21", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.648952Z", "iopub.status.busy": "2026-06-30T22:30:24.648756Z", "iopub.status.idle": "2026-06-30T22:30:24.652311Z", "shell.execute_reply": "2026-06-30T22:30:24.651503Z" } }, "outputs": [], "source": [ "expt_n2.peak.broad_gauss_sigma_0 = 300\n", "expt_n2.peak.broad_gauss_sigma_1 = 1200\n", "expt_n2.peak.broad_gauss_sigma_2 = 900" ] }, { "cell_type": "markdown", "id": "22", "metadata": {}, "source": [ "### Set Background" ] }, { "cell_type": "code", "execution_count": 15, "id": "23", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.653853Z", "iopub.status.busy": "2026-06-30T22:30:24.653683Z", "iopub.status.idle": "2026-06-30T22:30:24.661193Z", "shell.execute_reply": "2026-06-30T22:30:24.660396Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mBackground types\u001b[0m\n" ] }, { "data": { "text/html": [ "
TypeDescription
1chebyshevChebyshev polynomial background
2*line-segmentLinear interpolation between points
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "expt_s2.background.show_supported()" ] }, { "cell_type": "code", "execution_count": 16, "id": "24", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.662896Z", "iopub.status.busy": "2026-06-30T22:30:24.662693Z", "iopub.status.idle": "2026-06-30T22:30:24.910585Z", "shell.execute_reply": "2026-06-30T22:30:24.909699Z" } }, "outputs": [], "source": [ "expt_s2.background.auto_estimate()" ] }, { "cell_type": "code", "execution_count": 17, "id": "25", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.912169Z", "iopub.status.busy": "2026-06-30T22:30:24.911977Z", "iopub.status.idle": "2026-06-30T22:30:24.919393Z", "shell.execute_reply": "2026-06-30T22:30:24.918537Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mLine-segment background points\u001b[0m\n" ] }, { "data": { "text/html": [ "
PositionIntensity
140094.523400.00154
248089.848900.16817
351976.023000.18318
454301.356700.17817
558729.047000.29095
662710.782800.30387
767711.842900.25310
873158.857500.22573
976439.807800.20324
1081249.744600.19453
1185263.334300.17297
1296157.363500.24903
1398132.304400.34182
14102368.871300.39039
15104248.250600.36120
16108771.502500.62067
17111606.498401.22400
18112721.384401.32442
19115715.649701.12711
20135592.474800.00952
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "expt_s2.background.show()" ] }, { "cell_type": "code", "execution_count": 18, "id": "26", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.921159Z", "iopub.status.busy": "2026-06-30T22:30:24.920936Z", "iopub.status.idle": "2026-06-30T22:30:24.931846Z", "shell.execute_reply": "2026-06-30T22:30:24.930895Z" } }, "outputs": [], "source": [ "for point in expt_s2.background:\n", " expt_n2.background.create(\n", " id=point.id.value, position=point.position.value, intensity=point.intensity.value\n", " )" ] }, { "cell_type": "markdown", "id": "27", "metadata": {}, "source": [ "### Set Linked Structures" ] }, { "cell_type": "code", "execution_count": 19, "id": "28", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.933451Z", "iopub.status.busy": "2026-06-30T22:30:24.933277Z", "iopub.status.idle": "2026-06-30T22:30:24.936902Z", "shell.execute_reply": "2026-06-30T22:30:24.936123Z" } }, "outputs": [], "source": [ "expt_s2.linked_structures.create(structure_id='ferrite', scale=285)\n", "expt_s2.linked_structures.create(structure_id='austenite', scale=68)" ] }, { "cell_type": "code", "execution_count": 20, "id": "29", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.938353Z", "iopub.status.busy": "2026-06-30T22:30:24.938189Z", "iopub.status.idle": "2026-06-30T22:30:24.941630Z", "shell.execute_reply": "2026-06-30T22:30:24.940757Z" } }, "outputs": [], "source": [ "expt_n2.linked_structures.create(structure_id='ferrite', scale=285)\n", "expt_n2.linked_structures.create(structure_id='austenite', scale=68)" ] }, { "cell_type": "markdown", "id": "30", "metadata": {}, "source": [ "### Set Excluded Regions" ] }, { "cell_type": "code", "execution_count": 21, "id": "31", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.943368Z", "iopub.status.busy": "2026-06-30T22:30:24.943078Z", "iopub.status.idle": "2026-06-30T22:30:24.947271Z", "shell.execute_reply": "2026-06-30T22:30:24.946443Z" } }, "outputs": [], "source": [ "expt_s2.excluded_regions.create(id='1', start=0, end=40500)\n", "expt_s2.excluded_regions.create(id='2', start=130000, end=180000)" ] }, { "cell_type": "code", "execution_count": 22, "id": "32", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.948801Z", "iopub.status.busy": "2026-06-30T22:30:24.948642Z", "iopub.status.idle": "2026-06-30T22:30:24.951952Z", "shell.execute_reply": "2026-06-30T22:30:24.951243Z" } }, "outputs": [], "source": [ "expt_n2.excluded_regions.create(id='1', start=0, end=40500)\n", "expt_n2.excluded_regions.create(id='2', start=130000, end=180000)" ] }, { "cell_type": "markdown", "id": "33", "metadata": {}, "source": [ "## 📦 Define Project\n", "\n", "The project object is used to manage the structure, experiments,\n", "and analysis\n", "\n", "### Create Project" ] }, { "cell_type": "code", "execution_count": 23, "id": "34", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:24.953831Z", "iopub.status.busy": "2026-06-30T22:30:24.953641Z", "iopub.status.idle": "2026-06-30T22:30:25.257712Z", "shell.execute_reply": "2026-06-30T22:30:25.256827Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mSaving project 📦 \u001b[0m\u001b[32m'beer_mcstas'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/calibrate-beer-ess'\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 project.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 structures/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 experiments/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 analysis/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 analysis.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "└── 📁 reports/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " └── 📄 beer_mcstas.html\n" ] } ], "source": [ "project = Project(name='beer_mcstas')\n", "project.save_as(dir_path='projects/calibrate-beer-ess')" ] }, { "cell_type": "markdown", "id": "35", "metadata": {}, "source": [ "### Add Structures" ] }, { "cell_type": "code", "execution_count": 24, "id": "36", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:25.259405Z", "iopub.status.busy": "2026-06-30T22:30:25.259192Z", "iopub.status.idle": "2026-06-30T22:30:25.262756Z", "shell.execute_reply": "2026-06-30T22:30:25.261934Z" } }, "outputs": [], "source": [ "project.structures.add(ferrite)\n", "project.structures.add(austenite)" ] }, { "cell_type": "markdown", "id": "37", "metadata": {}, "source": [ "### Add Experiments" ] }, { "cell_type": "code", "execution_count": 25, "id": "38", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:25.264366Z", "iopub.status.busy": "2026-06-30T22:30:25.264161Z", "iopub.status.idle": "2026-06-30T22:30:25.267491Z", "shell.execute_reply": "2026-06-30T22:30:25.266764Z" } }, "outputs": [], "source": [ "project.experiments.add(expt_s2)\n", "project.experiments.add(expt_n2)" ] }, { "cell_type": "markdown", "id": "39", "metadata": {}, "source": [ "### Display Structure" ] }, { "cell_type": "code", "execution_count": 26, "id": "40", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:25.269359Z", "iopub.status.busy": "2026-06-30T22:30:25.269163Z", "iopub.status.idle": "2026-06-30T22:30:26.047663Z", "shell.execute_reply": "2026-06-30T22:30:26.046962Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mStructure 🧩 \u001b[0m\u001b[32m'ferrite'\u001b[0m\u001b[1;36m \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36mAtom view type: \u001b[0m\u001b[32m'covalent'\u001b[0m\u001b[1;36m)\u001b[0m\n" ] }, { "data": { "text/html": [ "
\n", "
\n", "
Loading plot…
\n", "
\n", "
\n", "
\n", "
drag = rotate
wheel = zoom
right-drag = pan
\n", "
\n", "
\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mStructure 🧩 \u001b[0m\u001b[32m'austenite'\u001b[0m\u001b[1;36m \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36mAtom view type: \u001b[0m\u001b[32m'covalent'\u001b[0m\u001b[1;36m)\u001b[0m\n" ] }, { "data": { "text/html": [ "
\n", "
\n", "
Loading plot…
\n", "
\n", "
\n", "
\n", "
drag = rotate
wheel = zoom
right-drag = pan
\n", "
\n", "
\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.structure(struct_name='ferrite')\n", "project.display.structure(struct_name='austenite')" ] }, { "cell_type": "markdown", "id": "41", "metadata": {}, "source": [ "### Display Pattern" ] }, { "cell_type": "code", "execution_count": 27, "id": "42", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:26.049331Z", "iopub.status.busy": "2026-06-30T22:30:26.049166Z", "iopub.status.idle": "2026-06-30T22:30:26.611365Z", "shell.execute_reply": "2026-06-30T22:30:26.610646Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(expt_name='expt_s2')" ] }, { "cell_type": "code", "execution_count": 28, "id": "43", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:26.617855Z", "iopub.status.busy": "2026-06-30T22:30:26.617673Z", "iopub.status.idle": "2026-06-30T22:30:27.161149Z", "shell.execute_reply": "2026-06-30T22:30:27.160521Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(expt_name='expt_n2')" ] }, { "cell_type": "markdown", "id": "44", "metadata": {}, "source": [ "## 🚀 Perform Analysis\n", "\n", "This section shows the analysis process, including how to set up\n", "calculation and fitting engines.\n", "\n", "### Set Fit Mode" ] }, { "cell_type": "code", "execution_count": 29, "id": "45", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.167416Z", "iopub.status.busy": "2026-06-30T22:30:27.167230Z", "iopub.status.idle": "2026-06-30T22:30:27.174412Z", "shell.execute_reply": "2026-06-30T22:30:27.173365Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mFitting Mode types\u001b[0m\n" ] }, { "data": { "text/html": [ "
TypeDescription
1jointFit several experiments together with shared parameters.
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.analysis.fitting_mode.show_supported()" ] }, { "cell_type": "code", "execution_count": 30, "id": "46", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.176000Z", "iopub.status.busy": "2026-06-30T22:30:27.175836Z", "iopub.status.idle": "2026-06-30T22:30:27.180901Z", "shell.execute_reply": "2026-06-30T22:30:27.180127Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mFitting mode changed to\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "joint\n" ] } ], "source": [ "project.analysis.fitting_mode.type = 'joint'" ] }, { "cell_type": "markdown", "id": "47", "metadata": {}, "source": [ "### Set Free Parameters" ] }, { "cell_type": "code", "execution_count": 31, "id": "48", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.182504Z", "iopub.status.busy": "2026-06-30T22:30:27.182340Z", "iopub.status.idle": "2026-06-30T22:30:27.330652Z", "shell.execute_reply": "2026-06-30T22:30:27.329845Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mFittable parameters for all structures \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36m🧩 data blocks\u001b[0m\u001b[1;36m)\u001b[0m\n" ] }, { "data": { "text/html": [ "
datablockcategoryentryparametervalueuncertaintyunitsfree
1ferritecelllength_a2.88600ÅFalse
2ferriteatom_siteFeoccupancy1.00000False
3ferriteatom_siteFeadp_iso1.00000ŲFalse
4austenitecelllength_a3.64680ÅFalse
5austeniteatom_siteFeoccupancy1.00000False
6austeniteatom_siteFeadp_iso1.00000ŲFalse
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mFittable parameters for all experiments \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36m🔬 data blocks\u001b[0m\u001b[1;36m)\u001b[0m\n" ] }, { "data": { "text/html": [ "
datablockcategoryentryparametervalueuncertaintyunitsfree
1expt_s2linked_structureferritescale285.00000False
2expt_s2linked_structureaustenitescale68.00000False
3expt_s2peakbroad_lorentz_gamma_00.00000μsFalse
4expt_s2peakbroad_lorentz_gamma_10.00000μs/ÅFalse
5expt_s2peakbroad_lorentz_gamma_20.00000μs²/ŲFalse
6expt_s2peakbroad_lorentz_size_l0.00000μs²/ŲFalse
7expt_s2peakbroad_lorentz_strain_l0.00000μs/ÅFalse
8expt_s2peakbroad_gauss_sigma_0300.00000μs²False
9expt_s2peakbroad_gauss_sigma_11200.00000μs/ÅFalse
10expt_s2peakbroad_gauss_sigma_2900.00000μs²/ŲFalse
11expt_s2peakbroad_gauss_size_g0.00000μs²/ŲFalse
12expt_s2peakbroad_gauss_strain_g0.00000μs/ÅFalse
13expt_s2instrumenttwotheta_bank90.00000degFalse
14expt_s2instrumentd_to_tof_offset0.00000μsFalse
15expt_s2instrumentd_to_tof_linear54902.18695μs/ÅFalse
16expt_s2instrumentd_to_tof_quadratic0.00000μs/ŲFalse
17expt_s2instrumentd_to_tof_reciprocal0.00000μs·ÅFalse
18expt_s2background1intensity0.00154False
19expt_s2background2intensity0.16817False
20expt_s2background3intensity0.18318False
21expt_s2background4intensity0.17817False
22expt_s2background5intensity0.29095False
23expt_s2background6intensity0.30387False
24expt_s2background7intensity0.25310False
25expt_s2background8intensity0.22573False
26expt_s2background9intensity0.20324False
27expt_s2background10intensity0.19453False
28expt_s2background11intensity0.17297False
29expt_s2background12intensity0.24903False
30expt_s2background13intensity0.34182False
31expt_s2background14intensity0.39039False
32expt_s2background15intensity0.36120False
33expt_s2background16intensity0.62067False
34expt_s2background17intensity1.22400False
35expt_s2background18intensity1.32442False
36expt_s2background19intensity1.12711False
37expt_s2background20intensity0.00952False
38expt_n2linked_structureferritescale285.00000False
39expt_n2linked_structureaustenitescale68.00000False
40expt_n2peakbroad_lorentz_gamma_00.00000μsFalse
41expt_n2peakbroad_lorentz_gamma_10.00000μs/ÅFalse
42expt_n2peakbroad_lorentz_gamma_20.00000μs²/ŲFalse
43expt_n2peakbroad_lorentz_size_l0.00000μs²/ŲFalse
44expt_n2peakbroad_lorentz_strain_l0.00000μs/ÅFalse
45expt_n2peakbroad_gauss_sigma_0300.00000μs²False
46expt_n2peakbroad_gauss_sigma_11200.00000μs/ÅFalse
47expt_n2peakbroad_gauss_sigma_2900.00000μs²/ŲFalse
48expt_n2peakbroad_gauss_size_g0.00000μs²/ŲFalse
49expt_n2peakbroad_gauss_strain_g0.00000μs/ÅFalse
50expt_n2instrumenttwotheta_bank90.00000degFalse
51expt_n2instrumentd_to_tof_offset0.00000μsFalse
52expt_n2instrumentd_to_tof_linear54902.18695μs/ÅFalse
53expt_n2instrumentd_to_tof_quadratic0.00000μs/ŲFalse
54expt_n2instrumentd_to_tof_reciprocal0.00000μs·ÅFalse
55expt_n2background1intensity0.00154False
56expt_n2background2intensity0.16817False
57expt_n2background3intensity0.18318False
58expt_n2background4intensity0.17817False
59expt_n2background5intensity0.29095False
60expt_n2background6intensity0.30387False
61expt_n2background7intensity0.25310False
62expt_n2background8intensity0.22573False
63expt_n2background9intensity0.20324False
64expt_n2background10intensity0.19453False
65expt_n2background11intensity0.17297False
66expt_n2background12intensity0.24903False
67expt_n2background13intensity0.34182False
68expt_n2background14intensity0.39039False
69expt_n2background15intensity0.36120False
70expt_n2background16intensity0.62067False
71expt_n2background17intensity1.22400False
72expt_n2background18intensity1.32442False
73expt_n2background19intensity1.12711False
74expt_n2background20intensity0.00952False
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.parameters.fittable()" ] }, { "cell_type": "code", "execution_count": 32, "id": "49", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.332256Z", "iopub.status.busy": "2026-06-30T22:30:27.332056Z", "iopub.status.idle": "2026-06-30T22:30:27.335438Z", "shell.execute_reply": "2026-06-30T22:30:27.334680Z" } }, "outputs": [], "source": [ "ferrite.atom_sites['Fe'].adp_iso.free = True\n", "austenite.atom_sites['Fe'].adp_iso.free = True" ] }, { "cell_type": "code", "execution_count": 33, "id": "50", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.336846Z", "iopub.status.busy": "2026-06-30T22:30:27.336700Z", "iopub.status.idle": "2026-06-30T22:30:27.340947Z", "shell.execute_reply": "2026-06-30T22:30:27.340213Z" } }, "outputs": [], "source": [ "expt_s2.linked_structures['ferrite'].scale.free = True\n", "expt_s2.linked_structures['austenite'].scale.free = True\n", "\n", "expt_s2.peak.broad_gauss_sigma_0.free = True\n", "expt_s2.peak.broad_gauss_sigma_1.free = True\n", "expt_s2.peak.broad_gauss_sigma_2.free = True\n", "expt_s2.peak.broad_lorentz_gamma_0.free = True\n", "\n", "expt_s2.instrument.calib_d_to_tof_offset.free = True\n", "\n", "for segment in expt_s2.background:\n", " segment.intensity.free = True" ] }, { "cell_type": "code", "execution_count": 34, "id": "51", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.342589Z", "iopub.status.busy": "2026-06-30T22:30:27.342433Z", "iopub.status.idle": "2026-06-30T22:30:27.346832Z", "shell.execute_reply": "2026-06-30T22:30:27.345960Z" } }, "outputs": [], "source": [ "expt_n2.linked_structures['ferrite'].scale.free = True\n", "expt_n2.linked_structures['austenite'].scale.free = True\n", "\n", "expt_n2.peak.broad_gauss_sigma_0.free = True\n", "expt_n2.peak.broad_gauss_sigma_1.free = True\n", "expt_n2.peak.broad_gauss_sigma_2.free = True\n", "expt_n2.peak.broad_lorentz_gamma_0.free = True\n", "\n", "expt_n2.instrument.calib_d_to_tof_offset.free = True\n", "\n", "for segment in expt_n2.background:\n", " segment.intensity.free = True" ] }, { "cell_type": "markdown", "id": "52", "metadata": {}, "source": [ "### Add Constraints" ] }, { "cell_type": "code", "execution_count": 35, "id": "53", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.348479Z", "iopub.status.busy": "2026-06-30T22:30:27.348316Z", "iopub.status.idle": "2026-06-30T22:30:27.353299Z", "shell.execute_reply": "2026-06-30T22:30:27.352593Z" } }, "outputs": [], "source": [ "project.analysis.aliases.create(\n", " id='s2_ferrite_scale', param=expt_s2.linked_structures['ferrite'].scale\n", ")\n", "project.analysis.aliases.create(\n", " id='s2_austenite_scale', param=expt_s2.linked_structures['austenite'].scale\n", ")\n", "\n", "project.analysis.aliases.create(\n", " id='n2_ferrite_scale', param=expt_n2.linked_structures['ferrite'].scale\n", ")\n", "project.analysis.aliases.create(\n", " id='n2_austenite_scale', param=expt_n2.linked_structures['austenite'].scale\n", ")\n", "\n", "project.analysis.constraints.create(expression='n2_ferrite_scale = s2_ferrite_scale')\n", "project.analysis.constraints.create(expression='n2_austenite_scale = s2_austenite_scale')" ] }, { "cell_type": "markdown", "id": "54", "metadata": {}, "source": [ "### Run Fitting\n", "\n", "Run full fitting with all free parameters." ] }, { "cell_type": "code", "execution_count": 36, "id": "55", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:27.355074Z", "iopub.status.busy": "2026-06-30T22:30:27.354923Z", "iopub.status.idle": "2026-06-30T22:30:49.717284Z", "shell.execute_reply": "2026-06-30T22:30:49.716756Z" } }, "outputs": [ { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function() {\n", " const button = document.getElementById('ed-fit-stop-74d8eee16c5440ed8d51879e7eb0b629-button');\n", " const status = document.getElementById('ed-fit-stop-74d8eee16c5440ed8d51879e7eb0b629-status');\n", " const kernelId = '';\n", " if (!button) {\n", " return;\n", " }\n", "\n", " function setStatus(text) {\n", " if (status) {\n", " status.textContent = text;\n", " }\n", " }\n", "\n", " function pageConfig() {\n", " const element = document.getElementById('jupyter-config-data');\n", " if (!element || !element.textContent) {\n", " return {};\n", " }\n", " try {\n", " return JSON.parse(element.textContent);\n", " } catch (error) {\n", " return {};\n", " }\n", " }\n", "\n", " function baseUrl(config) {\n", " const configured = config.baseUrl || config.base_url ||\n", " (window.Jupyter && Jupyter.notebook && Jupyter.notebook.base_url);\n", " if (configured) {\n", " return configured.endsWith('/') ? configured : configured + '/';\n", " }\n", " const markers = ['/lab/', '/notebooks/', '/tree/'];\n", " for (const marker of markers) {\n", " const index = window.location.pathname.indexOf(marker);\n", " if (index >= 0) {\n", " return window.location.pathname.slice(0, index + 1);\n", " }\n", " }\n", " return '/';\n", " }\n", "\n", " function token(config) {\n", " return config.token || new URLSearchParams(window.location.search).get('token') || '';\n", " }\n", "\n", " function cookie(name) {\n", " const prefix = name + '=';\n", " for (const part of document.cookie.split(';')) {\n", " const trimmed = part.trim();\n", " if (trimmed.startsWith(prefix)) {\n", " return decodeURIComponent(trimmed.slice(prefix.length));\n", " }\n", " }\n", " return '';\n", " }\n", "\n", " function notebookPath() {\n", " const decoded = decodeURIComponent(window.location.pathname);\n", " const markers = ['/lab/tree/', '/notebooks/', '/tree/'];\n", " for (const marker of markers) {\n", " const index = decoded.indexOf(marker);\n", " if (index >= 0) {\n", " return decoded.slice(index + marker.length);\n", " }\n", " }\n", " return '';\n", " }\n", "\n", " async function kernelFromSessions(config) {\n", " const url = new URL(baseUrl(config) + 'api/sessions', window.location.origin);\n", " const authToken = token(config);\n", " if (authToken) {\n", " url.searchParams.set('token', authToken);\n", " }\n", " const response = await fetch(url, {credentials: 'same-origin'});\n", " if (!response.ok) {\n", " return '';\n", " }\n", " const sessions = await response.json();\n", " const path = notebookPath();\n", " const session = sessions.find((item) => item.path === path) || sessions[0];\n", " return session && session.kernel ? session.kernel.id : '';\n", " }\n", "\n", " async function interruptKernel(config, resolvedKernelId) {\n", " const url = new URL(\n", " baseUrl(config) + 'api/kernels/' + resolvedKernelId + '/interrupt',\n", " window.location.origin\n", " );\n", " const authToken = token(config);\n", " if (authToken) {\n", " url.searchParams.set('token', authToken);\n", " }\n", " const xsrfToken = cookie('_xsrf');\n", " const headers = {};\n", " if (xsrfToken) {\n", " headers['X-XSRFToken'] = xsrfToken;\n", " }\n", " const response = await fetch(url, {\n", " method: 'POST',\n", " credentials: 'same-origin',\n", " headers: headers\n", " });\n", " return response.ok;\n", " }\n", "\n", " button.addEventListener('click', async function() {\n", " button.disabled = true;\n", " setStatus('Stopping...');\n", " const config = pageConfig();\n", " try {\n", " const resolvedKernelId = kernelId || await kernelFromSessions(config);\n", " if (!resolvedKernelId) {\n", " throw new Error('Could not resolve the current kernel id.');\n", " }\n", " const interrupted = await interruptKernel(config, resolvedKernelId);\n", " if (!interrupted) {\n", " throw new Error('Jupyter Server rejected the interrupt request.');\n", " }\n", " setStatus('Interrupt sent...');\n", " } catch (error) {\n", " button.disabled = false;\n", " setStatus('Use Kernel > Interrupt to stop this fit.');\n", " }\n", " });\n", "})();\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mUsing all experiments 🔬 \u001b[0m\u001b[1;36m[\u001b[0m\u001b[32m'expt_s2'\u001b[0m\u001b[1;36m, \u001b[0m\u001b[32m'expt_n2'\u001b[0m\u001b[1;36m]\u001b[0m\u001b[1;36m for \u001b[0m\u001b[32m'joint'\u001b[0m\u001b[1;36m 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 progress:\n" ] }, { "data": { "text/html": [ "
iterationtime (s)χ²change / status
110.06589.93
2583.1632.9894.4% ↓
31136.3812.9660.7% ↓
420411.4312.85
529216.4512.85
633421.7112.85
" ], "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;36m12.85\u001b[0m at iteration \u001b[1;36m333\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mSaving project 📦 \u001b[0m\u001b[32m'beer_mcstas'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/calibrate-beer-ess'\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 project.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 structures/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 ferrite.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 austenite.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 experiments/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 expt_s2.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 expt_n2.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 analysis/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 analysis.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "└── 📁 reports/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " └── 📄 beer_mcstas.html\n" ] } ], "source": [ "project.analysis.fit()" ] }, { "cell_type": "markdown", "id": "56", "metadata": {}, "source": [ "Fix background and run fitting again." ] }, { "cell_type": "code", "execution_count": 37, "id": "57", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:49.719748Z", "iopub.status.busy": "2026-06-30T22:30:49.719586Z", "iopub.status.idle": "2026-06-30T22:30:49.723567Z", "shell.execute_reply": "2026-06-30T22:30:49.722959Z" } }, "outputs": [], "source": [ "for segment in expt_s2.background:\n", " segment.intensity.free = False\n", "for segment in expt_n2.background:\n", " segment.intensity.free = False" ] }, { "cell_type": "code", "execution_count": 38, "id": "58", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:49.725702Z", "iopub.status.busy": "2026-06-30T22:30:49.725550Z", "iopub.status.idle": "2026-06-30T22:30:51.542842Z", "shell.execute_reply": "2026-06-30T22:30:51.542046Z" } }, "outputs": [ { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function() {\n", " const button = document.getElementById('ed-fit-stop-fb7b575169384bce9387c9d1532ae773-button');\n", " const status = document.getElementById('ed-fit-stop-fb7b575169384bce9387c9d1532ae773-status');\n", " const kernelId = '';\n", " if (!button) {\n", " return;\n", " }\n", "\n", " function setStatus(text) {\n", " if (status) {\n", " status.textContent = text;\n", " }\n", " }\n", "\n", " function pageConfig() {\n", " const element = document.getElementById('jupyter-config-data');\n", " if (!element || !element.textContent) {\n", " return {};\n", " }\n", " try {\n", " return JSON.parse(element.textContent);\n", " } catch (error) {\n", " return {};\n", " }\n", " }\n", "\n", " function baseUrl(config) {\n", " const configured = config.baseUrl || config.base_url ||\n", " (window.Jupyter && Jupyter.notebook && Jupyter.notebook.base_url);\n", " if (configured) {\n", " return configured.endsWith('/') ? configured : configured + '/';\n", " }\n", " const markers = ['/lab/', '/notebooks/', '/tree/'];\n", " for (const marker of markers) {\n", " const index = window.location.pathname.indexOf(marker);\n", " if (index >= 0) {\n", " return window.location.pathname.slice(0, index + 1);\n", " }\n", " }\n", " return '/';\n", " }\n", "\n", " function token(config) {\n", " return config.token || new URLSearchParams(window.location.search).get('token') || '';\n", " }\n", "\n", " function cookie(name) {\n", " const prefix = name + '=';\n", " for (const part of document.cookie.split(';')) {\n", " const trimmed = part.trim();\n", " if (trimmed.startsWith(prefix)) {\n", " return decodeURIComponent(trimmed.slice(prefix.length));\n", " }\n", " }\n", " return '';\n", " }\n", "\n", " function notebookPath() {\n", " const decoded = decodeURIComponent(window.location.pathname);\n", " const markers = ['/lab/tree/', '/notebooks/', '/tree/'];\n", " for (const marker of markers) {\n", " const index = decoded.indexOf(marker);\n", " if (index >= 0) {\n", " return decoded.slice(index + marker.length);\n", " }\n", " }\n", " return '';\n", " }\n", "\n", " async function kernelFromSessions(config) {\n", " const url = new URL(baseUrl(config) + 'api/sessions', window.location.origin);\n", " const authToken = token(config);\n", " if (authToken) {\n", " url.searchParams.set('token', authToken);\n", " }\n", " const response = await fetch(url, {credentials: 'same-origin'});\n", " if (!response.ok) {\n", " return '';\n", " }\n", " const sessions = await response.json();\n", " const path = notebookPath();\n", " const session = sessions.find((item) => item.path === path) || sessions[0];\n", " return session && session.kernel ? session.kernel.id : '';\n", " }\n", "\n", " async function interruptKernel(config, resolvedKernelId) {\n", " const url = new URL(\n", " baseUrl(config) + 'api/kernels/' + resolvedKernelId + '/interrupt',\n", " window.location.origin\n", " );\n", " const authToken = token(config);\n", " if (authToken) {\n", " url.searchParams.set('token', authToken);\n", " }\n", " const xsrfToken = cookie('_xsrf');\n", " const headers = {};\n", " if (xsrfToken) {\n", " headers['X-XSRFToken'] = xsrfToken;\n", " }\n", " const response = await fetch(url, {\n", " method: 'POST',\n", " credentials: 'same-origin',\n", " headers: headers\n", " });\n", " return response.ok;\n", " }\n", "\n", " button.addEventListener('click', async function() {\n", " button.disabled = true;\n", " setStatus('Stopping...');\n", " const config = pageConfig();\n", " try {\n", " const resolvedKernelId = kernelId || await kernelFromSessions(config);\n", " if (!resolvedKernelId) {\n", " throw new Error('Could not resolve the current kernel id.');\n", " }\n", " const interrupted = await interruptKernel(config, resolvedKernelId);\n", " if (!interrupted) {\n", " throw new Error('Jupyter Server rejected the interrupt request.');\n", " }\n", " setStatus('Interrupt sent...');\n", " } catch (error) {\n", " button.disabled = false;\n", " setStatus('Use Kernel > Interrupt to stop this fit.');\n", " }\n", " });\n", "})();\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mUsing all experiments 🔬 \u001b[0m\u001b[1;36m[\u001b[0m\u001b[32m'expt_s2'\u001b[0m\u001b[1;36m, \u001b[0m\u001b[32m'expt_n2'\u001b[0m\u001b[1;36m]\u001b[0m\u001b[1;36m for \u001b[0m\u001b[32m'joint'\u001b[0m\u001b[1;36m 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 progress:\n" ] }, { "data": { "text/html": [ "
iterationtime (s)χ²change / status
110.0612.76
2191.1612.76
" ], "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;36m12.76\u001b[0m at iteration \u001b[1;36m18\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Fitting complete.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;36mSaving project 📦 \u001b[0m\u001b[32m'beer_mcstas'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/calibrate-beer-ess'\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📄 project.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 structures/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 ferrite.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 austenite.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 experiments/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 expt_s2.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 expt_n2.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "├── 📁 analysis/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "│ └── 📄 analysis.edi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "└── 📁 reports/\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " └── 📄 beer_mcstas.html\n" ] } ], "source": [ "project.analysis.fit()" ] }, { "cell_type": "markdown", "id": "59", "metadata": {}, "source": [ "Show fit results and parameter correlations." ] }, { "cell_type": "code", "execution_count": 39, "id": "60", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:51.544374Z", "iopub.status.busy": "2026-06-30T22:30:51.544216Z", "iopub.status.idle": "2026-06-30T22:30:52.548411Z", "shell.execute_reply": "2026-06-30T22:30:52.547817Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "⚙️ Settings used:\n" ] }, { "data": { "text/html": [ "
NameValueDescription
1max_iterations1000Maximum solver iterations.
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "📋 Least-squares fit results:\n" ] }, { "data": { "text/html": [ "
MetricValue
1🧪 Minimizerlmfit (leastsq)
2✅ Overall statussuccess
3⏱️ Fitting time (seconds)1.16
4🔁 Iterations16
5📏 Goodness-of-fit (reduced χ²)12.76
6📏 R-factor (Rf, %)4.97
7📏 R-factor squared (Rf², %)3.89
8📏 Weighted R-factor (wR, %)3.40
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "📈 Refined parameters:\n" ] }, { "data": { "text/html": [ "
datablockcategoryentryparameterunitsstartvalues.u.change
1ferriteatom_siteFeadp_isoŲ1.71911.71910.01260.00 % ↑
2austeniteatom_siteFeadp_isoŲ1.71261.71260.01180.00 % ↑
3expt_s2linked_structureferritescale284.7197284.72010.83540.00 % ↑
4expt_s2linked_structureaustenitescale67.913267.91330.16830.00 % ↑
5expt_s2peakbroad_lorentz_gamma_0μs5.23515.23510.14700.00 % ↑
6expt_s2peakbroad_gauss_sigma_0μs²884.3308884.352456.29930.00 % ↑
7expt_s2peakbroad_gauss_sigma_1μs/Å1284.16571284.145556.24200.00 % ↓
8expt_s2peakbroad_gauss_sigma_2μs²/Ų311.1710311.174711.19450.00 % ↑
9expt_s2instrumentd_to_tof_offsetμs-10.4533-10.45340.11760.00 % ↑
10expt_n2peakbroad_lorentz_gamma_0μs5.24295.24290.14750.00 % ↑
11expt_n2peakbroad_gauss_sigma_0μs²921.6972921.718756.85820.00 % ↑
12expt_n2peakbroad_gauss_sigma_1μs/Å1226.53631226.515956.81310.00 % ↓
13expt_n2peakbroad_gauss_sigma_2μs²/Ų329.0370329.040811.31130.00 % ↑
14expt_n2instrumentd_to_tof_offsetμs-2.2574-2.25740.11780.00 % ↑
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
• start = parameter value before refinement
• value = refined value from least-squares minimization
• s.u. = standard uncertainty (one sigma), from the covariance matrix
• change = relative change from start, in %; ↑ = increase, ↓ = decrease
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "
\n", "
Loading plot…
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.fit.results()\n", "project.display.fit.correlations()" ] }, { "cell_type": "markdown", "id": "61", "metadata": {}, "source": [ "### Display Pattern\n", "\n", "Show full range in TOF." ] }, { "cell_type": "code", "execution_count": 40, "id": "62", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:52.549916Z", "iopub.status.busy": "2026-06-30T22:30:52.549743Z", "iopub.status.idle": "2026-06-30T22:30:52.616395Z", "shell.execute_reply": "2026-06-30T22:30:52.615587Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(expt_name='expt_s2')" ] }, { "cell_type": "code", "execution_count": 41, "id": "63", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:52.620274Z", "iopub.status.busy": "2026-06-30T22:30:52.620078Z", "iopub.status.idle": "2026-06-30T22:30:53.907220Z", "shell.execute_reply": "2026-06-30T22:30:53.906581Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(expt_name='expt_n2')" ] }, { "cell_type": "markdown", "id": "64", "metadata": {}, "source": [ "Show selected peaks in d-spacing." ] }, { "cell_type": "code", "execution_count": 42, "id": "65", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:53.913317Z", "iopub.status.busy": "2026-06-30T22:30:53.913058Z", "iopub.status.idle": "2026-06-30T22:30:53.967646Z", "shell.execute_reply": "2026-06-30T22:30:53.966810Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(\n", " expt_name='expt_s2',\n", " x='d_spacing',\n", " x_min=2.08,\n", " x_max=2.13,\n", ")" ] }, { "cell_type": "code", "execution_count": 43, "id": "66", "metadata": { "execution": { "iopub.execute_input": "2026-06-30T22:30:53.969302Z", "iopub.status.busy": "2026-06-30T22:30:53.969144Z", "iopub.status.idle": "2026-06-30T22:30:54.969756Z", "shell.execute_reply": "2026-06-30T22:30:54.969124Z" } }, "outputs": [ { "data": { "text/html": [ "
Loading plot…
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "project.display.pattern(\n", " expt_name='expt_n2',\n", " x='d_spacing',\n", " x_min=2.08,\n", " x_max=2.13,\n", ")" ] } ], "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.14.5" } }, "nbformat": 4, "nbformat_minor": 5 }