{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "0",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:47.594883Z",
"iopub.status.busy": "2026-06-30T22:40:47.594666Z",
"iopub.status.idle": "2026-06-30T22:40:47.602279Z",
"shell.execute_reply": "2026-06-30T22:40:47.601450Z"
},
"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": [
"# Bayesian Analysis (`bumps-dream`): LBCO, HRPT\n",
"\n",
"This tutorial demonstrates a practical two-stage workflow for powder\n",
"diffraction analysis with EasyDiffraction.\n",
"\n",
"In the first stage, we run a fast local refinement to obtain a sensible\n",
"point estimate and parameter uncertainties. In the second stage, we use\n",
"these refined values to define fit bounds and then sample the posterior\n",
"distribution with DREAM.\n",
"\n",
"The example uses constant-wavelength neutron powder diffraction data\n",
"for La0.5Ba0.5CoO3 measured on HRPT at PSI.\n",
"\n",
"The goal is not only to obtain a good fit, but also to answer Bayesian\n",
"questions such as:\n",
"\n",
"- Which parameter values are most probable?\n",
"- How broad are the credible intervals?\n",
"- Which parameters are strongly correlated?\n",
"- How much uncertainty propagates into the calculated diffraction\n",
" pattern?"
]
},
{
"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:40:47.604937Z",
"iopub.status.busy": "2026-06-30T22:40:47.604565Z",
"iopub.status.idle": "2026-06-30T22:40:51.901267Z",
"shell.execute_reply": "2026-06-30T22:40:51.900029Z"
}
},
"outputs": [],
"source": [
"import easydiffraction as edi"
]
},
{
"cell_type": "markdown",
"id": "4",
"metadata": {},
"source": [
"## π¦ Define Project\n",
"\n",
"The project object keeps structures, experiments, fit settings, and\n",
"plotting utilities together in a single place. We will build the full\n",
"workflow inside this object.\n",
"\n",
"Save the project to a directory early on so that you can easily reload\n",
"it later if needed."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "5",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:51.902917Z",
"iopub.status.busy": "2026-06-30T22:40:51.902638Z",
"iopub.status.idle": "2026-06-30T22:40:52.247698Z",
"shell.execute_reply": "2026-06-30T22:40:52.246811Z"
}
},
"outputs": [],
"source": [
"project = edi.Project(name='lbco_hrpt_bumps_dream')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.249531Z",
"iopub.status.busy": "2026-06-30T22:40:52.249365Z",
"iopub.status.idle": "2026-06-30T22:40:52.320195Z",
"shell.execute_reply": "2026-06-30T22:40:52.319409Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mSaving project π¦ \u001b[0m\u001b[32m'lbco_hrpt_bumps_dream'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/bayesian-dream-lbco-hrpt'\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": [
" βββ π lbco_hrpt_bumps_dream.html\n"
]
}
],
"source": [
"project.save_as(dir_path='projects/bayesian-dream-lbco-hrpt')"
]
},
{
"cell_type": "markdown",
"id": "7",
"metadata": {},
"source": [
"## π§© Define Structure\n",
"\n",
"We define a simple cubic perovskite model for LBCO. La and Ba share the\n",
"same crystallographic site with equal occupancy, while Co and O occupy\n",
"the remaining ideal perovskite positions."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.321945Z",
"iopub.status.busy": "2026-06-30T22:40:52.321707Z",
"iopub.status.idle": "2026-06-30T22:40:52.327700Z",
"shell.execute_reply": "2026-06-30T22:40:52.327131Z"
}
},
"outputs": [],
"source": [
"project.structures.create(name='lbco')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "9",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.330053Z",
"iopub.status.busy": "2026-06-30T22:40:52.329589Z",
"iopub.status.idle": "2026-06-30T22:40:52.334314Z",
"shell.execute_reply": "2026-06-30T22:40:52.332928Z"
}
},
"outputs": [],
"source": [
"structure = project.structures['lbco']"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "10",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.336664Z",
"iopub.status.busy": "2026-06-30T22:40:52.336448Z",
"iopub.status.idle": "2026-06-30T22:40:52.345344Z",
"shell.execute_reply": "2026-06-30T22:40:52.341928Z"
}
},
"outputs": [],
"source": [
"structure.space_group.name_h_m = 'P m -3 m'\n",
"structure.space_group.coord_system_code = '1'"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "11",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.347546Z",
"iopub.status.busy": "2026-06-30T22:40:52.347191Z",
"iopub.status.idle": "2026-06-30T22:40:52.351041Z",
"shell.execute_reply": "2026-06-30T22:40:52.349913Z"
}
},
"outputs": [],
"source": [
"structure.cell.length_a = 3.88"
]
},
{
"cell_type": "markdown",
"id": "12",
"metadata": {},
"source": [
"The atom-site definitions below form the starting structural model. The\n",
"parameters are intentionally reasonable rather than fully optimized,\n",
"because the refinement step will improve them."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "13",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.352731Z",
"iopub.status.busy": "2026-06-30T22:40:52.352534Z",
"iopub.status.idle": "2026-06-30T22:40:52.365690Z",
"shell.execute_reply": "2026-06-30T22:40:52.365132Z"
}
},
"outputs": [],
"source": [
"structure.atom_sites.create(\n",
" id='La',\n",
" type_symbol='La',\n",
" fract_x=0,\n",
" fract_y=0,\n",
" fract_z=0,\n",
" wyckoff_letter='a',\n",
" adp_type='Biso',\n",
" adp_iso=0.5151,\n",
" occupancy=0.5,\n",
")\n",
"structure.atom_sites.create(\n",
" id='Ba',\n",
" type_symbol='Ba',\n",
" fract_x=0,\n",
" fract_y=0,\n",
" fract_z=0,\n",
" wyckoff_letter='a',\n",
" adp_type='Biso',\n",
" adp_iso=0.5151,\n",
" occupancy=0.5,\n",
")\n",
"structure.atom_sites.create(\n",
" id='Co',\n",
" type_symbol='Co',\n",
" fract_x=0.5,\n",
" fract_y=0.5,\n",
" fract_z=0.5,\n",
" wyckoff_letter='b',\n",
" adp_type='Biso',\n",
" adp_iso=0.2190,\n",
")\n",
"structure.atom_sites.create(\n",
" id='O',\n",
" type_symbol='O',\n",
" fract_x=0,\n",
" fract_y=0.5,\n",
" fract_z=0.5,\n",
" wyckoff_letter='c',\n",
" adp_type='Biso',\n",
" adp_iso=1.3916,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "14",
"metadata": {},
"source": [
"With the structural model complete, render it to confirm the perovskite\n",
"framework before configuring the experiment."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "15",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.367790Z",
"iopub.status.busy": "2026-06-30T22:40:52.367584Z",
"iopub.status.idle": "2026-06-30T22:40:52.443305Z",
"shell.execute_reply": "2026-06-30T22:40:52.442133Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mStructure π§© \u001b[0m\u001b[32m'lbco'\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='lbco')"
]
},
{
"cell_type": "markdown",
"id": "16",
"metadata": {},
"source": [
"## π¬ Define Experiment\n",
"\n",
"Next we download the measured powder pattern, create a neutron powder\n",
"experiment, and configure the instrument, profile, background, and\n",
"excluded regions."
]
},
{
"cell_type": "markdown",
"id": "17",
"metadata": {},
"source": [
"Download the measured data from the repository. Alternatively, you\n",
"could use your own data file by providing the path to it instead of\n",
"downloading from the repository."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "18",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.445022Z",
"iopub.status.busy": "2026-06-30T22:40:52.444855Z",
"iopub.status.idle": "2026-06-30T22:40:52.456532Z",
"shell.execute_reply": "2026-06-30T22:40:52.453497Z"
}
},
"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-lbco-hrpt'\u001b[0m: La0.5Ba0.5CoO3, HRPT \u001b[1m(\u001b[0mPSI\u001b[1m)\u001b[0m, \u001b[1;36m300\u001b[0m K\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β
Data \u001b[32m'meas-lbco-hrpt'\u001b[0m already present at \u001b[32m'../../../data/meas-lbco-hrpt.xye'\u001b[0m. Keeping existing.\n"
]
}
],
"source": [
"data_path = edi.download_data('meas-lbco-hrpt', destination='data')"
]
},
{
"cell_type": "markdown",
"id": "19",
"metadata": {},
"source": [
"Create the experiment object and specify the sample form, beam mode,\n",
"and radiation probe."
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "20",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:52.460145Z",
"iopub.status.busy": "2026-06-30T22:40:52.459819Z",
"iopub.status.idle": "2026-06-30T22:40:53.157286Z",
"shell.execute_reply": "2026-06-30T22:40:53.156156Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mData loaded successfully\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Experiment π¬ \u001b[32m'hrpt'\u001b[0m. Number of data points: \u001b[1;36m3098\u001b[0m.\n"
]
}
],
"source": [
"project.experiments.add_from_data_path(\n",
" name='hrpt',\n",
" data_path=data_path,\n",
" sample_form='powder',\n",
" beam_mode='constant wavelength',\n",
" radiation_probe='neutron',\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "21",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.159419Z",
"iopub.status.busy": "2026-06-30T22:40:53.159195Z",
"iopub.status.idle": "2026-06-30T22:40:53.163409Z",
"shell.execute_reply": "2026-06-30T22:40:53.162275Z"
}
},
"outputs": [],
"source": [
"experiment = project.experiments['hrpt']"
]
},
{
"cell_type": "markdown",
"id": "22",
"metadata": {},
"source": [
"Link the structural phase to the experiment."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "23",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.165436Z",
"iopub.status.busy": "2026-06-30T22:40:53.165180Z",
"iopub.status.idle": "2026-06-30T22:40:53.169981Z",
"shell.execute_reply": "2026-06-30T22:40:53.168833Z"
}
},
"outputs": [],
"source": [
"experiment.linked_structures.create(structure_id='lbco', scale=9.1351)"
]
},
{
"cell_type": "markdown",
"id": "24",
"metadata": {},
"source": [
"Set instrument and peak profile parameters.\n",
"\n",
"These values provide the initial instrument description for the local\n",
"refinement. Later, a subset of them will be refined."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "25",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.171848Z",
"iopub.status.busy": "2026-06-30T22:40:53.171618Z",
"iopub.status.idle": "2026-06-30T22:40:53.176448Z",
"shell.execute_reply": "2026-06-30T22:40:53.175834Z"
}
},
"outputs": [],
"source": [
"experiment.instrument.setup_wavelength = 1.494\n",
"experiment.instrument.calib_twotheta_offset = 0.0"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "26",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.178372Z",
"iopub.status.busy": "2026-06-30T22:40:53.178230Z",
"iopub.status.idle": "2026-06-30T22:40:53.183652Z",
"shell.execute_reply": "2026-06-30T22:40:53.181919Z"
}
},
"outputs": [],
"source": [
"experiment.peak.broad_gauss_u = 0.1\n",
"experiment.peak.broad_gauss_v = -0.1\n",
"experiment.peak.broad_gauss_w = 0.1204\n",
"experiment.peak.broad_lorentz_y = 0.0844"
]
},
{
"cell_type": "markdown",
"id": "27",
"metadata": {},
"source": [
"Add background points and excluded regions.\n",
"\n",
"The line-segment background is defined by a few anchor points. We also\n",
"exclude regions that are not intended to contribute to the fit."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "28",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.185632Z",
"iopub.status.busy": "2026-06-30T22:40:53.185420Z",
"iopub.status.idle": "2026-06-30T22:40:53.199400Z",
"shell.execute_reply": "2026-06-30T22:40:53.195383Z"
}
},
"outputs": [],
"source": [
"experiment.background.create(id='1', position=10, intensity=168.5585)\n",
"experiment.background.create(id='2', position=30, intensity=164.3357)\n",
"experiment.background.create(id='3', position=50, intensity=166.8881)\n",
"experiment.background.create(id='4', position=110, intensity=175.4006)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "29",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.201488Z",
"iopub.status.busy": "2026-06-30T22:40:53.201238Z",
"iopub.status.idle": "2026-06-30T22:40:53.212198Z",
"shell.execute_reply": "2026-06-30T22:40:53.209844Z"
}
},
"outputs": [],
"source": [
"experiment.excluded_regions.create(id='1', start=0, end=10)\n",
"experiment.excluded_regions.create(id='2', start=100, end=180)"
]
},
{
"cell_type": "markdown",
"id": "30",
"metadata": {},
"source": [
"## π Initial Refinement\n",
"\n",
"Before Bayesian sampling, it is useful to run a deterministic fit. This\n",
"gives us:\n",
"\n",
"- a good point estimate near the best-fit region,\n",
"- uncertainties from the local optimizer,\n",
"- a quick check that the model and experiment are configured\n",
" sensibly.\n",
"\n",
"In this tutorial we refine only a small set of parameters that are easy\n",
"to interpret in the later Bayesian stage."
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "31",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.213699Z",
"iopub.status.busy": "2026-06-30T22:40:53.213532Z",
"iopub.status.idle": "2026-06-30T22:40:53.216159Z",
"shell.execute_reply": "2026-06-30T22:40:53.215505Z"
}
},
"outputs": [],
"source": [
"structure.cell.length_a.free = True"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "32",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.217403Z",
"iopub.status.busy": "2026-06-30T22:40:53.217260Z",
"iopub.status.idle": "2026-06-30T22:40:53.220115Z",
"shell.execute_reply": "2026-06-30T22:40:53.219513Z"
}
},
"outputs": [],
"source": [
"experiment.linked_structures['lbco'].scale.free = True\n",
"experiment.peak.broad_gauss_u.free = True\n",
"experiment.peak.broad_gauss_v.free = True\n",
"experiment.instrument.calib_twotheta_offset.free = True"
]
},
{
"cell_type": "markdown",
"id": "33",
"metadata": {},
"source": [
"We choose the BUMPS Levenberg-Marquardt minimizer as a fast local\n",
"optimizer. Its main purpose here is to provide a stable starting point\n",
"and uncertainty estimates for the Bayesian run."
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "34",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.221372Z",
"iopub.status.busy": "2026-06-30T22:40:53.221208Z",
"iopub.status.idle": "2026-06-30T22:40:53.234586Z",
"shell.execute_reply": "2026-06-30T22:40:53.233147Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mMinimizer types\u001b[0m\n"
]
},
{
"data": {
"text/html": [
" | | Type | Description |
|---|
| 1 | | bumps | BUMPS library using the default Levenberg-Marquardt method |
|---|
| 2 | | bumps (amoeba) | BUMPS library with Nelder-Mead simplex method |
|---|
| 3 | | bumps (de) | BUMPS library with differential evolution method |
|---|
| 4 | | bumps (dream) | BUMPS library with DREAM Bayesian sampling |
|---|
| 5 | | bumps (lm) | BUMPS library with Levenberg-Marquardt method |
|---|
| 6 | | dfols | DFO-LS library for derivative-free least-squares optimization |
|---|
| 7 | | emcee | emcee affine-invariant ensemble Bayesian sampling |
|---|
| 8 | | lmfit | LMFIT library using the default Levenberg-Marquardt method |
|---|
| 9 | | lmfit (least_squares) | LMFIT library with SciPy's trust region reflective algorithm |
|---|
| 10 | * | lmfit (leastsq) | LMFIT library with Levenberg-Marquardt least squares method |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.analysis.minimizer.show_supported()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "35",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.236353Z",
"iopub.status.busy": "2026-06-30T22:40:53.236139Z",
"iopub.status.idle": "2026-06-30T22:40:53.243843Z",
"shell.execute_reply": "2026-06-30T22:40:53.242522Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mCurrent minimizer changed to\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"bumps \u001b[1m(\u001b[0mlm\u001b[1m)\u001b[0m\n"
]
}
],
"source": [
"project.analysis.minimizer.type = 'bumps (lm)'"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "36",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:53.247867Z",
"iopub.status.busy": "2026-06-30T22:40:53.247645Z",
"iopub.status.idle": "2026-06-30T22:40:57.056466Z",
"shell.execute_reply": "2026-06-30T22:40:57.056058Z"
}
},
"outputs": [
{
"data": {
"text/html": [],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"(function() {\n",
" const button = document.getElementById('ed-fit-stop-16b1660e2f374537a638b2578f09f61f-button');\n",
" const status = document.getElementById('ed-fit-stop-16b1660e2f374537a638b2578f09f61f-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;36mStandard fitting\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Using experiment π¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mlm\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.03 | 377.51 | |
|---|
| 2 | 7 | 0.23 | 56.31 | 85.1% β |
|---|
| 3 | 13 | 0.45 | 39.54 | 29.8% β |
|---|
| 4 | 20 | 0.78 | 37.66 | 4.7% β |
|---|
| 5 | 26 | 1.13 | 23.47 | 37.7% β |
|---|
| 6 | 32 | 1.40 | 8.74 | 62.7% β |
|---|
| 7 | 38 | 1.57 | 1.85 | 78.9% β |
|---|
| 8 | 44 | 1.77 | 1.30 | 29.9% β |
|---|
| 9 | 70 | 3.22 | 1.29 | |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Best goodness-of-fit \u001b[1m(\u001b[0mreduced ΟΒ²\u001b[1m)\u001b[0m is \u001b[1;36m1.29\u001b[0m at iteration \u001b[1;36m70\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'lbco_hrpt_bumps_dream'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/bayesian-dream-lbco-hrpt'\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": [
"β βββ π lbco.edi\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"βββ π experiments/\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β βββ π hrpt.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": [
" βββ π lbco_hrpt_bumps_dream.html\n"
]
}
],
"source": [
"project.analysis.fit()"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "37",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.059032Z",
"iopub.status.busy": "2026-06-30T22:40:57.058833Z",
"iopub.status.idle": "2026-06-30T22:40:57.430941Z",
"shell.execute_reply": "2026-06-30T22:40:57.430433Z"
}
},
"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 | bumps (lm) |
|---|
| 2 | β
Overall status | success |
|---|
| 3 | β±οΈ Fitting time (seconds) | 3.22 |
|---|
| 4 | π Goodness-of-fit (reduced ΟΒ²) | 1.29 |
|---|
| 5 | π R-factor (Rf, %) | 5.65 |
|---|
| 6 | π R-factor squared (RfΒ², %) | 4.92 |
|---|
| 7 | π Weighted R-factor (wR, %) | 4.08 |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Refined parameters:\n"
]
},
{
"data": {
"text/html": [
" | datablock | category | entry | parameter | units | start | value | s.u. | change |
|---|
| 1 | lbco | cell | | length_a | Γ
| 3.8800 | 3.8913 | 0.0001 | 0.29 % β |
|---|
| 2 | hrpt | linked_structure | lbco | scale | | 9.1351 | 9.1329 | 0.0333 | 0.02 % β |
|---|
| 3 | hrpt | peak | | broad_gauss_u | degΒ² | 0.1000 | 0.0817 | 0.0078 | 18.33 % β |
|---|
| 4 | hrpt | peak | | broad_gauss_v | degΒ² | -0.1000 | -0.1169 | 0.0057 | 16.91 % β |
|---|
| 5 | hrpt | instrument | | twotheta_offset | deg | 0.0000 | 0.6306 | 0.0019 | N/A |
|---|
"
],
"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"
}
],
"source": [
"project.display.fit.results()"
]
},
{
"cell_type": "markdown",
"id": "38",
"metadata": {},
"source": [
"The correlation plot shows how strongly the fitted parameters move\n",
"together in the local refinement. The measured-vs-calculated plots show\n",
"how well the refined model reproduces the data globally and in a zoomed\n",
"region."
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "39",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.438249Z",
"iopub.status.busy": "2026-06-30T22:40:57.435594Z",
"iopub.status.idle": "2026-06-30T22:40:57.471813Z",
"shell.execute_reply": "2026-06-30T22:40:57.471122Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.fit.correlations()"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "40",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.474690Z",
"iopub.status.busy": "2026-06-30T22:40:57.473875Z",
"iopub.status.idle": "2026-06-30T22:40:57.558504Z",
"shell.execute_reply": "2026-06-30T22:40:57.556074Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.pattern(expt_name='hrpt')"
]
},
{
"cell_type": "markdown",
"id": "41",
"metadata": {},
"source": [
"## π² Prepare Sampling\n",
"\n",
"DREAM requires finite bounds for the free parameters. Instead of\n",
"setting them manually, we derive them from the uncertainties estimated\n",
"in the local refinement.\n",
"\n",
"The helper method `set_fit_bounds_from_uncertainty` centers the bounds\n",
"on the current parameter value and expands them by a chosen multiple of\n",
"the reported uncertainty.\n",
"\n",
"The default `multiplier` is 4. If the local refinement is very tight,\n",
"or if you expect a broader posterior, increase it explicitly.\n",
"\n",
"Show unset fit bounds before setting them from the local refinement uncertainties."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "42",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.560026Z",
"iopub.status.busy": "2026-06-30T22:40:57.559866Z",
"iopub.status.idle": "2026-06-30T22:40:57.621677Z",
"shell.execute_reply": "2026-06-30T22:40:57.620948Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mFree parameters for both structures \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36mπ§© data blocks\u001b[0m\u001b[1;36m)\u001b[0m\u001b[1;36m and experiments \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 | min | max | units |
|---|
| 1 | lbco | cell | | length_a | 3.89134 | 0.00011 | -inf | inf | Γ
|
|---|
| 2 | hrpt | linked_structure | lbco | scale | 9.13288 | 0.03329 | -inf | inf | |
|---|
| 3 | hrpt | peak | | broad_gauss_u | 0.08167 | 0.00783 | -inf | inf | degΒ² |
|---|
| 4 | hrpt | peak | | broad_gauss_v | -0.11691 | 0.00566 | -inf | inf | degΒ² |
|---|
| 5 | hrpt | instrument | | twotheta_offset | 0.63057 | 0.00191 | -inf | inf | deg |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.parameters.free()"
]
},
{
"cell_type": "markdown",
"id": "43",
"metadata": {},
"source": [
"Set fit bounds for all free parameters using the default multiplier of\n",
"4. In this tutorial that means the posterior pair plot will later\n",
"refer to a `Β±4 Γ uncertainty` region in its title. To use a different\n",
"region, pass another value, for example `multiplier=6`."
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "44",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.625788Z",
"iopub.status.busy": "2026-06-30T22:40:57.625598Z",
"iopub.status.idle": "2026-06-30T22:40:57.682446Z",
"shell.execute_reply": "2026-06-30T22:40:57.681803Z"
}
},
"outputs": [],
"source": [
"for param in project.free_parameters:\n",
" param.set_fit_bounds_from_uncertainty()"
]
},
{
"cell_type": "markdown",
"id": "45",
"metadata": {},
"source": [
"Displaying the free parameters again is a convenient way to confirm\n",
"that the fit bounds have been assigned as expected before launching the\n",
"sampler."
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "46",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.685917Z",
"iopub.status.busy": "2026-06-30T22:40:57.685739Z",
"iopub.status.idle": "2026-06-30T22:40:57.766230Z",
"shell.execute_reply": "2026-06-30T22:40:57.765081Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mFree parameters for both structures \u001b[0m\u001b[1;36m(\u001b[0m\u001b[1;36mπ§© data blocks\u001b[0m\u001b[1;36m)\u001b[0m\u001b[1;36m and experiments \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 | min | max | units |
|---|
| 1 | lbco | cell | | length_a | 3.89134 | 0.00011 | 3.89091 | 3.89177 | Γ
|
|---|
| 2 | hrpt | linked_structure | lbco | scale | 9.13288 | 0.03329 | 8.99973 | 9.26603 | |
|---|
| 3 | hrpt | peak | | broad_gauss_u | 0.08167 | 0.00783 | 0.05034 | 0.11300 | degΒ² |
|---|
| 4 | hrpt | peak | | broad_gauss_v | -0.11691 | 0.00566 | -0.13955 | -0.09427 | degΒ² |
|---|
| 5 | hrpt | instrument | | twotheta_offset | 0.63057 | 0.00191 | 0.62292 | 0.63823 | deg |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.parameters.free()"
]
},
{
"cell_type": "markdown",
"id": "47",
"metadata": {},
"source": [
"## π² Run Sampling\n",
"\n",
"We now switch from the local minimizer to the Bayesian DREAM sampler.\n",
"\n",
"The settings below are intentionally small so the tutorial runs\n",
"quickly. For production analysis you would usually increase the number\n",
"of steps (`steps`) and often the burn-in (`burn`) as well. When\n",
"needed, the DREAM API also lets you tune how chains are initialized\n",
"through the `init` setting. Other sampler settings such as `thin` and\n",
"`pop` can be adjusted as well. The current EasyDiffraction defaults\n",
"use `steps=3000`, `init='lhs'`, and `parallel=0`, which tells\n",
"BUMPS-DREAM to use all available CPUs for population evaluations.\n",
"\n",
"The `burn` setting is auto-resolved when left unset. With the default\n",
"`steps=3000` this gives `burn=600`, but if you override `steps` and\n",
"keep `burn=None`, the effective burn-in is recomputed automatically.\n",
"Here we use a much smaller step count to keep the tutorial fast, but\n",
"this is not recommended for production analysis."
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "48",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.767716Z",
"iopub.status.busy": "2026-06-30T22:40:57.767554Z",
"iopub.status.idle": "2026-06-30T22:40:57.777961Z",
"shell.execute_reply": "2026-06-30T22:40:57.777456Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mMinimizer types\u001b[0m\n"
]
},
{
"data": {
"text/html": [
" | | Type | Description |
|---|
| 1 | | bumps | BUMPS library using the default Levenberg-Marquardt method |
|---|
| 2 | | bumps (amoeba) | BUMPS library with Nelder-Mead simplex method |
|---|
| 3 | | bumps (de) | BUMPS library with differential evolution method |
|---|
| 4 | | bumps (dream) | BUMPS library with DREAM Bayesian sampling |
|---|
| 5 | * | bumps (lm) | BUMPS library with Levenberg-Marquardt method |
|---|
| 6 | | dfols | DFO-LS library for derivative-free least-squares optimization |
|---|
| 7 | | emcee | emcee affine-invariant ensemble Bayesian sampling |
|---|
| 8 | | lmfit | LMFIT library using the default Levenberg-Marquardt method |
|---|
| 9 | | lmfit (least_squares) | LMFIT library with SciPy's trust region reflective algorithm |
|---|
| 10 | | lmfit (leastsq) | LMFIT library with Levenberg-Marquardt least squares method |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.analysis.minimizer.show_supported()"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "49",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.784235Z",
"iopub.status.busy": "2026-06-30T22:40:57.782434Z",
"iopub.status.idle": "2026-06-30T22:40:57.799529Z",
"shell.execute_reply": "2026-06-30T22:40:57.797546Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"β οΈ Switching minimizer type removes these settings: \n",
" β’ max_iterations \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β οΈ Switching minimizer type adds these settings with defaults: \n",
" β’ burn_in_steps=600 \n",
" β’ initialization_method='latin_hypercube' \n",
" β’ parallel_workers=0 \n",
" β’ population_size=4 \n",
" β’ random_seed=None \n",
" β’ sampling_steps=3000 \n",
" β’ thinning_interval=1 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mCurrent minimizer changed to\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"bumps \u001b[1m(\u001b[0mdream\u001b[1m)\u001b[0m\n"
]
}
],
"source": [
"project.analysis.minimizer.type = 'bumps (dream)'"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "50",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.802512Z",
"iopub.status.busy": "2026-06-30T22:40:57.802339Z",
"iopub.status.idle": "2026-06-30T22:40:57.817133Z",
"shell.execute_reply": "2026-06-30T22:40:57.811801Z"
}
},
"outputs": [],
"source": [
"project.analysis.minimizer.sampling_steps = 100 # lower than the default 3000\n",
"project.analysis.minimizer.burn_in_steps = 20 # lower than the default 600\n",
"project.analysis.minimizer.random_seed = 42 # fixed seed for reproducible output"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "51",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:40:57.822302Z",
"iopub.status.busy": "2026-06-30T22:40:57.822122Z",
"iopub.status.idle": "2026-06-30T22:42:11.341232Z",
"shell.execute_reply": "2026-06-30T22:42:11.340493Z"
}
},
"outputs": [
{
"data": {
"text/html": [],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"(function() {\n",
" const button = document.getElementById('ed-fit-stop-2d542b7782d04027b5637de6ea54a28a-button');\n",
" const status = document.getElementById('ed-fit-stop-2d542b7782d04027b5637de6ea54a28a-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;36mStandard fitting\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Using experiment π¬ \u001b[32m'hrpt'\u001b[0m for \u001b[32m'single'\u001b[0m fitting\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Starting fit process with \u001b[32m'bumps \u001b[0m\u001b[32m(\u001b[0m\u001b[32mdream\u001b[0m\u001b[32m)\u001b[0m\u001b[32m'\u001b[0m\u001b[33m...\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Bayesian sampling progress:\n"
]
},
{
"data": {
"text/html": [
" | step | progress | time (s) | log posterior | phase |
|---|
| 1 | | | 0.33 | -1350.94 | pre-processing |
|---|
| 2 | 7/120 | 5.8% | 3.61 | -1201.99 | burn-in |
|---|
| 3 | 14/120 | 11.7% | 5.87 | -1174.18 | burn-in |
|---|
| 4 | 20/120 | 16.7% | 7.78 | -1168.29 | burn-in |
|---|
| 5 | 21/120 | 17.5% | 8.11 | -1168.28 | sampling |
|---|
| 6 | 26/120 | 21.7% | 9.77 | -1165.85 | sampling |
|---|
| 7 | 31/120 | 25.8% | 11.31 | -1163.59 | sampling |
|---|
| 8 | 36/120 | 30.0% | 12.93 | -1161.64 | sampling |
|---|
| 9 | 41/120 | 34.2% | 14.53 | -1161.44 | sampling |
|---|
| 10 | 46/120 | 38.3% | 16.11 | -1161.43 | sampling |
|---|
| 11 | 51/120 | 42.5% | 17.75 | -1161.40 | sampling |
|---|
| 12 | 56/120 | 46.7% | 19.28 | -1160.56 | sampling |
|---|
| 13 | 61/120 | 50.8% | 20.96 | -1160.16 | sampling |
|---|
| 14 | 66/120 | 55.0% | 22.56 | -1159.82 | sampling |
|---|
| 15 | 71/120 | 59.2% | 24.04 | -1159.74 | sampling |
|---|
| 16 | 76/120 | 63.3% | 25.36 | -1159.43 | sampling |
|---|
| 17 | 81/120 | 67.5% | 26.61 | -1159.83 | sampling |
|---|
| 18 | 86/120 | 71.7% | 27.93 | -1160.02 | sampling |
|---|
| 19 | 91/120 | 75.8% | 29.18 | -1160.33 | sampling |
|---|
| 20 | 96/120 | 80.0% | 30.48 | -1160.18 | sampling |
|---|
| 21 | 101/120 | 84.2% | 31.76 | -1160.25 | sampling |
|---|
| 22 | 106/120 | 88.3% | 33.04 | -1159.95 | sampling |
|---|
| 23 | 111/120 | 92.5% | 34.23 | -1159.69 | sampling |
|---|
| 24 | 116/120 | 96.7% | 35.54 | -1159.60 | sampling |
|---|
| 25 | 120/120 | 100.0% | 36.80 | -1159.84 | sampling |
|---|
| 26 | | | 73.11 | | post-processing |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β
Bayesian sampling complete.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β οΈ Convergence diagnostics indicate the posterior may be poorly mixed. \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;36mSaving project π¦ \u001b[0m\u001b[32m'lbco_hrpt_bumps_dream'\u001b[0m\u001b[1;36m to \u001b[0m\u001b[32m'../../../projects/bayesian-dream-lbco-hrpt'\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": [
"β βββ π lbco.edi\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"βββ π experiments/\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"β βββ π hrpt.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": [
"β βββ π mcmc.h5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"βββ π reports/\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" βββ π lbco_hrpt_bumps_dream.html\n"
]
}
],
"source": [
"project.analysis.fit()"
]
},
{
"cell_type": "markdown",
"id": "52",
"metadata": {},
"source": [
"## π Inspect Results\n",
"\n",
"The fit-results display now includes sampler settings, convergence\n",
"diagnostics, committed parameter values, and posterior summary\n",
"statistics."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "53",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.343001Z",
"iopub.status.busy": "2026-06-30T22:42:11.342833Z",
"iopub.status.idle": "2026-06-30T22:42:11.382521Z",
"shell.execute_reply": "2026-06-30T22:42:11.381850Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"βοΈ Settings used:\n"
]
},
{
"data": {
"text/html": [
" | Name | Value | Description |
|---|
| 1 | sampling_steps | 100 | Total sampler iterations per chain. |
|---|
| 2 | burn_in_steps | 20 | Sampler iterations discarded as warm-up. |
|---|
| 3 | thinning_interval | 1 | Sampler thinning interval. |
|---|
| 4 | population_size | 4 | Number of chains or walkers. |
|---|
| 5 | parallel_workers | 0 | Worker count; 0 uses all available CPUs. |
|---|
| 6 | initialization_method | latin_hypercube | Sampler initialization method. |
|---|
| 7 | random_seed | 42 | Random seed; None uses a system-derived seed. |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Bayesian fit results:\n"
]
},
{
"data": {
"text/html": [
" | Metric | Value |
|---|
| 1 | π§ͺ Sampler | bumps (dream) |
|---|
| 2 | β Overall status | failed |
|---|
| 3 | π¬ Engine message | DREAM sampling completed |
|---|
| 4 | β±οΈ Fitting time (seconds) | 73.11 |
|---|
| 5 | π Goodness-of-fit (reduced ΟΒ²) | 1.29 |
|---|
| 6 | π R-factor (Rf, %) | 5.65 |
|---|
| 7 | π R-factor squared (RfΒ², %) | 4.92 |
|---|
| 8 | π Weighted R-factor (wR, %) | 4.08 |
|---|
| 9 | π Best log-posterior | -1157.01 |
|---|
| 10 | π Convergence status | failed |
|---|
| 11 | π Max r-hat | 1.379 |
|---|
| 12 | π Min ess bulk | 118.182 |
|---|
| 13 | π Draws per chain | 100 |
|---|
| 14 | π Chains | 20 |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Committed parameters:\n"
]
},
{
"data": {
"text/html": [
" | datablock | category | entry | parameter | units | start | value | s.u. | change |
|---|
| 1 | lbco | cell | | length_a | Γ
| 3.8913 | 3.8913 | 0.0001 | 0.00 % β |
|---|
| 2 | hrpt | linked_structure | lbco | scale | | 9.1329 | 9.1329 | 0.0369 | 0.00 % β |
|---|
| 3 | hrpt | peak | | broad_gauss_u | degΒ² | 0.0817 | 0.0817 | 0.0082 | 0.00 % β |
|---|
| 4 | hrpt | peak | | broad_gauss_v | degΒ² | -0.1169 | -0.1169 | 0.0062 | 0.00 % β |
|---|
| 5 | hrpt | instrument | | twotheta_offset | deg | 0.6306 | 0.6306 | 0.0020 | 0.00 % β |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" β’ start = parameter value before sampling
β’ value = estimate written back to the project (best posterior sample)
β’ s.u. = standard uncertainty (one sigma), posterior standard deviation
β’ change = relative change from start, in %; β = increase, β = decrease
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"π Posterior distribution:\n"
]
},
{
"data": {
"text/html": [
" | datablock | category | entry | parameter | units | median | 95% CI | r-hat | ess bulk |
|---|
| 1 | lbco | cell | | length_a | Γ
| 3.8913 | [3.8911, 3.8915] | 1.379 | 120.6 |
|---|
| 2 | hrpt | linked_structure | lbco | scale | | 9.1269 | [9.0638, 9.2080] | 1.323 | 162.9 |
|---|
| 3 | hrpt | peak | | broad_gauss_u | degΒ² | 0.0827 | [0.0608, 0.0955] | 1.368 | 154.5 |
|---|
| 4 | hrpt | peak | | broad_gauss_v | degΒ² | -0.1182 | [-0.1267, -0.1023] | 1.374 | 161.4 |
|---|
| 5 | hrpt | instrument | | twotheta_offset | deg | 0.6304 | [0.6261, 0.6334] | 1.352 | 118.2 |
|---|
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" β’ median = 50th percentile of the marginal posterior
β’ 95% CI = 95% credible interval (2.5%-97.5%, asymmetric)
β’ r-hat = Gelman-Rubin diagnostic (good convergence: r-hat <= 1.01)
β’ ess bulk = bulk effective sample size (typically >= 400)
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"β οΈ r-hat > 1.01: Consider longer sampling, better initialization, or reparameterization.
β οΈ ess bulk < 400: Consider longer sampling or reparameterization.
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.fit.results()"
]
},
{
"cell_type": "markdown",
"id": "54",
"metadata": {},
"source": [
"The correlation and posterior-pair plots are complementary:\n",
"\n",
"- `plot_param_correlations` summarizes pairwise structure in a compact\n",
" matrix.\n",
"- `plot_posterior_pairs` shows marginal densities on the diagonal and\n",
" posterior contours off-diagonal. In this tutorial its title also\n",
" reminds you that the display region follows the `Β±4 Γ uncertainty`\n",
" bounds defined above, while numeric subplot ranges are omitted to\n",
" keep the grid readable."
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "55",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.384254Z",
"iopub.status.busy": "2026-06-30T22:42:11.384063Z",
"iopub.status.idle": "2026-06-30T22:42:11.405863Z",
"shell.execute_reply": "2026-06-30T22:42:11.405140Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.fit.correlations()"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "56",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.407816Z",
"iopub.status.busy": "2026-06-30T22:42:11.407653Z",
"iopub.status.idle": "2026-06-30T22:42:11.655760Z",
"shell.execute_reply": "2026-06-30T22:42:11.654981Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.posterior.pairs()"
]
},
{
"cell_type": "markdown",
"id": "57",
"metadata": {},
"source": [
"The one-dimensional posterior distributions below make it easier to\n",
"inspect individual parameters in isolation, including asymmetry or\n",
"multimodality."
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "58",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.668407Z",
"iopub.status.busy": "2026-06-30T22:42:11.668217Z",
"iopub.status.idle": "2026-06-30T22:42:11.749320Z",
"shell.execute_reply": "2026-06-30T22:42:11.748294Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.posterior.distribution()"
]
},
{
"cell_type": "markdown",
"id": "59",
"metadata": {},
"source": [
"Finally, the posterior predictive plot propagates the sampled parameter\n",
"uncertainty into the calculated diffraction pattern. Comparing this to\n",
"the zoomed measured-vs-calculated view helps assess whether the sampled\n",
"model family explains the data in the region of interest."
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "60",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.751053Z",
"iopub.status.busy": "2026-06-30T22:42:11.750811Z",
"iopub.status.idle": "2026-06-30T22:42:11.805851Z",
"shell.execute_reply": "2026-06-30T22:42:11.805088Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.posterior.predictive(expt_name='hrpt')"
]
},
{
"cell_type": "markdown",
"id": "61",
"metadata": {},
"source": [
"A final zoomed measured-vs-calculated plot is useful for checking how\n",
"the posterior-supported model behaves in a narrow region of the pattern\n",
"after the Bayesian run."
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "62",
"metadata": {
"execution": {
"iopub.execute_input": "2026-06-30T22:42:11.809152Z",
"iopub.status.busy": "2026-06-30T22:42:11.808965Z",
"iopub.status.idle": "2026-06-30T22:42:11.856339Z",
"shell.execute_reply": "2026-06-30T22:42:11.855419Z"
}
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"project.display.posterior.predictive(expt_name='hrpt', x_min=92, x_max=93)"
]
}
],
"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
}