Dans_Diffraction.classes_scattering (version 2.3.4)
index
c:\users\grp66007\onedrive - diamond light source ltd\pythonprojects\dans_diffraction\dans_diffraction\classes_scattering.py

Scattering Class "classes_scattering.py"
    Scattering functions for Crystal class.
 
By Dan Porter, PhD
Diamond
2017
 
Version 2.3.4
Last updated: 17/05/24
 
Version History:
10/09/17 0.1    Program created
30/10/17 1.0    Main functions finshed, some testing done
06/01/18 1.1    Renamed classes_scattering.py
31/10/18 1.2    Added print_symmetric_contributions
21/01/19 1.3    Added non-resonant diffraction, corrected resonant diffraction
16/12/19 1.4    Added multiple_scattering code, print_all_reflections updated with units
18/02/20 1.5    Added tensor_scattering code
20/03/20 1.6    Increased powder gauss width from 2fwhm to 6fwhm, added powder averaging
14/04/20 1.6    Added powder_correction
26/05/20 1.7    Removed tensor_scattering
16/06/20 1.7.1  Added output option of setup_scatter
04/01/21 1.7.2  Added structure_factor function
21/01/21 1.8    Added xray_dispersion scattering function
10/06/21 1.9    Added x_ray calculation using Waasmaier and Kirfel scattering factors.
09/07/21 1.9    Added new scattering factors as option on normal scattering functions
20/08/21 2.0    Switched over to new scattering module, added self.powder()
28/09/21 2.0.1  Added __repr__
08/02/22 2.0.3  Corrected error in powder of wrong tth values. Thanks Mirko!
14/03/22 2.1.0   powder() updated for new inputs and outputs for pVoight and custom peak shapes. Thanks yevgenyr!
14/01/23 2.1.1  Corrected background error in xtl.Scatter.powder
06/05/23 2.0.0  Merged pull request for non-integer hkl option on SF and electron form factors. Thanks Prestipino!
02/07/23 2.3.0  Fixed rounding error in Scatter.powder, thanks Sergio I. Rincon!
26/09/23 2.3.1  Added Scattering.orientation_reflections for automatic orientation help
19/20/23 2.3.2  Fixed scatteringbasis so xray_resonant() now works with non-cubic systems
28/03/24 2.3.3  Fixed scattering type comparison to compare .lower() scattering types
02/05/24 2.3.4  added min_twotheta to get_hkl, added generate_envelope_cut, fixed low tth error in powder()
15/05/24 2.3.4  Added "save" and "load" methods to structure factor calculation, improved powder for large calculations
16/05/24 2.3.4  Added printed progress bar to generate_intensity_cut during convolusion
17/05/24 2.3.4  Changed generate_intensity_cut to make it much faster
 
@author: DGPorter

 
Modules
       
datetime
Dans_Diffraction.functions_crystallography
Dans_Diffraction.functions_general
Dans_Diffraction.functions_scattering
Dans_Diffraction.multiple_scattering
numpy

 
Classes
       
builtins.object
Reflections
Scattering
ScatteringTypes

 
class Reflections(builtins.object)
    Reflections(hkl, q_mag, intensity, energy_kev=None, wavelength_a=None)
 
Contains h,k,l indices, intensity
 
masking doesn't work currently
 
  Methods defined here:
__getitem__(self, item)
__init__(self, hkl, q_mag, intensity, energy_kev=None, wavelength_a=None)
Initialize self.  See help(type(self)) for accurate signature.
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
dspacing(self)
labels(self)
Return list of str labels "(h,k,l)"
limits(self, min_val=None, max_val=None, limit_type='q')
Adds limits
:param min_val: float, minimum value in units determined by overlap_type
:param max_val: float, maximum value
:param limit_type: str 'q', 'tth' or 'd'
:return: None
mask(self, center=None, width=None, mask_type='q')
Adds mask
:param center: float, centre of mask in units determined by overlap_type
:param width: float, width of mask
:param limit_type: str 'q', 'tth' or 'd'
:return: None
non_overlapping_refs(self, min_overlap=0.05, overlap_type='q')
Return list of non-overlapping label
:param min_overlap: float, minimum overlap in units determined by overlap_type
:param overlap_type: str 'q', 'tth' or 'd'
:return:
set_energy(self, energy_kev)
set_wavelength(self, wavelength_a)
sort_hkl(self)
sort_intensity(self)
sort_qmag(self)
Sort arrays by qmag
two_theta(self)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class Scattering(builtins.object)
    Scattering(xtl)
 
