{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "0",
"metadata": {
"execution": {
"iopub.execute_input": "2026-08-18T18:34:40.292556Z",
"iopub.status.busy": "2026-08-18T18:34:40.292392Z",
"iopub.status.idle": "2026-08-18T18:34:40.302599Z",
"shell.execute_reply": "2026-08-18T18:34:40.302159Z"
},
"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.20.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-08-18T18:34:40.307575Z",
"iopub.status.busy": "2026-08-18T18:34:40.304445Z",
"iopub.status.idle": "2026-08-18T18:34:43.471269Z",
"shell.execute_reply": "2026-08-18T18:34:43.470200Z"
}
},
"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-08-18T18:34:43.472994Z",
"iopub.status.busy": "2026-08-18T18:34:43.472748Z",
"iopub.status.idle": "2026-08-18T18:34:43.479225Z",
"shell.execute_reply": "2026-08-18T18:34:43.478512Z"
}
},
"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-08-18T18:34:43.481007Z",
"iopub.status.busy": "2026-08-18T18:34:43.480855Z",
"iopub.status.idle": "2026-08-18T18:34:43.485146Z",
"shell.execute_reply": "2026-08-18T18:34:43.484463Z"
}
},
"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-08-18T18:34:43.486555Z",
"iopub.status.busy": "2026-08-18T18:34:43.486384Z",
"iopub.status.idle": "2026-08-18T18:34:43.824309Z",
"shell.execute_reply": "2026-08-18T18:34:43.823530Z"
}
},
"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-08-18T18:34:43.826315Z",
"iopub.status.busy": "2026-08-18T18:34:43.826030Z",
"iopub.status.idle": "2026-08-18T18:34:44.309441Z",
"shell.execute_reply": "2026-08-18T18:34:44.308581Z"
}
},
"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-08-18T18:34:44.311091Z",
"iopub.status.busy": "2026-08-18T18:34:44.310918Z",
"iopub.status.idle": "2026-08-18T18:34:44.556821Z",
"shell.execute_reply": "2026-08-18T18:34:44.555768Z"
}
},
"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-08-18T18:34:44.558578Z",
"iopub.status.busy": "2026-08-18T18:34:44.558377Z",
"iopub.status.idle": "2026-08-18T18:34:44.562562Z",
"shell.execute_reply": "2026-08-18T18:34:44.561754Z"
}
},
"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-08-18T18:34:44.564366Z",
"iopub.status.busy": "2026-08-18T18:34:44.564206Z",
"iopub.status.idle": "2026-08-18T18:34:44.568008Z",
"shell.execute_reply": "2026-08-18T18:34:44.567298Z"
}
},
"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-08-18T18:34:44.569867Z",
"iopub.status.busy": "2026-08-18T18:34:44.569714Z",
"iopub.status.idle": "2026-08-18T18:34:44.578500Z",
"shell.execute_reply": "2026-08-18T18:34:44.577774Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mPeak types\u001b[0m\n"
]
},
{
"data": {
"text/html": [
"
| | Type | Description |
|---|
| 1 | | pseudo-voigt | TOF non-convoluted pseudo-Voigt profile |
|---|
| 2 | * | jorgensen | TOF Jorgensen profile: back-to-back exponentials ⊗ Gaussian |
|---|
| 3 | | jorgensen-von-dreele | TOF Jorgensen-Von Dreele profile: back-to-back exponentials ⊗ pseudo-Voigt |
|---|
| 4 | | double-jorgensen-von-dreele | TOF 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-08-18T18:34:44.580250Z",
"iopub.status.busy": "2026-08-18T18:34:44.580083Z",
"iopub.status.idle": "2026-08-18T18:34:44.588252Z",
"shell.execute_reply": "2026-08-18T18:34:44.587464Z"
}
},
"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=0.0 \n",
" • broad_lorentz_strain=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-08-18T18:34:44.589817Z",
"iopub.status.busy": "2026-08-18T18:34:44.589636Z",
"iopub.status.idle": "2026-08-18T18:34:44.593505Z",
"shell.execute_reply": "2026-08-18T18:34:44.592642Z"
}
},
"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-08-18T18:34:44.595023Z",
"iopub.status.busy": "2026-08-18T18:34:44.594846Z",
"iopub.status.idle": "2026-08-18T18:34:44.602373Z",
"shell.execute_reply": "2026-08-18T18:34:44.601711Z"
}
},
"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=0.0 \n",
" • broad_lorentz_strain=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-08-18T18:34:44.604079Z",
"iopub.status.busy": "2026-08-18T18:34:44.603881Z",
"iopub.status.idle": "2026-08-18T18:34:44.607399Z",
"shell.execute_reply": "2026-08-18T18:34:44.606582Z"
}
},
"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-08-18T18:34:44.608943Z",
"iopub.status.busy": "2026-08-18T18:34:44.608770Z",
"iopub.status.idle": "2026-08-18T18:34:44.616024Z",
"shell.execute_reply": "2026-08-18T18:34:44.615193Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mBackground types\u001b[0m\n"
]
},
{
"data": {
"text/html": [
" | | Type | Description |
|---|
| 1 | | chebyshev | Chebyshev polynomial background |
|---|
| 2 | * | line-segment | Linear 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-08-18T18:34:44.617536Z",
"iopub.status.busy": "2026-08-18T18:34:44.617353Z",
"iopub.status.idle": "2026-08-18T18:34:44.644977Z",
"shell.execute_reply": "2026-08-18T18:34:44.644255Z"
}
},
"outputs": [],
"source": [
"expt_s2.background.auto_estimate()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "25",
"metadata": {
"execution": {
"iopub.execute_input": "2026-08-18T18:34:44.646961Z",
"iopub.status.busy": "2026-08-18T18:34:44.646794Z",
"iopub.status.idle": "2026-08-18T18:34:44.653562Z",
"shell.execute_reply": "2026-08-18T18:34:44.652737Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mLine-segment background points\u001b[0m\n"
]
},
{
"data": {
"text/html": [
" | Position | Intensity |
|---|
| 1 | 40094.52340 | 0.00154 |
|---|
| 2 | 48089.84890 | 0.16817 |
|---|
| 3 | 51976.02300 | 0.18318 |
|---|
| 4 | 54301.35670 | 0.17817 |
|---|
| 5 | 58729.04700 | 0.29095 |
|---|
| 6 | 62710.78280 | 0.30387 |
|---|
| 7 | 67711.84290 | 0.25310 |
|---|
| 8 | 73158.85750 | 0.22573 |
|---|
| 9 | 76439.80780 | 0.20324 |
|---|
| 10 | 81249.74460 | 0.19453 |
|---|
| 11 | 85263.33430 | 0.17297 |
|---|
| 12 | 96157.36350 | 0.24903 |
|---|
| 13 | 98132.30440 | 0.34182 |
|---|
| 14 | 102368.87130 | 0.39039 |
|---|
| 15 | 104248.25060 | 0.36120 |
|---|
| 16 | 108771.50250 | 0.62067 |
|---|
| 17 | 111606.49840 | 1.22400 |
|---|
| 18 | 112721.38440 | 1.32442 |
|---|
| 19 | 115715.64970 | 1.12711 |
|---|
| 20 | 135592.47480 | 0.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-08-18T18:34:44.655187Z",
"iopub.status.busy": "2026-08-18T18:34:44.654989Z",
"iopub.status.idle": "2026-08-18T18:34:44.666358Z",
"shell.execute_reply": "2026-08-18T18:34:44.665509Z"
}
},
"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-08-18T18:34:44.668108Z",
"iopub.status.busy": "2026-08-18T18:34:44.667936Z",
"iopub.status.idle": "2026-08-18T18:34:44.671252Z",
"shell.execute_reply": "2026-08-18T18:34:44.670539Z"
}
},
"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-08-18T18:34:44.673089Z",
"iopub.status.busy": "2026-08-18T18:34:44.672920Z",
"iopub.status.idle": "2026-08-18T18:34:44.676059Z",
"shell.execute_reply": "2026-08-18T18:34:44.675343Z"
}
},
"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-08-18T18:34:44.677745Z",
"iopub.status.busy": "2026-08-18T18:34:44.677530Z",
"iopub.status.idle": "2026-08-18T18:34:44.681684Z",
"shell.execute_reply": "2026-08-18T18:34:44.680790Z"
}
},
"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-08-18T18:34:44.683332Z",
"iopub.status.busy": "2026-08-18T18:34:44.683185Z",
"iopub.status.idle": "2026-08-18T18:34:44.686516Z",
"shell.execute_reply": "2026-08-18T18:34:44.685729Z"
}
},
"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-08-18T18:34:44.688091Z",
"iopub.status.busy": "2026-08-18T18:34:44.687866Z",
"iopub.status.idle": "2026-08-18T18:34:45.281605Z",
"shell.execute_reply": "2026-08-18T18:34:45.280747Z"
}
},
"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",
"├── 📁 structures/\n",
"├── 📁 experiments/\n",
"├── 📁 analysis/\n",
"│ └── 📄 analysis.edi\n",
"└── 📁 reports/\n",
" └── 📄 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-08-18T18:34:45.283521Z",
"iopub.status.busy": "2026-08-18T18:34:45.283350Z",
"iopub.status.idle": "2026-08-18T18:34:45.286189Z",
"shell.execute_reply": "2026-08-18T18:34:45.285481Z"
}
},
"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-08-18T18:34:45.287911Z",
"iopub.status.busy": "2026-08-18T18:34:45.287762Z",
"iopub.status.idle": "2026-08-18T18:34:45.290448Z",
"shell.execute_reply": "2026-08-18T18:34:45.289731Z"
}
},
"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-08-18T18:34:45.291856Z",
"iopub.status.busy": "2026-08-18T18:34:45.291709Z",
"iopub.status.idle": "2026-08-18T18:34:45.792677Z",
"shell.execute_reply": "2026-08-18T18:34:45.791801Z"
}
},
"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-08-18T18:34:45.794230Z",
"iopub.status.busy": "2026-08-18T18:34:45.794065Z",
"iopub.status.idle": "2026-08-18T18:34:46.357009Z",
"shell.execute_reply": "2026-08-18T18:34:46.356169Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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-08-18T18:34:46.360868Z",
"iopub.status.busy": "2026-08-18T18:34:46.360706Z",
"iopub.status.idle": "2026-08-18T18:34:46.924343Z",
"shell.execute_reply": "2026-08-18T18:34:46.923499Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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-08-18T18:34:46.928414Z",
"iopub.status.busy": "2026-08-18T18:34:46.928185Z",
"iopub.status.idle": "2026-08-18T18:34:46.936068Z",
"shell.execute_reply": "2026-08-18T18:34:46.935081Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mFitting Mode types\u001b[0m\n"
]
},
{
"data": {
"text/html": [
" | | Type | Description |
|---|
| 1 | | joint | Fit 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-08-18T18:34:46.937623Z",
"iopub.status.busy": "2026-08-18T18:34:46.937430Z",
"iopub.status.idle": "2026-08-18T18:34:46.942182Z",
"shell.execute_reply": "2026-08-18T18:34:46.941386Z"
}
},
"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-08-18T18:34:46.943639Z",
"iopub.status.busy": "2026-08-18T18:34:46.943479Z",
"iopub.status.idle": "2026-08-18T18:34:47.097971Z",
"shell.execute_reply": "2026-08-18T18:34:47.097229Z"
}
},
"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": [
" | datablock | category | entry | parameter | value | uncertainty | units | free |
|---|
| 1 | ferrite | cell | | length_a | 2.88600 | | Å | False |
|---|
| 2 | ferrite | atom_site | Fe | occupancy | 1.00000 | | | False |
|---|
| 3 | ferrite | atom_site | Fe | adp_iso | 1.00000 | | Ų | False |
|---|
| 4 | austenite | cell | | length_a | 3.64680 | | Å | False |
|---|
| 5 | austenite | atom_site | Fe | occupancy | 1.00000 | | | False |
|---|
| 6 | austenite | atom_site | Fe | adp_iso | 1.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": [
""
],
"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-08-18T18:34:47.099948Z",
"iopub.status.busy": "2026-08-18T18:34:47.099778Z",
"iopub.status.idle": "2026-08-18T18:34:47.102786Z",
"shell.execute_reply": "2026-08-18T18:34:47.102047Z"
}
},
"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-08-18T18:34:47.104529Z",
"iopub.status.busy": "2026-08-18T18:34:47.104362Z",
"iopub.status.idle": "2026-08-18T18:34:47.108333Z",
"shell.execute_reply": "2026-08-18T18:34:47.107737Z"
}
},
"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-08-18T18:34:47.110041Z",
"iopub.status.busy": "2026-08-18T18:34:47.109874Z",
"iopub.status.idle": "2026-08-18T18:34:47.114439Z",
"shell.execute_reply": "2026-08-18T18:34:47.113789Z"
}
},
"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-08-18T18:34:47.116281Z",
"iopub.status.busy": "2026-08-18T18:34:47.116090Z",
"iopub.status.idle": "2026-08-18T18:34:47.122112Z",
"shell.execute_reply": "2026-08-18T18:34:47.121223Z"
}
},
"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-08-18T18:34:47.123592Z",
"iopub.status.busy": "2026-08-18T18:34:47.123424Z",
"iopub.status.idle": "2026-08-18T18:35:07.864867Z",
"shell.execute_reply": "2026-08-18T18:35:07.864129Z"
}
},
"outputs": [
{
"data": {
"text/html": [],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"(function() {\n",
" const button = document.getElementById('ed-fit-stop-5bec9b865b2c475eb315ccd8741ae15b-button');\n",
" const status = document.getElementById('ed-fit-stop-5bec9b865b2c475eb315ccd8741ae15b-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": [
" | iteration | time (s) | χ² | change / status |
|---|
| 1 | 1 | 0.05 | 350.70 | |
|---|
| 2 | 58 | 2.87 | 34.88 | 90.1% ↓ |
|---|
| 3 | 113 | 5.64 | 12.86 | 63.1% ↓ |
|---|
| 4 | 205 | 10.66 | 12.85 | |
|---|
| 5 | 297 | 15.67 | 12.85 | |
|---|
| 6 | 334 | 20.67 | 12.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"
]
}
],
"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-08-18T18:35:07.866819Z",
"iopub.status.busy": "2026-08-18T18:35:07.866664Z",
"iopub.status.idle": "2026-08-18T18:35:07.870816Z",
"shell.execute_reply": "2026-08-18T18:35:07.870059Z"
}
},
"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-08-18T18:35:07.872364Z",
"iopub.status.busy": "2026-08-18T18:35:07.872204Z",
"iopub.status.idle": "2026-08-18T18:35:08.996142Z",
"shell.execute_reply": "2026-08-18T18:35:08.995524Z"
}
},
"outputs": [
{
"data": {
"text/html": [],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"(function() {\n",
" const button = document.getElementById('ed-fit-stop-8a46cc976c954c9ea7d57c81ac89bbf5-button');\n",
" const status = document.getElementById('ed-fit-stop-8a46cc976c954c9ea7d57c81ac89bbf5-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": [
" | iteration | time (s) | χ² | change / status |
|---|
| 1 | 1 | 0.06 | 12.76 | |
|---|
| 2 | 19 | 1.07 | 12.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"
]
}
],
"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-08-18T18:35:08.998081Z",
"iopub.status.busy": "2026-08-18T18:35:08.997916Z",
"iopub.status.idle": "2026-08-18T18:35:10.061996Z",
"shell.execute_reply": "2026-08-18T18:35:10.061241Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"⚙️ Settings used:\n"
]
},
{
"data": {
"text/html": [
" | Name | Value | Description |
|---|
| 1 | max_iterations | 1000 | Maximum solver iterations. |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"📋 Least-squares fit results:\n"
]
},
{
"data": {
"text/html": [
" | Metric | Value |
|---|
| 1 | 🧪 Minimizer | lmfit (leastsq) |
|---|
| 2 | ✅ Overall status | success |
|---|
| 3 | ⏱️ Fitting time (seconds) | 1.07 |
|---|
| 4 | 🔁 Iterations | 16 |
|---|
| 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": [
""
],
"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",
""
],
"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-08-18T18:35:10.063448Z",
"iopub.status.busy": "2026-08-18T18:35:10.063287Z",
"iopub.status.idle": "2026-08-18T18:35:10.121916Z",
"shell.execute_reply": "2026-08-18T18:35:10.121092Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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-08-18T18:35:10.124815Z",
"iopub.status.busy": "2026-08-18T18:35:10.124634Z",
"iopub.status.idle": "2026-08-18T18:35:11.158218Z",
"shell.execute_reply": "2026-08-18T18:35:11.157499Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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-08-18T18:35:11.162290Z",
"iopub.status.busy": "2026-08-18T18:35:11.162124Z",
"iopub.status.idle": "2026-08-18T18:35:11.212622Z",
"shell.execute_reply": "2026-08-18T18:35:11.211831Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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-08-18T18:35:11.214176Z",
"iopub.status.busy": "2026-08-18T18:35:11.214012Z",
"iopub.status.idle": "2026-08-18T18:35:12.247085Z",
"shell.execute_reply": "2026-08-18T18:35:12.245718Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"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",
")"
]
},
{
"cell_type": "markdown",
"id": "67",
"metadata": {},
"source": [
"## 💾 Save Project\n",
"\n",
"Save the fitted parameters and analysis results."
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "68",
"metadata": {
"execution": {
"iopub.execute_input": "2026-08-18T18:35:12.249080Z",
"iopub.status.busy": "2026-08-18T18:35:12.248925Z",
"iopub.status.idle": "2026-08-18T18:35:13.133098Z",
"shell.execute_reply": "2026-08-18T18:35:13.132362Z"
}
},
"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",
"├── 📁 structures/\n",
"│ └── 📄 ferrite.edi\n",
"│ └── 📄 austenite.edi\n",
"├── 📁 experiments/\n",
"│ └── 📄 expt_s2.edi\n",
"│ └── 📄 expt_n2.edi\n",
"├── 📁 analysis/\n",
"│ └── 📄 analysis.edi\n",
"└── 📁 reports/\n",
" └── 📄 beer_mcstas.html\n"
]
}
],
"source": [
"project.save()"
]
}
],
"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.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}