Pair Distribution Function: Ni, NPD¶
This example demonstrates a pair distribution function (PDF) analysis of Ni, based on data collected from a constant wavelength neutron powder diffraction experiment.
The dataset is taken from: https://github.com/diffpy/cmi_exchange/tree/main/cmi_scripts/fitNiPDF
🛠️ Import Library¶
In [2]:
Copied!
import easydiffraction as ed
import easydiffraction as ed
📦 Define Project¶
Create Project¶
In [3]:
Copied!
project = ed.Project(name='ni_pdf')
project = ed.Project(name='ni_pdf')
Add Structure¶
In [4]:
Copied!
project.structures.create(name='ni')
project.structures.create(name='ni')
In [5]:
Copied!
project.structures['ni'].space_group.name_h_m = 'F m -3 m'
project.structures['ni'].space_group.it_coordinate_system_code = '1'
project.structures['ni'].cell.length_a = 3.52387
project.structures['ni'].atom_sites.create(
label='Ni',
type_symbol='Ni',
fract_x=0.0,
fract_y=0.0,
fract_z=0.0,
adp_iso=0.5,
)
project.structures['ni'].space_group.name_h_m = 'F m -3 m'
project.structures['ni'].space_group.it_coordinate_system_code = '1'
project.structures['ni'].cell.length_a = 3.52387
project.structures['ni'].atom_sites.create(
label='Ni',
type_symbol='Ni',
fract_x=0.0,
fract_y=0.0,
fract_z=0.0,
adp_iso=0.5,
)
Display Structure¶
In [6]:
Copied!
project.display.structure(struct_name='ni')
project.display.structure(struct_name='ni')
Structure 🧩 'ni' (Atom view type: 'covalent')
Loading plot…
drag = rotate
wheel = zoom
right-drag = pan
wheel = zoom
right-drag = pan
Add Experiment¶
In [7]:
Copied!
data_path = ed.download_data(id=6, destination='data')
data_path = ed.download_data(id=6, destination='data')
Getting data...
Data #6: ni-q27r100-neutron_from-2.gr
✅ Data #6 downloaded to '../../../data/ed-6.gr'
In [8]:
Copied!
project.experiments.add_from_data_path(
name='pdf',
data_path=data_path,
sample_form='powder',
beam_mode='constant wavelength',
radiation_probe='neutron',
scattering_type='total',
)
project.experiments.add_from_data_path(
name='pdf',
data_path=data_path,
sample_form='powder',
beam_mode='constant wavelength',
radiation_probe='neutron',
scattering_type='total',
)
⚠️ No uncertainty (sy) column provided. Defaulting to 0.03.
Data loaded successfully
Experiment 🔬 'pdf'. Number of data points: 9801.
In [9]:
Copied!
project.experiments['pdf'].linked_phases.create(id='ni', scale=1.0)
project.experiments['pdf'].peak.damp_q = 0
project.experiments['pdf'].peak.broad_q = 0.03
project.experiments['pdf'].peak.cutoff_q = 27.0
project.experiments['pdf'].peak.sharp_delta_1 = 0.0
project.experiments['pdf'].peak.sharp_delta_2 = 2.0
project.experiments['pdf'].peak.damp_particle_diameter = 0
project.experiments['pdf'].linked_phases.create(id='ni', scale=1.0)
project.experiments['pdf'].peak.damp_q = 0
project.experiments['pdf'].peak.broad_q = 0.03
project.experiments['pdf'].peak.cutoff_q = 27.0
project.experiments['pdf'].peak.sharp_delta_1 = 0.0
project.experiments['pdf'].peak.sharp_delta_2 = 2.0
project.experiments['pdf'].peak.damp_particle_diameter = 0
🚀 Perform Analysis¶
Set Free Parameters¶
In [10]:
Copied!
project.structures['ni'].cell.length_a.free = True
project.structures['ni'].atom_sites['Ni'].adp_iso.free = True
project.structures['ni'].cell.length_a.free = True
project.structures['ni'].atom_sites['Ni'].adp_iso.free = True
In [11]:
Copied!
project.experiments['pdf'].linked_phases['ni'].scale.free = True
project.experiments['pdf'].peak.broad_q.free = True
project.experiments['pdf'].peak.sharp_delta_2.free = True
project.experiments['pdf'].linked_phases['ni'].scale.free = True
project.experiments['pdf'].peak.broad_q.free = True
project.experiments['pdf'].peak.sharp_delta_2.free = True
Run Fitting¶
In [12]:
Copied!
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations(threshold=0.75)
project.analysis.fit()
project.display.fit.results()
project.display.fit.correlations(threshold=0.75)
Standard fitting
📋 Using experiment 🔬 'pdf' for 'single' fitting
🚀 Starting fit process with 'lmfit (leastsq)'...
📈 Goodness-of-fit progress:
| iteration | time (s) | χ² | change / status | |
|---|---|---|---|---|
| 1 | 1 | 1.94 | 2334.39 | |
| 2 | 4 | 7.69 | 2322.80 | |
| 3 | 7 | 13.46 | 2334.46 | |
| 4 | 9 | 16.79 | 416.28 | 82.2% ↓ |
| 5 | 13 | 22.54 | 416.28 | |
| 6 | 15 | 25.46 | 210.14 | 49.5% ↓ |
| 7 | 19 | 31.34 | 210.15 | |
| 8 | 21 | 34.28 | 207.13 | 1.4% ↓ |
| 9 | 25 | 40.08 | 207.13 | |
| 10 | 29 | 45.86 | 207.10 | |
| 11 | 33 | 51.68 | 207.10 | |
| 12 | 37 | 57.63 | 207.10 | |
| 13 | 41 | 63.47 | 207.10 | |
| 14 | 45 | 69.29 | 207.10 |
🏆 Best goodness-of-fit (reduced χ²) is 207.10 at iteration 44
✅ 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) | 69.29 |
| 4 | 🔁 Iterations | 42 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 207.10 |
| 6 | 📏 R-factor (Rf, %) | 9.83 |
| 7 | 📏 R-factor squared (Rf², %) | 9.48 |
| 8 | 📏 Weighted R-factor (wR, %) | 9.48 |
📈 Refined parameters:
| datablock | category | entry | parameter | units | start | value | s.u. | change | |
|---|---|---|---|---|---|---|---|---|---|
| 1 | ni | cell | length_a | Å | 3.5239 | 3.5260 | 0.0000 | 0.06 % ↑ | |
| 2 | ni | atom_site | Ni | adp_iso | Ų | 0.5000 | 0.4281 | 0.0011 | 14.39 % ↓ |
| 3 | linked_phases | ni | scale | 1.0000 | 0.9892 | 0.0007 | 1.08 % ↓ | ||
| 4 | peak | broad_q | Å⁻² | 0.0300 | 0.0220 | 0.0001 | 26.77 % ↓ | ||
| 5 | peak | sharp_delta_2 | Ų | 2.0000 | 2.5587 | 0.0444 | 27.94 % ↑ |
• 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
⚠️ No parameter pairs with |correlation| >= 0.75 were found.
Display Pattern¶
In [13]:
Copied!
project.display.pattern(expt_name='pdf')
project.display.pattern(expt_name='pdf')
Loading plot…
💾 Save Project¶
In [14]:
Copied!
project.save_as(dir_path='projects/ed_10_ni_pdf')
project.save_as(dir_path='projects/ed_10_ni_pdf')
Saving project 📦 'ni_pdf' to '../../../projects/ed_10_ni_pdf'
├── 📄 project.cif
├── 📁 structures/
│ └── 📄 ni.cif
├── 📁 experiments/
│ └── 📄 pdf.cif
├── 📁 analysis/
│ └── 📄 analysis.cif
└── 📁 reports/
└── 📄 ni_pdf.html