Simulate diffraction from Crystal
Useage:
    xtl = Crystal()
    xtl.Scatter.setup_scatter(type='x-ray',energy_keV=8.0)
    xtl.Scatter.intensity([h,k,l]) # Returns intensity
    print(xtl.Scatter.print_all_refelctions()) # Returns formated string of all allowed reflections
    
    Allowed radiation types:
        'xray','neutron','xray magnetic','neutron magnetic','xray resonant'
 
  Methods defined here:
__init__(self, xtl)
Initialize self.  See help(type(self)) for accurate signature.
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
detector_image(self, detector_distance_mm=100.0, delta=0, gamma=0, height_mm=100.0, width_mm=100.0, pixel_size_mm=0.1, energy_range_ev=1000.0, peak_width_deg=0.5, wavelength_a=None, background=0, min_intensity=0.01)
Calcualte detector image
  Creates a detector rotated about the sample and generates incident reflections on the detector.
  Reflections incident on the detector are scaled by the distance of the scattered wavevector from the Ewald
  sphere and also scaled by all reflections incident on the Ewald sphere.
Example
  tth = xtl.Cell.tth([0, 0, 2], wavelength_a=1)[0]
  xtl.Cell.orientation.rotate_6circle(mu=tth/2)  # Orient crystal to scattering position
  xx, yy, mesh, reflist = xtl.Scatter.detector_image(detector_distance_mm=100, gamma=tth, wavelength_a=1)
  # Plot detector image
  plt.figure()
  plt.pcolormesh(xx, yy, mesh, vmin=0, vmax=1, shading='auto')
  # reflection labels
  for n in range(len(reflist['hkl'])):
      plt.text(reflist['detx'][n], reflist['dety'][n], reflist['hkl_str'][n], c='w')
