Pair Distribution Function: NaCl, XRD¶
This example demonstrates a pair distribution function (PDF) analysis of NaCl, based on data collected from an X-ray powder diffraction experiment.
The dataset is taken from: https://github.com/diffpy/add2019-diffpy-cmi/tree/master
🛠️ Import Library¶
In [2]:
Copied!
import easydiffraction as ed
import easydiffraction as ed
📦 Define Project¶
Create Project¶
In [3]:
Copied!
project = ed.Project(name='nacl_xray_pdf')
project = ed.Project(name='nacl_xray_pdf')
Set Plotting Engine¶
In [4]:
Copied!
# Keep the auto-selected engine. Alternatively, you can uncomment the
# line below to explicitly set the engine to the required one.
# project.rendering_plot.type = 'plotly'
# Keep the auto-selected engine. Alternatively, you can uncomment the
# line below to explicitly set the engine to the required one.
# project.rendering_plot.type = 'plotly'
In [5]:
Copied!
# Set global plot range for plots
project.rendering_plot.plotter.x_min = 2.0
project.rendering_plot.plotter.x_max = 30.0
# Set global plot range for plots
project.rendering_plot.plotter.x_min = 2.0
project.rendering_plot.plotter.x_max = 30.0
Add Structure¶
In [6]:
Copied!
project.structures.create(name='nacl')
project.structures.create(name='nacl')
In [7]:
Copied!
project.structures['nacl'].space_group.name_h_m = 'F m -3 m'
project.structures['nacl'].space_group.it_coordinate_system_code = '1'
project.structures['nacl'].cell.length_a = 5.62
project.structures['nacl'].atom_sites.create(
label='Na',
type_symbol='Na',
fract_x=0,
fract_y=0,
fract_z=0,
adp_iso=1.0,
)
project.structures['nacl'].atom_sites.create(
label='Cl',
type_symbol='Cl',
fract_x=0.5,
fract_y=0.5,
fract_z=0.5,
adp_iso=1.0,
)
project.structures['nacl'].space_group.name_h_m = 'F m -3 m'
project.structures['nacl'].space_group.it_coordinate_system_code = '1'
project.structures['nacl'].cell.length_a = 5.62
project.structures['nacl'].atom_sites.create(
label='Na',
type_symbol='Na',
fract_x=0,
fract_y=0,
fract_z=0,
adp_iso=1.0,
)
project.structures['nacl'].atom_sites.create(
label='Cl',
type_symbol='Cl',
fract_x=0.5,
fract_y=0.5,
fract_z=0.5,
adp_iso=1.0,
)
Display Structure¶
In [8]:
Copied!
project.display.structure(struct_name='nacl')
project.display.structure(struct_name='nacl')
Structure 🧩 'nacl' (Atom view type: 'covalent')
Loading plot…
drag = rotate
wheel = zoom
right-drag = pan
wheel = zoom
right-drag = pan
Add Experiment¶
In [9]:
Copied!
data_path = ed.download_data(id=4, destination='data')
data_path = ed.download_data(id=4, destination='data')
Getting data...
Data #4: NaCl.gr
✅ Data #4 downloaded to '../../../data/ed-4.gr'
In [10]:
Copied!
project.experiments.add_from_data_path(
name='xray_pdf',
data_path=data_path,
sample_form='powder',
beam_mode='constant wavelength',
radiation_probe='xray',
scattering_type='total',
)
project.experiments.add_from_data_path(
name='xray_pdf',
data_path=data_path,
sample_form='powder',
beam_mode='constant wavelength',
radiation_probe='xray',
scattering_type='total',
)
⚠️ No uncertainty (sy) column provided. Defaulting to 0.03.
Data loaded successfully
Experiment 🔬 'xray_pdf'. Number of data points: 5000.
In [11]:
Copied!
project.experiments['xray_pdf'].peak.show_supported()
project.experiments['xray_pdf'].peak.show_supported()
Peak types
| Type | Description | ||
|---|---|---|---|
| 1 | * | gaussian-damped-sinc | Total-scattering Gaussian-damped sinc profile for PDF analysis. |
In [12]:
Copied!
project.experiments['xray_pdf'].peak.type = 'gaussian-damped-sinc'
project.experiments['xray_pdf'].peak.type = 'gaussian-damped-sinc'
Peak profile type for experiment 'xray_pdf' changed to
gaussian-damped-sinc
In [13]:
Copied!
project.experiments['xray_pdf'].peak.damp_q = 0.03
project.experiments['xray_pdf'].peak.broad_q = 0
project.experiments['xray_pdf'].peak.cutoff_q = 21
project.experiments['xray_pdf'].peak.sharp_delta_1 = 0
project.experiments['xray_pdf'].peak.sharp_delta_2 = 5
project.experiments['xray_pdf'].peak.damp_particle_diameter = 0
project.experiments['xray_pdf'].peak.damp_q = 0.03
project.experiments['xray_pdf'].peak.broad_q = 0
project.experiments['xray_pdf'].peak.cutoff_q = 21
project.experiments['xray_pdf'].peak.sharp_delta_1 = 0
project.experiments['xray_pdf'].peak.sharp_delta_2 = 5
project.experiments['xray_pdf'].peak.damp_particle_diameter = 0
In [14]:
Copied!
project.experiments['xray_pdf'].linked_phases.create(id='nacl', scale=0.5)
project.experiments['xray_pdf'].linked_phases.create(id='nacl', scale=0.5)
🚀 Perform Analysis¶
Set Free Parameters¶
In [15]:
Copied!
project.structures['nacl'].cell.length_a.free = True
project.structures['nacl'].atom_sites['Na'].adp_iso.free = True
project.structures['nacl'].atom_sites['Cl'].adp_iso.free = True
project.structures['nacl'].cell.length_a.free = True
project.structures['nacl'].atom_sites['Na'].adp_iso.free = True
project.structures['nacl'].atom_sites['Cl'].adp_iso.free = True
In [16]:
Copied!
project.experiments['xray_pdf'].linked_phases['nacl'].scale.free = True
project.experiments['xray_pdf'].peak.damp_q.free = True
project.experiments['xray_pdf'].peak.sharp_delta_2.free = True
project.experiments['xray_pdf'].linked_phases['nacl'].scale.free = True
project.experiments['xray_pdf'].peak.damp_q.free = True
project.experiments['xray_pdf'].peak.sharp_delta_2.free = True
Run Fitting¶
In [17]:
Copied!
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations()
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations()
Standard fitting
📋 Using experiment 🔬 'xray_pdf' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit progress:
| iteration | time (s) | χ² | change / status | |
|---|---|---|---|---|
| 1 | 1 | 0.31 | 163.09 | |
| 2 | 10 | 2.19 | 17.06 | 89.5% ↓ |
| 3 | 17 | 3.65 | 2.27 | 86.7% ↓ |
| 4 | 24 | 5.08 | 1.48 | 34.6% ↓ |
| 5 | 50 | 10.23 | 1.48 | |
| 6 | 53 | 10.87 | 1.48 |
🏆 Best goodness-of-fit (reduced χ²) is 1.48 at iteration 52
✅ Fitting complete.
⚙️ Settings used:
| Name | Value | Description | |
|---|---|---|---|
| 1 | max_iterations | 1000 | Maximum solver iterations. |
📋 Least-squares fit results:
| Metric | Value | |
|---|---|---|
| 1 | 🧪 Minimizer | lmfit (leastsq) |
| 2 | ✅ Overall status | success |
| 3 | ⏱️ Fitting time (seconds) | 10.87 |
| 4 | 🔁 Iterations | 50 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 1.48 |
| 6 | 📏 R-factor (Rf, %) | 11.02 |
| 7 | 📏 R-factor squared (Rf², %) | 11.38 |
| 8 | 📏 Weighted R-factor (wR, %) | 11.38 |
📈 Refined parameters:
| datablock | category | entry | parameter | units | start | value | s.u. | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | nacl | cell | length_a | Å | 5.6200 | 5.6018 | 0.0001 | 0.32 % ↓ | |
| 2 | nacl | atom_site | Na | adp_iso | Ų | 1.0000 | 1.1053 | 0.0077 | 10.53 % ↑ |
| 3 | nacl | atom_site | Cl | adp_iso | Ų | 1.0000 | 0.5707 | 0.0028 | 42.93 % ↓ |
| 4 | xray_pdf | linked_phases | nacl | scale | 0.5000 | 0.4254 | 0.0006 | 14.93 % ↓ | |
| 5 | xray_pdf | peak | damp_q | Å⁻¹ | 0.0300 | 0.0606 | 0.0001 | 102.13 % ↑ | |
| 6 | xray_pdf | peak | sharp_delta_2 | Ų | 5.0000 | 3.5041 | 0.0667 | 29.92 % ↓ |
• 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
• 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
Loading plot…
Display Pattern¶
In [18]:
Copied!
project.display.pattern(expt_name='xray_pdf')
project.display.pattern(expt_name='xray_pdf')
Loading plot…
💾 Save Project¶
In [19]:
Copied!
project.save_as(dir_path='projects/ed_12_nacl_xray_pdf')
project.save_as(dir_path='projects/ed_12_nacl_xray_pdf')
Saving project 📦 'nacl_xray_pdf' to '../../../projects/ed_12_nacl_xray_pdf'
├── 📄 project.cif
├── 📁 structures/
│ └── 📄 nacl.cif
├── 📁 experiments/
│ └── 📄 xray_pdf.cif
├── 📁 analysis/
│ └── 📄 analysis.cif
└── 📁 reports/
└── 📄 nacl_xray_pdf.html