Skip to content

Commit a8ae0dc

Browse files
authored
Merge pull request #26 from DanPorter/new_cell_basis
New cell basis
2 parents 7b66535 + 2bfce64 commit a8ae0dc

30 files changed

+4278
-307
lines changed

Dans_Diffraction/Structures/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ The files are downloaded or generated from a range of data sources, for example:
3636
* [MAGNDATA](http://webbdcrista1.ehu.es/magndata/)
3737
* [ISODISTORT](https://stokes.byu.edu/iso/isodistort.php)
3838
* [Jana2006](http://www-xray.fzu.cz/jana/jana.html)
39-
* [Vesta](http://jp-minerals.org/vesta/en/)
39+
* [Vesta](http://jp-minerals.org/vesta/en/)
40+
* [CrystalMaker](https://crystalmaker.com/index.html)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
data_Rutile
2+
_audit_creation_method 'generated by CrystalDiffract 6 for OS X'
3+
_cell_length_a 4.5870
4+
_cell_length_b 4.5870
5+
_cell_length_c 2.9540
6+
_cell_angle_alpha 90.0000
7+
_cell_angle_beta 90.0000
8+
_cell_angle_gamma 90.0000
9+
10+
_symmetry_space_group_name_H-M 'P 42/m n m'
11+
12+
loop_
13+
_symmetry_equiv_pos_as_xyz
14+
'+x,+y,+z'
15+
'-x,-y,+z'
16+
'1/2-y,1/2+x,1/2+z'
17+
'1/2+y,1/2-x,1/2+z'
18+
'1/2-x,1/2+y,1/2-z'
19+
'1/2+x,1/2-y,1/2-z'
20+
'+y,+x,-z'
21+
'-y,-x,+z'
22+
'-x,-y,-z'
23+
'+x,+y,-z'
24+
'1/2+y,1/2-x,1/2-z'
25+
'1/2-y,1/2+x,1/2-z'
26+
'1/2+x,1/2-y,1/2+z'
27+
'1/2-x,1/2+y,1/2+z'
28+
'-y,-x,-z'
29+
'+y,+x,+z'
30+
31+
loop_
32+
_atom_site_label
33+
_atom_site_type_symbol
34+
_atom_site_occupancy
35+
_atom_site_fract_x
36+
_atom_site_fract_y
37+
_atom_site_fract_z
38+
Label Ti 1.0000 0.0000 0.0000 0.0000
39+
Label O 1.0000 0.3051 0.3051 0.0000
40+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
#======================================================================
3+
# CRYSTAL DATA
4+
#----------------------------------------------------------------------
5+
data_VESTA_phase_1
6+
7+
_chemical_name_common 'Test_Triclinic'
8+
_cell_length_a 6.867000
9+
_cell_length_b 16.705999
10+
_cell_length_c 5.399000
11+
_cell_angle_alpha 62.980000
12+
_cell_angle_beta 42.250000
13+
_cell_angle_gamma 52.160000
14+
_cell_volume 328.878918
15+
_space_group_name_H-M_alt 'P 1'
16+
_space_group_IT_number 1
17+
18+
loop_
19+
_space_group_symop_operation_xyz
20+
'x, y, z'
21+
22+
loop_
23+
_atom_site_label
24+
_atom_site_occupancy
25+
_atom_site_fract_x
26+
_atom_site_fract_y
27+
_atom_site_fract_z
28+
_atom_site_adp_type
29+
_atom_site_U_iso_or_equiv
30+
_atom_site_type_symbol
31+
Fe1 1.0 0.000000 0.000000 0.000000 Uiso 0.050000 Fe

Dans_Diffraction/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
Diamond
3232
2017
3333
34-
Version 3.2.4
35-
Last updated: 25/09/24
34+
Version 3.3.2
35+
Last updated: 20/11/2024
3636
3737
Version History:
3838
02/03/18 1.0 Version History started.
@@ -81,6 +81,8 @@
8181
04/09/24 3.2.3 Updated method of generating charge states in classes_orbtials.py, Thanks Seonghun!
8282
25/09/24 3.2.4 Fixed error of missing rotation matrices after load_spacegroup. Thanks asteppke!
8383
26/09/24 3.3.0 Added complex neutron scattering lengths for isotopes from package periodictable. Thanks thamnos!
84+
06/11/24 3.3.1 Fixed incorrect cell basis for triclinic cells. Added functions_lattice.py and tests. Thanks LeeRichter!
85+
20/11/24 3.3.2 Added alternate option for neutron scattering lengths
8486
8587
Acknoledgements:
8688
2018 Thanks to Hepesu for help with Python3 support and ideas about breaking up calculations
@@ -105,6 +107,8 @@
105107
May 2024 Thanks to paul-cares pointing out a silly spelling error in the title!
106108
Aug 2024 Thanks to Seonghun for pointing out the error with charge states in Hf
107109
Aug 2024 Thanks to MaxPelly for spell checks in examples
110+
Sep 2024 Thanks to thamnos for suggestion to add complex neutron scattering lengths
111+
Oct 2024 Thanks to Lee Richter for pointing out the error in triclinic basis definition
108112
109113
-----------------------------------------------------------------------------
110114
Copyright 2024 Diamond Light Source Ltd.
@@ -146,6 +150,7 @@
146150
# Dans Diffraction
147151
from . import functions_general as fg
148152
from . import functions_plotting as fp
153+
from . import functions_lattice as fl
149154
from . import functions_crystallography as fc
150155
from .classes_crystal import Crystal
151156
from .classes_multicrystal import MultiCrystal
@@ -154,8 +159,12 @@
154159
from .functions_crystallography import readcif
155160

156161

157-
__version__ = '3.2.4'
158-
__date__ = '25/09/24'
162+
__all__ = ['fg', 'fp', 'fl', 'fc', 'Crystal', 'MultiCrystal', 'readcif',
163+
'Structures', 'Fdmnes', 'FdmnesAnalysis']
164+
165+
166+
__version__ = '3.3.2'
167+
__date__ = '2024/11/20'
159168

160169

161170
# Build

Dans_Diffraction/classes_crystal.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@
5757
from warnings import warn
5858

5959
# Internal functions
60-
from . import functions_general as fg, functions_crystallography as fc
60+
from . import functions_general as fg
6161
from . import functions_crystallography as fc
62+
from . import functions_lattice as fl
6263
from .classes_orientation import Orientation
6364
from .classes_properties import Properties
6465
# from .classes_orbitals import CrystalOrbitals
@@ -514,9 +515,10 @@ def __init__(self, a=1.0, b=1.0, c=1.0, alpha=90., beta=90.0, gamma=90.0):
514515
self.alpha = float(alpha)
515516
self.beta = float(beta)
516517
self.gamma = float(gamma)
518+
self._basis_function = fl.basis_3
517519
self.orientation = Orientation()
518520

519-
def latt(self, lattice_parameters=(), *args, **kwargs):
521+
def latt(self, *lattice_parameters, **kwargs):
520522
"""
521523
Generate lattice parameters with list
522524
latt(1) -> a=b=c=1,alpha=beta=gamma=90
@@ -527,7 +529,7 @@ def latt(self, lattice_parameters=(), *args, **kwargs):
527529
latt(a=1,b=2,c=3,alpha=10,beta=20,gamma=30]) -> a=1,b=2,c=3,alpha=10,beta=20,gamma=30
528530
"""
529531

530-
lp = fc.gen_lattice_parameters(lattice_parameters, *args, **kwargs)
532+
lp = fc.gen_lattice_parameters(*lattice_parameters, **kwargs)
531533
self.a = lp[0]
532534
self.b = lp[1]
533535
self.c = lp[2]
@@ -585,35 +587,46 @@ def lp(self):
585587
"""
586588
return self.a, self.b, self.c, self.alpha, self.beta, self.gamma
587589

590+
def choose_basis(self, option='default'):
591+
"""
592+
Choose the basis function
593+
Options:
594+
1. c || z, b* || y - basis choice of Materials Project
595+
2. a || x, c* || z - basis choice of Vesta
596+
3. c || z, a* || x - basis choice of Busing & Levy (Default)
597+
:param option: name or number of basis
598+
"""
599+
self._basis_function = fl.choose_basis(option)
600+
588601
def UV(self):
589602
"""
590603
Returns the unit cell as a [3x3] array, [A,B,C]
591604
The vector A is directed along the x-axis
592605
"""
593-
return self.orientation(fc.latpar2uv_rot(*self.lp()))
606+
return self.orientation(self._basis_function(*self.lp()))
594607

595608
def UVstar(self):
596609
"""
597610
Returns the reciprocal unit cell as a [3x3] array, [A*,B*,C*]
598611
:return: [a*;b*;c*]
599612
"""
600-
return fc.RcSp(self.UV())
613+
return fl.reciprocal_basis(self.UV())
601614

602615
def volume(self):
603616
"""
604617
Returns the volume of the unit cell, in A^3
605618
:return: volume
606619
"""
607-
return fc.calc_vol(self.UV())
620+
return fl.lattice_volume(*self.lp())
608621

609622
def Bmatrix(self):
610623
"""
611624
Calculate the Busing and Levy B matrix from a real space UV
612625
"choose the x-axis parallel to a*, the y-axis in the plane of a* and b*, and the z-axis perpendicular to
613626
that plane"
614-
W. R. Busing & H. A. Levy, Acta Cryst. (1967). 22, 457
627+
W. R. Busing & H. A. Levy, Acta Cryst. (1967). 22, 457
615628
"""
616-
return fc.Bmatrix(self.UV())
629+
return fl.busingandlevy(*self.lp())
617630

618631
def info(self):
619632
"""
@@ -660,7 +673,7 @@ def indexQ(self, Q):
660673
> HKL = [1,0,0]
661674
"""
662675
Q = np.reshape(np.asarray(Q, dtype=float), [-1, 3])
663-
return fc.indx(Q, self.UVstar())
676+
return fl.index_lattice(Q, self.UVstar())
664677

665678
def calculateR(self, UVW):
666679
"""
@@ -685,7 +698,7 @@ def indexR(self, R):
685698
> UVW = [0.1,0,0]
686699
"""
687700
R = np.reshape(np.asarray(R, dtype=float), [-1, 3])
688-
return fc.indx(R, self.UV())
701+
return fl.index_lattice(R, self.UV())
689702

690703
def moment(self, mxmymz):
691704
"""Calcualte moment from value stored in cif"""
@@ -892,7 +905,7 @@ def find_close_reflections(self, hkl, energy_kev, max_twotheta=2, max_angle=10):
892905
selected = (tth_dif < max_twotheta) * (all_angles < max_angle)
893906
return all_hkl[selected, :]
894907

895-
def reciprocal_space_plane(self, x_axis=[1, 0, 0], y_axis=[0, 1, 0], centre=[0, 0, 0], q_max=4.0, cut_width=0.05):
908+
def reciprocal_space_plane(self, x_axis=(1, 0, 0), y_axis=(0, 1, 0), centre=(0, 0, 0), q_max=4.0, cut_width=0.05):
896909
"""
897910
Returns positions within a reciprocal space plane
898911
x_axis = direction along x, in units of the reciprocal lattice (hkl)
@@ -1481,7 +1494,7 @@ def check(self):
14811494
def fitincell(self):
14821495
"""Adjust all atom positions to fit within unit cell"""
14831496
uvw = fc.fitincell(self.uvw())
1484-
1497+
self.u, self.v, self.w = uvw.T
14851498

14861499
def uvw(self):
14871500
"""
@@ -2366,7 +2379,7 @@ def __init__(self, Parent, P):
23662379
self.P = np.asarray(P, dtype=float)
23672380
self.Parent = Parent
23682381
newUV = Parent.Cell.calculateR(P)
2369-
self.new_cell(fc.UV2latpar(newUV))
2382+
self.new_cell(fl.basis2latpar(newUV))
23702383
self.scale = Parent.scale * np.prod(self.P)
23712384

23722385
# Add exta functions

Dans_Diffraction/classes_orientation.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515
@author: DGPorter
1616
"""
1717

18-
import sys, os, re
1918
import numpy as np
20-
from warnings import warn
2119

22-
from . import functions_general as fg
20+
from . import functions_lattice as fl
2321
from . import functions_crystallography as fc
2422

2523
__version__ = '1.0.0'
@@ -174,10 +172,9 @@ class CrystalOrientation:
174172
x-axis : vector normal to phi axis where phi=0 (toward ceiling (+y) in lab frame)
175173
y-axis : vector normal to x,z axes (parallel to beam (+z) in lab frame)
176174
"""
177-
def __init__(self, lattice_parameters=(), *args, **kwargs):
175+
def __init__(self, *lattice_parameters, **kwargs):
178176
self.a, self.b, self.c, self.alpha, self.beta, self.gamma = fc.gen_lattice_parameters(
179-
lattice_parameters,
180-
*args,
177+
*lattice_parameters,
181178
**kwargs
182179
)
183180
self.orientation = Orientation()
@@ -218,17 +215,15 @@ def lp(self):
218215

219216
def lp_star(self):
220217
"""Return tuple of reciprocal lattice parameters in inverse-angstroms and degrees"""
221-
uv = self._uv()
222-
return fc.latpar_reciprocal(uv)
218+
return fl.reciprocal_lattice_parameters(*self.lp())
223219

224220
def _uv(self):
225-
"""Return unit vectors [a,b,c] in default frame (b along X)"""
226-
return fc.latpar2uv_rot(self.a, self.b, self.c, self.alpha, self.beta, self.gamma)
221+
"""Return unit vectors [a,b,c] in default frame (a* along X)"""
222+
return fl.basis_3(*self.lp())
227223

228224
def _uvstar(self):
229225
"""Return unit vectors in recirpocal space in default frame (a* along X)"""
230-
uv = self._uv()
231-
return fc.RcSp(uv)
226+
return fl.reciprocal_basis(self._uv())
232227

233228
def unit_vectors(self):
234229
"""Return real space unit vectors [a, b, c]"""
@@ -240,7 +235,7 @@ def reciprocal_unit_vectors(self):
240235

241236
def bmatrix(self):
242237
"""Return the B matrix from Busing & Levy in the diffractometer frame"""
243-
return fc.Bmatrix(self._uv())
238+
return fl.busingandlevy(*self.lp())
244239

245240
def ubmatrix(self):
246241
"""Return UB matrix from Busing & Levy in the diffractometer frame"""

Dans_Diffraction/classes_scattering.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class Scattering:
104104
# Uses the coefficients for analytical approximation to the scattering factors from:
105105
# "Waasmaier and Kirfel, Acta Cryst. (1995) A51, 416-431"
106106
_use_waaskirf_scattering_factor = False
107+
108+
# Use the neutron scattering factors from the Internation tables (Sears 1995)
109+
_use_sears_scattering_lengths = False
107110

108111
# Thermal Factors
109112
_use_isotropic_thermal_factor = True
@@ -161,6 +164,8 @@ def __str__(self):
161164
out += ' max twotheta: %s\n' % self._scattering_max_twotheta
162165
out += ' ---X-Ray Settings---\n'
163166
out += ' Waasmaier scattering factor: %s\n' % self._use_waaskirf_scattering_factor
167+
out += ' ---Neutron Settings---\n'
168+
out += ' Sears (ITC) scattering lengths: %s\n' % self._use_sears_scattering_lengths
164169
out += ' ---Magnetic Settings---\n'
165170
out += ' Mag. scattering: %s\n' % self._calclate_magnetic_component
166171
out += ' Mag. form factor: %s\n' % self._use_magnetic_form_factor
@@ -185,7 +190,7 @@ def setup_scatter(self, scattering_type=None, energy_kev=None, wavelength_a=None
185190
powder_units=None, powder_pixels=None, powder_lorentz=None, powder_overlap=None,
186191
specular=None, parallel=None, theta_offset=None,
187192
min_theta=None, max_theta=None, min_twotheta=None, max_twotheta=None,
188-
output=True, scattering_factors=None, magnetic_formfactor=None,
193+
output=True, scattering_factors=None, scattering_lengths=None, magnetic_formfactor=None,
189194
polarisation=None, polarisation_vector=None, azimuthal_reference=None, azimuth=None, flm=None):
190195
"""
191196
Simple way to set scattering parameters, each parameter is internal to xtl (self)
@@ -205,6 +210,7 @@ def setup_scatter(self, scattering_type=None, energy_kev=None, wavelength_a=None
205210
specular : self._scattering_specular_direction : [h,k,l] : reflections normal to sample surface
206211
parallel : self._scattering_parallel_direction : [h,k,l] : reflections normal to sample surface
207212
scattering_factors: self._use_waaskirf_scattering_factor : xray scattering factor ['waaskirf', 'itc']
213+
scattering_lengths: self._use_sears_scattering_lengths : neutron scattering lengths ['sears', 'default']
208214
magnetic_formfactor: self._use_magnetic_form_factor: True/False magnetic form factor for magnetic SF
209215
polarisation: self._polarisation : beam polarisation setting ['ss', 'sp'*, 'sp', 'pp']
210216
polarisation_vector: _polarisation_vector_incident: [x,y,z] incident polarisation vector
@@ -263,6 +269,14 @@ def setup_scatter(self, scattering_type=None, energy_kev=None, wavelength_a=None
263269
print('Using scattering factors from: International Tables of Crystallography Vol. C, Table 6.1.1.4')
264270
self._use_waaskirf_scattering_factor = False
265271

272+
if scattering_lengths is not None:
273+
if scattering_lengths.lower() in ['sears', 'itc', 'alternate', 'alt']:
274+
print('Using scattering lengths from International Tables of Crystallography Vol. C, Table 4.4.4.1')
275+
self._use_sears_scattering_lengths = True
276+
else:
277+
print('Using scattering lengths from Neutron Data Booklet')
278+
self._use_sears_scattering_lengths = False
279+
266280
if magnetic_formfactor is not None:
267281
self._use_magnetic_form_factor = magnetic_formfactor
268282

@@ -470,8 +484,11 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg
470484
qmag = fg.mag(_q) # q magnitude
471485
# Scattering factors
472486
if scattering_type in fs.SCATTERING_TYPES['neutron']:
473-
# ff = fc.atom_properties(atom_type, 'Coh_b')
474-
ff = fc.neutron_scattering_length(atom_type)
487+
if self._use_sears_scattering_lengths:
488+
ff = fc.neutron_scattering_length(atom_type, 'Sears')
489+
else:
490+
# ff = fc.atom_properties(atom_type, 'Coh_b')
491+
ff = fc.neutron_scattering_length(atom_type)
475492
elif scattering_type in fs.SCATTERING_TYPES['electron']:
476493
ff = fc.electron_scattering_factor(atom_type, qmag)
477494
elif scattering_type in fs.SCATTERING_TYPES['xray fast']:

0 commit comments

Comments
 (0)