:param detector_distance_mm: float, Detector distance in mm (along (0,1,0))
:param delta: flaot, angle to rotate detector about (0,0,1) in Deg
:param gamma: float, angle to rotate detector about (1,0,0) in Deg
:param height_mm: float, detector size vertically (along (0,0,1))
:param width_mm: float, detector size horizontally (along (1,0,0))
:param pixel_size_mm: float, size of pixels, determines grid size
:param energy_range_ev: float, determines width of energies in incident intensity in eV
:param peak_width_deg: float, determines peak width on detector
:param wavelength_a: float, wavelength in A
:param background: float, detector background
:param min_intensity: float, min intenisty to include
:return xx: [height//pixelsize x width//pixelsize] array of x-coordinates
:return yy: [height//pixelsize x width//pixelsize] array of y-coordinates
:return mesh: [height//pixelsize x width//pixelsize] array of intensities
:return reflist: dict with info about each reflection on detector
diff6circle_intensity(self, phi=0, chi=0, eta=0, mu=0, delta=0, gamma=0, energy_kev=None, wavelength=1.0, fwhm=0.5)
Return the closest hkl and intensity factor
:param phi: float sample angle in degrees
:param chi: float sample angle in degrees
:param eta: float sample angle in degrees
:param mu: float sample angle in degrees
:param delta: float detector angle in degrees
:param gamma: float detector angle in degrees
:param energy_kev: float energy in KeV
:param wavelength: float wavelength in A
:param fwhm: float peak width in A-1
:return: [h,k,l], If
electron(self, HKL)
Calculate the squared structure factor for the given HKL, using electron form factors
  Scattering.electron([1,0,0])
  Scattering.electron([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
find_close_reflections(self, HKL, energy_kev=None, max_twotheta=2, max_angle=10)
Find and print list of reflections close to the given one
generate_envelope_cut(self, x_axis=(1, 0, 0), y_axis=(0, 1, 0), centre=(0, 0, 0), q_max=4.0, background=0.0, pixels=301)
*In Development*
Generate the envelope function, calculating the structure factor at discrete points
Inputs:
  x_axis = direction along x, in units of the reciprocal lattice (hkl)
  y_axis = direction along y, in units of the reciprocal lattice (hkl)
  centre = centre of the plot, in units of the reciprocal lattice (hkl)
  q_max = maximum distance to plot to - in A-1
  background = average background value
  pixels = size of mesh, calculates structure factor at each pixel
Returns:
  Qx/Qy = [pixels x pixels] array of coordinates
  plane = [pixels x pixels] array of plane in reciprocal space
 
E.G. hk plane at L=3 for hexagonal system:
    Qx, Qy, plane = xtl.generate_envelope_cut([1,0,0],[0,1,0],[0,0,3])
    plt.figure()
    plt.pcolormesh(Qx, Qy, plane)
    plt.axis('image')
generate_intensity_cut(self, x_axis=(1, 0, 0), y_axis=(0, 1, 0), centre=(0, 0, 0), q_max=4.0, cut_width=0.05, background=0.0, peak_width=0.05, pixels=1001)
Generate a cut through reciprocal space, returns an array with centred reflections
Inputs:
  x_axis = direction along x, in units of the reciprocal lattice (hkl)
  y_axis = direction along y, in units of the reciprocal lattice (hkl)
  centre = centre of the plot, in units of the reciprocal lattice (hkl)
  q_max = maximum distance to plot to - in A-1
  cut_width = width in height that will be included, in A-1
  background = average background value
  peak_width = reflection width in A-1
  pixels = size of the plotting mesh
Returns:
  Qx/Qy = [pixels x pixels] array of coordinates
  plane = [pixels x pixels] array of plane in reciprocal space
 
E.G. hk plane at L=3 for hexagonal system:
    Qx,Qy,plane = xtl.Scatter.generate_intensity_cut([1,0,0],[0,1,0],[0,0,3])
    plt.figure()
    plt.pcolormesh(Qx,Qy,plane)
    plt.axis('image')
generate_intensity_cut_old(self, x_axis=(1, 0, 0), y_axis=(0, 1, 0), centre=(0, 0, 0), q_max=4.0, cut_width=0.05, background=0.0, peak_width=0.05, pixels=1001)
Generate a cut through reciprocal space, returns an array with centred reflections
  **Old version - creates full Gaussian for each peak, very slow**
Inputs:
  x_axis = direction along x, in units of the reciprocal lattice (hkl)
  y_axis = direction along y, in units of the reciprocal lattice (hkl)
  centre = centre of the plot, in units of the reciprocal lattice (hkl)
  q_max = maximum distance to plot to - in A-1
  cut_width = width in height that will be included, in A-1
  background = average background value
  peak_width = reflection width in A-1
Returns:
  Qx/Qy = [1000x1000] array of coordinates
  plane = [1000x1000] array of plane in reciprocal space
 
E.G. hk plane at L=3 for hexagonal system:
    Qx,Qy,plane = xtl.generate_intensity_cut([1,0,0],[0,1,0],[0,0,3])
    plt.figure()
    plt.pcolormesh(Qx,Qy,plane)
    plt.axis('image')
generate_powder(self, q_max=8, peak_width=0.01, background=0, powder_average=True)
*DEPRECIATED*
Generates array of intensities along a spaced grid, equivalent to a powder pattern.
  Q,I = generate_powder(energy_kev=8.0,peak_width=0.05,background=0)
    q_max = maximum Q, in A-1
    peak_width = width of convolution, in A-1
    background = average of normal background
    powder_average = True*/False, apply the powder averaging correction
  Returns:
    Q = [1000x1] array of wave-vector values
    I = [1000x1] array of intensity values
 
Note: This function is depreciated, use self.powder() instead.
Note: To get two-theta values use:
    tth = fc.cal2theta(Q, energy_kev)
Note: To get d-spacing values use:
    dspace = fc.caldspace(Q)
get_energy(self, **kwargs)
Return energy
:param kwargs: energy_kev, wavelength_a
:return: energy_kev
get_hkl(self, regenerate=True, remove_symmetric=False, reflection=False, transmission=False, **kwargs)
Return stored hkl or generate
:param regenerate: if True, hkl list will be regenerated, if False - previous list will be returned
:param remove_symmetric: generate only non-symmetric hkl values
:param reflection: generate only reflections possible in reflection geometry
:param transmission: generate only reflections possible in transmission geometry
:param kwargs: additional options to pass to setup_scatter()
:return: array
hkl(self, HKL, energy_kev=None)
Calculate the two-theta and intensity of the given HKL, display the result
hkl_reflection(self, HKL, energy_kev=None)
Calculate the theta, two-theta and intensity of the given HKL in reflection geometry, display the result
Uses sample orientation set up in setup_scatter
:param HKL: [h,k,l] or list of hkl
:param energy_kev: None or float
:return: str
hkl_transmission(self, HKL, energy_kev=None)
Calculate the theta, two-theta and intensity of the given HKL in transmission geometry, display the result
intensity(self, hkl=None, scattering_type=None, int_hkl=True, **options)
Return the structure factor squared
:param hkl: array[n,3] : reflection indexes (h, k, l)
:param scattering_type: str : one of ['xray','neutron', 'electron', 'xray magnetic','neutron magnetic','xray resonant']
:param int_hkl: Bool : when True, hkl values are converted to integer.
:param kwargs: additional options to pass to scattering function
:return: float array[n] : array of |SF|^2
magnetic_neutron(self, HKL)
Calculate the magnetic component of the structure factor for the given HKL, using neutron rules and form factor
  Scattering.magnetic_neutron([1,0,0])
  Scattering.magnetic_neutron([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
ms_azimuth(self, hkl, energy_kev, azir=[0, 0, 1], pv=[1, 0], numsteps=3, peak_width=0.1, full=False, pv1=False, pv2=False, sfonly=True, pv1xsf1=False)
Returns an azimuthal dependence at a particular energy
 
:param xtl: Crystal structure from Dans_Diffraction
:param hkl: [h,k,l] principle reflection
:param energy_kev: calculation energy
:param azir: [h,k,l] reference of azimuthal 0 angle
:param pv: [s,p] polarisation vector
:param numsteps: int: number of calculation steps from energy min to max
:param peak_width: convolution width
:param full: True/False: calculation type: full
:param pv1: True/False: calculation type: pv1
:param pv2: True/False: calculation type: pv2
:param sfonly: True/False: calculation type: sfonly *default
:param pv1xsf1: True/False: calculation type: pv1xsf1?
:return: None
multiple_scattering(self, hkl, azir=[0, 0, 1], pv=[1, 0], energy_range=[7.8, 8.2], numsteps=60, full=False, pv1=False, pv2=False, sfonly=True, pv1xsf1=False)
Run multiple scattering code, plot result.
 
mslist = xtl.Scatter.multiple_scattering([h,k,l], energy_range=[7.8, 8.2])
 
See multiple_scattering.py for more details. Code created by Dr Gareth Nisbet, DLS
:param hkl: [h,k,l] principle reflection
:param azir: [h,k,l] reference of azimuthal 0 angle
:param pv: [s,p] polarisation vector
:param energy_range: [min, max] energy range in keV
:param numsteps: int: number of calculation steps from energy min to max
:param full: True/False: calculation type: full
:param pv1: True/False: calculation type: pv1
:param pv2: True/False: calculation type: pv2
:param sfonly: True/False: calculation type: sfonly *default
:param pv1xsf1: True/False: calculation type: pv1xsf1?
:return: array
neutron(self, HKL)
Calculate the squared structure factor for the given HKL, using neutron scattering length
  Scattering.neutron([1,0,0])
  Scattering.neutron([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
new_intensity = intensity(self, hkl=None, scattering_type=None, int_hkl=True, **options)
new_structure_factor = structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwargs)
old_intensity(self, HKL, scattering_type=None)
Calculate the squared structure factor for the given HKL
  Crystal.intensity([1,0,0])
  Crystal.intensity([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
 
Notes:
- Uses x-ray atomic form factors, calculated from approximated tables in the ITC
- This may be a little slow for large numbers of reflections, as it is not currently
 possible to use accelerated calculation methods in Jython.
- Debye-Waller factor (atomic displacement) is applied for isotropic ADPs
- Crystal.scale is used to scale the complex structure factor, so the intensity is  
 reduced by (Crystal.scale)^2
- Testing against structure factors calculated by Vesta.exe is very close, though there
  are some discrepancies, probably due to the method of calculation of the form factor.
old_structure_factor(self, HKL, scattering_type=None)
Calculate the complex structure factor for the given HKL
  Crystal.structure_factor([1,0,0])
  Crystal.structure_factor([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the complex structure factor at each reflection.
 
Notes:
- Uses x-ray atomic form factors, calculated from approximated tables in the ITC
- This may be a little slow for large numbers of reflections, as it is not currently
 possible to use accelerated calculation methods in Jython.
- Debye-Waller factor (atomic displacement) is applied for isotropic ADPs
- Crystal.scale is used to scale the complex structure factor, so the intensity is
 reduced by (Crystal.scale)^2
- Testing against structure factors calculated by Vesta.exe is very close, though there
  are some discrepancies, probably due to the method of calculation of the form factor.
orientation_reflections(self, energy_kev, hkl_1=None)
Return 2 reflections to use to orient a crystal
 1. a strong reflection that is easy to discriminate in 2-theta
 2. another strong reflection non-parallel and non-normal to (1)
 
hkl_1, hkl_2, alternatives = xtl.Scatter.orientation_reflections(8)
 
:param energy_kev: photon energy in keV
:param hkl_1: None or [h,k,l], allows to specify the first reflection
:returns hkl_1: [h,k,l] indices of reflection 1
:returns hkl_2: [h,k,l] indices of reflection 2
:returns hkl_2_alternatives: [[h,k,l],...] list of alternative reflections with same angles
powder(self, scattering_type=None, units=None, peak_width=None, background=None, pixels=None, powder_average=None, lorentz_fraction=None, custom_peak=None, min_overlap=None, **options)
Generates array of intensities along a spaced grid, equivalent to a powder pattern.
  tth, inten, reflections = Scatter.powder('xray', units='tth', energy_kev=8)
 
Note: This function is the new replacement for generate_power and uses both _scattering_min_twotheta
and _scattering_max_twotheta.
 
:param scattering_type: str : one of ['xray','neutron','xray magnetic','neutron magnetic','xray resonant']
:param units: str : one of ['tth', 'dspace', 'q']
:param peak_width: float : Peak with in units of inverse wavevector (Q)
:param background: float : if >0, a normal background around this value will be added
:param pixels: int : number of pixels per inverse-anstrom to add to the resulting mesh
:param powder_average: Bool : if True, intensities will be reduced for the powder average
:param lorentz_fraction: float 0-1: sets the Lorentzian fraction of the psuedo-Voight peak functions
:param custom_peak: array: if not None, the array will be convolved with delta-functions at each reflection.
:param min_overlap: minimum overlap of neighboring reflections.
:param options: additional arguments to pass to intensity calculation
:return xval: arrray : x-axis of powder scan (units)
:return inten: array :  intensity values at each point in x-axis
:return reflections: (h, k, l, xval, intensity) array of reflection positions, grouped by min_overlap
powder_correction(self, HKL, intensities, symmetric_multiplyer=True, powder_average=True)
Averages symmetric reflections and applies symmetry multipliers and 1/q^2 correction
Ic = I0*C
:param HKL: [nx3] array of [h,k,l] reflections
:param intensities: [nx1] array of reflection intensities
:return: [mx3], [mx1] arrays of averaged, corrected reflections + intensity
print_all_reflections(self, energy_kev=None, print_symmetric=False, min_intensity=0.01, max_intensity=None, units=None)
Prints a list of all allowed reflections at this energy
    energy_kev = energy in keV
    print_symmetric = False*/True : omits reflections with the same intensity at the same angle
    min_intensity = None/ 0.01 : omits reflections less than this (remove extinctions)
    max_intensity = None/ 0.01 : omits reflections greater than this (show extinctions only)
    units = None/ 'twotheta'/ 'q'/ 'dspace' : choose scattering angle units to display
print_atomic_contributions(self, HKL)
Prints the atomic contributions to the structure factor
print_intensity(self, HKL)
Print intensities calcualted in different ways
print_ref_reflections(self, energy_kev=None, min_intensity=0.01, max_intensity=None)
Prints a list of all allowed reflections at this energy in the reflection geometry
    energy = energy in keV
    min_intensity = None/ 0.01 : omits reflections less than this (remove extinctions)
    max_intensity = None/ 0.01 : omits reflections greater than this (show extinctions only)
               |
            // |                    \ |
             \|___/____
              \                          \__
 
Note, to change min/max theta values or specular direciton, change the following attributres of 
the crystal object:
    self._scattering_max_two_theta   :  maximum detector (two-theta) angle
    self._scattering_min_theta       :  minimum sample angle = -opening angle
    self._scattering_max_theta       :  maximum sample angle = opening angle
    self._scattering_theta_offset    :  sample offset angle
    self._scattering_specular_direction : [h,k,l] : reflections normal to sample surface
print_scattering_coordinates(self, hkl, azim_zero=[1, 0, 0], psi=0)
Transform magnetic vector into components within the scattering plane
    ***warning - may not be correct for non-cubic systems***
print_symmetric_reflections(self, HKL)
Prints equivalent reflections
print_symmetry_contributions(self, HKL)
Prints the symmetry contributions to the structure factor for each atomic site
print_tran_reflections(self, energy_kev=None, min_intensity=0.01, max_intensity=None)
Prints a list of all allowed reflections at this energy in the transmission geometry
    energy = energy in keV
    min_intensity = None/ 0.01 : omits reflections less than this (remove extinctions)
    max_intensity = None/ 0.01 : omits reflections greater than this (show extinctions only)
           \ /      
     --<-- || --<-- 
          / \       
 
Note, to change min/max theta values or specular direciton, change the following attributres of 
the crystal object:
    self._scattering_max_two_theta   :  maximum detector (two-theta) angle
    self._scattering_min_theta       :  minimum sample angle = -opening angle
    self._scattering_max_theta       :  maximum sample angle = opening angle
    self._scattering_theta_offset    :  sample offset angle
    self._scattering_parallel_direction : [h,k,l] : reflections normal to sample surface, parallel to beam at theta = 0
print_xray_nonresonant(self, HKL, energy_kev=None, azim_zero=(1, 0, 0), psi=0)
Return string with non-resonant magnetic contriubtions to the x-ray scattering
:param HKL: array(nx3) of (h,k,l) reflections
:param energy_kev: incident photon energy in keV
:param azim_zero: (h,k,l) reference vector defining azimuthal zero angle
:param psi: float, azimuthal angle
:return: str
print_xray_resonant(self, HKL, energy_kev=None, azim_zero=(1, 0, 0), psi=0, F0=0, F1=1, F2=0)
Return string with resonant magnetic contriubtions to the x-ray scattering
:param HKL: array(nx3) of (h,k,l) reflections
:param energy_kev: incident photon energy in keV
:param azim_zero: (h,k,l) reference vector defining azimuthal zero angle
:param psi: float, azimuthal angle
:param F0, F1, F2: Resonance factor Flm
:return: str
scatteringbasis(self, hkl, azim_zero=[1, 0, 0], psi=0)
Determine the scattering and polarisation vectors of a reflection based on energy, azimuth and polarisation.
:param hkl: [n,3] array of reflections
:param azim_zero: [1,3] direction along which the azimuthal zero angle is determind
:param psi: float azimuthal angle about U3 in degrees
:return: U1, U2, U3
The basis is chosen such that Q defines the scattering plane, the sigma direction is normal to this plane,
the pi direction is always within this plane.
The azimuthal angle defines a rotation about the Q axis in a clockwise mannor, matching I16.
At an azimuth of 0degrees, U1 is perpendicular to Q, along the direction of azim_zero.
scatteringcomponents(self, mxmymz, hkl, azim_zero=[1, 0, 0], psi=0)
Transform magnetic vector into components within the scattering plane
First transforms the moments into a cartesian reference frame.
   U1 = direction || ki - kf = Q
   U2 = direction || kf + ki (within scattering plane, pi)
   U3 = direction perp. to U1, U2 (normal to scattering plane, sigma)
scatteringvectors(self, hkl, energy_kev=None, azim_zero=[1, 0, 0], psi=0, polarisation='s-p')
Determine the scattering and polarisation vectors of a reflection based on energy, azimuth and polarisation.
:param xtl: Crystal Class
:param hkl: [n,3] array of reflections
:param energy_kev: x-ray scattering energy in keV
:param azim_zero: [1,3] direction along which the azimuthal zero angle is determind
:param psi: float angle in degrees about the azimuth
:param polarisation: polarisation with respect to the scattering plane, options:
            'ss' : sigma-sigma polarisation
            'sp' : sigma-pi polarisation
            'ps' : pi-sigma polarisation
            'pp' : pi-pi polarisation
        or: polarisation: float polarisation angle of scattered vector in degrees
:return: kin, kout, ein, eout
Returned values are [n,3] arrays
    kin : [n,3] array of incident wavevectors
    kout: [n,3] array of scattered wavevectors
    ein : [n,3] array of incident polarisation
    eout: [n,3] array of scattered polarisation
 
The basis is chosen such that Q defines the scattering plane, sigma and pi directions are normal to this plane.
Q is defined as Q = kout - kin, with kout +ve along the projection of azim_zero
setup_scatter(self, scattering_type=None, energy_kev=None, wavelength_a=None, powder_units=None, powder_pixels=None, powder_lorentz=None, powder_overlap=None, specular=None, parallel=None, theta_offset=None, min_theta=None, max_theta=None, min_twotheta=None, max_twotheta=None, output=True, scattering_factors=None, magnetic_formfactor=None, polarisation=None, polarisation_vector=None, azimuthal_reference=None, azimuth=None, flm=None)
Simple way to set scattering parameters, each parameter is internal to xtl (self)
 
scattering_type: self._scattering type            :  'xray','neutron','xray magnetic','neutron magnetic','xray resonant', 'xray dispersion'
energy_kev  : self._energy_kev                    :  radiation energy in keV
wavelength_a: self._wavelength_a                  :  radiation wavelength in Angstrom
powder_units: self._powder_units                  :  units to use when displaying/ plotting ['twotheta', 'd',' 'q']
powder_pixels: self._powder_pixels                :  number of bins per inverse-angstrom in the powder spectrum
powder_lorentz: self._powder_lorentz_fraction     :  the fraction of Lorentzian in the peak function psuedo-Voight
powder_overlap: self._powder_min_overlap          :  minimum overlap of grouped reflections in powder
min_twotheta: self._scattering_min_two_theta      :  minimum detector (two-theta) angle
max_twotheta: self._scattering_max_two_theta      :  maximum detector (two-theta) angle
min_theta   : self._scattering_min_theta          :  minimum sample angle = -opening angle
max_theta   : self._scattering_max_theta          :  maximum sample angle = opening angle
theta_offset: self._scattering_theta_offset       :  sample offset angle
specular    : self._scattering_specular_direction : [h,k,l] : reflections normal to sample surface
parallel    : self._scattering_parallel_direction : [h,k,l] : reflections normal to sample surface
scattering_factors: self._use_waaskirf_scattering_factor : xray scattering factor ['waaskirf', 'itc']
magnetic_formfactor: self._use_magnetic_form_factor: True/False magnetic form factor for magnetic SF
polarisation: self._polarisation                  : beam polarisation setting ['ss', 'sp'*, 'sp', 'pp']
polarisation_vector: _polarisation_vector_incident: [x,y,z] incident polarisation vector
azimuthal_reference: self._azimuthal_reference    : [h,k,l] direction of azimuthal zero angle
azimuth    : self._azimuthal_angle                : azimuthal angle in deg
flm        : self._resonant_flm                   : Resonant settings (flm1, flm2, flm3)
structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwargs)
Calculate the structure factor at reflection indexes (h,k,l)
Notes:
- Uses x-ray atomic form factors, calculated from approximated tables in the ITC
- This may be a little slow for large numbers of reflections, as it is not currently
 possible to use accelerated calculation methods in Jython.
- Debye-Waller factor (atomic displacement) is applied for isotropic ADPs
- Crystal.scale is used to scale the complex structure factor, so the intensity is
 reduced by (Crystal.scale)^2
- Testing against structure factors calculated by Vesta.exe is exactly the same when using Waasmaier structure factors.
 
Save/Load behaviour
    structure_factor(..., save='sf.npy')  # saves structure factors after calculation in compressed file
    structure_factor(..., load='sf.npy')  # loads structure factors if sf.npy, rather than calculating
      - if the number of values in load doesn't match the number of hkl indices, an Exception is raised
 
:param hkl: array[n,3] : reflection indexes (h, k, l)
:param scattering_type: str : one of ['xray','neutron','xray magnetic','neutron magnetic','xray resonant']
:param int_hkl: Bool : when True, hkl values are converted to integer.
:param kwargs: additional options to pass to scattering function
:return: complex array[n] : structure factors
x_ray(self, HKL)
Calculate the squared structure factor for the given HKL, using x-ray scattering factors
  Scattering.x_ray([1,0,0])
  Scattering.x_ray([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
x_ray_fast(self, HKL)
Calculate the squared structure factor for the given HKL, using atomic number as scattering length
  Scattering.x_ray_fast([1,0,0])
  Scattering.x_ray_fast([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
xray_dispersion(self, HKL, energy_kev)
Calculate the squared structure factor for the given HKL,
using x-ray scattering factors with dispersion corrections
  Scattering.xray_dispersion([1,0,0], 9.71)
  Scattering.xray_dispersion([[1,0,0],[2,0,0],[3,0,0]], 2.838)
  Scattering.xray_dispersion([[1,0,0],[2,0,0],[3,0,0]], np.arange(2.83, 2.86, 0.001))
Returns an array with the same length as HKL, giving the real intensity at each reflection.
if energy_kev is an array, the returned array will have shape [len(HKL), len(energy_kev)]
xray_magnetic(self, HKL)
Calculate the non-resonant magnetic component of the structure factor 
for the given HKL, using x-ray rules and form factor
  Scattering.xray_magnetic([1,0,0])
  Scattering.xray_magnetic([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
 
From Hill+McMorrow Acta Cryst. 1996 A52, 236-244 Equ. (2)
Book: "X-ray Scattering and Absorption by Magnetic Materials" by Loevesy and Collins. Ch 2. Eqn.2.21+1
No orbital component assumed
magnetic moments assumed to be in the same reference frame as the polarisation
xray_nonresonant_magnetic(self, HKL, energy_kev=None, azim_zero=[1, 0, 0], psi=0, polarisation='s-p', disp=False)
Calculate the non-resonant magnetic component of the structure factor
for the given HKL, using x-ray rules and form factor
  Scattering.xray_magnetic([1,0,0])
  Scattering.xray_magnetic([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
 
From Hill+McMorrow Acta Cryst. 1996 A52, 236-244 Equ. (2)
Book: "X-ray Scattering and Absorption by Magnetic Materials" by Loevesy and Collins. Ch 2. Eqn.2.21+1
No orbital component assumed
magnetic moments assumed to be in the same reference frame as the polarisation
xray_resonant(self, HKL, energy_kev=None, polarisation='sp', F0=1, F1=1, F2=1, azim_zero=[1, 0, 0], PSI=[0], disp=False)
Calculate structure factors using resonant scattering factors in the dipolar approximation
  I = Scattering.xray_resonant(HKL,energy_kev,polarisation,F0,F1,F2)
Returns an array with the same length as HKL, giving the real intensity at each reflection.
    energy_kev = x-ray energy in keV
    polarisation = x-ray polarisation: 'ss',{'sp'},'ps','pp'
    F0/1/2 = Resonance factor Flm
    azim_zero = [h,k,l] vector parallel to the origin of the azimuth
    psi = azimuthal angle defining the scattering plane
 
Uses the E1E1 resonant x-ray scattering amplitude:
    fxr_n = (ef.ei)*F0 -i(ef X ei).z_n*F1 + (ef.z_n)(ei.z_n)F2
 
Where ei and ef are the initial and final polarisation states, respectively,
and z_n is a unit vector in the direction of the magnetic moment of the nth ion.
The polarisation states are determined to be one of the natural synchrotron 
states, where sigma (s) is perpendicular to the scattering plane and pi (p) is
parallel to it.
        ( s-s  s-p )
        ( p-s  p-p )
 
From Hill+McMorrow Acta Cryst. 1996 A52, 236-244 Equ. (15)
xray_resonant_magnetic(self, HKL, energy_kev=None, azim_zero=[1, 0, 0], psi=0, polarisation='s-p', F0=0, F1=1, F2=0, disp=True)
Calculate the resonant magnetic component of the structure factor
for the given HKL, using x-ray rules and form factor
  Scattering.xray_magnetic([1,0,0])
  Scattering.xray_magnetic([[1,0,0],[2,0,0],[3,0,0])
Returns an array with the same length as HKL, giving the real intensity at each reflection.
 
From Hill+McMorrow Acta Cryst. 1996 A52, 236-244 Equ. (2)
Book: "X-ray Scattering and Absorption by Magnetic Materials" by Loevesy and Collins. Ch 2. Eqn.2.21+1
No orbital component assumed
magnetic moments assumed to be in the same reference frame as the polarisation
xray_resonant_scattering_factor(self, HKL, energy_kev=None, polarisation='sp', F0=1, F1=1, F2=1, azim_zero=[1, 0, 0], psi=0, disp=False)
Calcualte fxres, the resonant x-ray scattering factor
  fxres = Scattering.xray_resonant_scattering_factor(HKL,energy_kev,polarisation,F0,F1,F2,azim_zero,psi)
energy_kev = x-ray energy in keV
    polarisation = x-ray polarisation: 'ss',{'sp'},'ps','pp'
    F0/1/2 = Resonance factor Flm
    azim_zero = [h,k,l] vector parallel to the origin of the azimuth {[1,0,0]}
    psi = azimuthal angle defining the scattering plane {0}
 
Uses the E1E1 resonant x-ray scattering amplitude:
    fxr_n = (ef.ei)*F0 -i(ef X ei).z_n*F1 + (ef.z_n)(ei.z_n)F2
 
Where ei and ef are the initial and final polarisation states, respectively,
and z_n is a unit vector in the direction of the magnetic moment of the nth ion.
The polarisation states are determined to be one of the natural synchrotron 
states, where sigma (s) is perpendicular to the scattering plane and pi (p) is
parallel to it.
        ( s-s  s-p )
        ( p-s  p-p )
 
From Hill+McMorrow Acta Cryst. 1996 A52, 236-244 Equ. (15)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class ScatteringTypes(builtins.object)
    ScatteringTypes(parent, typedict)
 
Container for available scattering types
 
  Methods defined here:
__call__(self, type)
Calling this container with a scattering type will set the scattering type in the parent class
:param type: str scattering type
:return: None
__init__(self, parent, typedict)
Initialize self.  See help(type(self)) for accurate signature.
i16(self)
Set max/min angles consistent with reflection geometry on beamline I16
:return: None
wish(self)
Set max/min angles consistent with reflection geometry on beamline I16
:return: None

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

Data and other attributes defined here:
ScatteringType = <class 'Dans_Diffraction.classes_scattering.ScatteringTypes.ScatteringType'>
Container for scattering type switcher

 
Data
        __scattering_types__ = {'neutron': ['neutron', 'n', 'nuclear'], 'neutron magnetic': ['neutron magnetic', 'magnetic neutron', 'magnetic'], 'xray': ['xray', 'x', 'x-ray', 'thomson', 'charge'], 'xray dispersion': ['dispersion', 'xray dispersion'], 'xray magnetic': ['xray magnetic', 'magnetic xray', 'spin xray', 'xray spin'], 'xray resonant': ['xray resonant', 'resonant', 'resonant xray', 'rxs']}