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 edi
import easydiffraction as edi
📦 Define Project¶
Create Project¶
In [3]:
Copied!
project = edi.Project(name='ni_pdf')
project = edi.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.coord_system_code = '1'
project.structures['ni'].cell.length_a = 3.52387
project.structures['ni'].atom_sites.create(
id='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.coord_system_code = '1'
project.structures['ni'].cell.length_a = 3.52387
project.structures['ni'].atom_sites.create(
id='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 = edi.download_data('meas-ni-pdf', destination='data')
data_path = edi.download_data('meas-ni-pdf', destination='data')
Getting data...
Data 'meas-ni-pdf': Ni, PDF
✅ Data 'meas-ni-pdf' downloaded to '../../../data/meas-ni-pdf.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_structures.create(structure_id='ni', scale=1.0)
project.experiments['pdf'].peak.damp_q = 0
project.experiments['pdf'].peak.broad_q = 0.02
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.8
project.experiments['pdf'].peak.damp_particle_diameter = 0
project.experiments['pdf'].linked_structures.create(structure_id='ni', scale=1.0)
project.experiments['pdf'].peak.damp_q = 0
project.experiments['pdf'].peak.broad_q = 0.02
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.8
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_structures['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_structures['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.70 | 911.16 | |
| 2 | 4 | 6.68 | 890.92 | 2.2% ↓ |
| 3 | 8 | 13.30 | 911.16 | |
| 4 | 9 | 15.01 | 220.45 | 75.3% ↓ |
| 5 | 12 | 20.05 | 220.44 | |
| 6 | 15 | 25.12 | 207.23 | 6.0% ↓ |
| 7 | 18 | 30.17 | 207.23 | |
| 8 | 22 | 36.76 | 207.29 | |
| 9 | 26 | 43.38 | 207.10 | |
| 10 | 30 | 49.71 | 207.10 | |
| 11 | 34 | 56.39 | 207.28 | |
| 12 | 37 | 63.71 | 207.10 | |
| 13 | 39 | 68.74 | 207.10 | |
| 14 | 42 | 76.21 | 207.10 | |
| 15 | 44 | 81.35 | 207.10 | |
| 16 | 47 | 87.00 | 207.10 | |
| 17 | 50 | 92.51 | 207.10 | |
| 18 | 53 | 98.15 | 207.10 | |
| 19 | 54 | 100.05 | 207.10 |
🏆 Best goodness-of-fit (reduced χ²) is 207.10 at iteration 45
✅ 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) | 100.05 |
| 4 | 🔁 Iterations | 51 |
| 5 | 📏 Goodness-of-fit (reduced χ²) | 207.10 |
| 6 | 📏 R-factor (Rf, %) | 9.85 |
| 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.0013 | 14.39 % ↓ |
| 3 | linked_structure | ni | scale | 1.0000 | 0.9785 | 0.0014 | 2.15 % ↓ | ||
| 4 | peak | broad_q | Å⁻² | 0.0200 | 0.0220 | 0.0001 | 9.84 % ↑ | ||
| 5 | peak | sharp_delta_2 | Ų | 2.8000 | 2.5589 | 0.0444 | 8.61 % ↓ |
• 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/pdf-ni-npd')
project.save_as(dir_path='projects/pdf-ni-npd')
Saving project 📦 'ni_pdf' to '../../../projects/pdf-ni-npd'
├── 📄 project.edi
├── 📁 structures/
│ └── 📄 ni.edi
├── 📁 experiments/
│ └── 📄 pdf.edi
├── 📁 analysis/
│ └── 📄 analysis.edi
└── 📁 reports/
└── 📄 ni_pdf.html