{
"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": [
"
| | 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-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": [
" | | 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-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": [
" | 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-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": [
""
],
"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": [
""
],
"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": [
" | | 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-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": [
" | 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-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": [
" | iteration | time (s) | χ² | change / status |
|---|
| 1 | 1 | 0.06 | 589.93 | |
|---|
| 2 | 58 | 3.16 | 32.98 | 94.4% ↓ |
|---|
| 3 | 113 | 6.38 | 12.96 | 60.7% ↓ |
|---|
| 4 | 204 | 11.43 | 12.85 | |
|---|
| 5 | 292 | 16.45 | 12.85 | |
|---|
| 6 | 334 | 21.71 | 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"
]
},
{
"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": [
" | iteration | time (s) | χ² | change / status |
|---|
| 1 | 1 | 0.06 | 12.76 | |
|---|
| 2 | 19 | 1.16 | 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"
]
},
{
"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": [
" | 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.16 |
|---|
| 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-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": [
""
],
"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": [
""
],
"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": [
""
],
"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": [
""
],
"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
}