Dans_Diffraction (version 3.3.3, 2025/02/06)
index
c:\users\grp66007\onedrive - diamond light source ltd\pythonprojects\dans_diffraction\dans_diffraction\__init__.py

Dans_Diffraction
Python package for loading crystal structures from cif files and calculating diffraction information.
 
Installation:
$ python -m pip install Dans-Diffraction
or
$ git clone https://github.com/DanPorter/Dans_Diffraction.git
or
$ python -m pip install git+https://github.com/DanPorter/Dans_Diffraction.git
 
Requirements:
Python 3.5+ with packages: Numpy, Matplotlib, Tkinter
BuiltIn packages used: sys, os, re, glob, warnings, json, itertools
 
Usage:
    ***In Python/ script***
    import Dans_Diffraction as dif
    f = '/location/of/file.cif'
    xtl = dif.Crystal(f)
    
Usage:
    ***From Terminal***
    $ cd /location/of/file
    $ ipython -i -m -matplotlib tk Dans_Diffraction
 
GitHub Repo: https://github.com/DanPorter/Dans_Diffraction
Citation DOI: https://doi.org/10.5281/zenodo.8106031
 
By Dan Porter, PhD
Diamond
2017-2025
 
Version 3.3.3
Last updated: 06/02/2025
 
Version History:
02/03/18 1.0    Version History started.
30/05/18 1.1    Fdmnes added
08/06/18 1.2    Python3 now fully supported
23/02/19 1.3    Graphical user intrface and magnetic x-ray scattering now implemented
13/07/19 1.4    FDMNES GUI functionality added
13/12/19 1.5    Multiple Scattering added, tkGUI refactored, Startgui changed to start_gui
20/02/20 1.6    Tensor Scattering added
31/03/20 1.7    Refactored multicrystal methods, other minor changes, improved powder diffraction
19/04/20 1.7.1  Added write_cif + spacegroup file + functions
02/05/20 1.8    Updated readcif, added heavy atom properties, added magnetic spacegroups
12/05/20 1.8.1  Updated readcif, added atomic_scattering_factors and classes_orbitals
26/05/20 1.8.2  Updated copyright, removed tensor scattering. Updated magnetic spacegroups
09/06/20 1.9    Chaneged magnetic symmetry calculation, now correctly generates mag symmetry from operations
10/06/20 1.9.1  Added time symmetry to Symmetry class
16/06/20 1.9.2  Made change in simpulate_powder to remove linspace error
29/06/20 1.9.3  Removed import of scipy.convolve2d due to import errrors, new method slower but more accurate
02/09/20 1.9.4  Added string methods to Crystal classes
26/11/20 1.9.5  Various improvements and corrections
04/01/21 1.9.6  Added Scattering.structure_factor function
26/01/21 1.9.7  Added xray dispersion correction functions, plus x-ray interactions calculations
15/02/21 1.9.8  Added plotting options for out-of-plane recirprocal lattice lines
10/06/21 1.9.9  Corrected error in calculation of DebyeWaller factor (APDs), added x-ray factors by Waasmaier and Kirfel
09/07/21 1.9.9  Added new scattering factors to scattering factor settings
20/08/21 2.0.0  Added functions_scattering module with updated, more consistent scattering formula
27/09/21 2.1.0  Added classes_orientation and diffractometer orientation functions
15/11/21 2.1.1  Updated Plot.plot_crystal, added additional orientation functions
07/02/22 2.1.2  Corrected error in classes_scattering.powder() of wrong tth values. Thanks Mirko!
14/03/22 2.2.0  Scatter.powder() updated for new inputs and outputs for pVoight and custom peak shapes. Thanks yevgenyr!
23/07/22 2.2.1  Fixed error in MultiCrystal.Scatter
06/01/23 2.2.2  Removed redundent references to np.float
14/01/23 2.2.3  Corrected background error in xtl.Scatter.powder
08/05/23 2.3.0  Merged pull request for non-integer hkl option on SF and electron form factors. Thanks Prestipino!
25/06/23 3.0.0  Added new GUI elements including new Scattering UI and diffractomter simulator, plus other updates
11/07/23 3.0.1  Some fixes for plotting and additions to diffractometer orientation. Thanks asteppke!
20/07/23 3.1.0  Refactored FDMNES wrapper with new methods and new defaults. Thanks YvesJoly!
26/09/23 3.1.1  Minor changes and improvments. Added hkl1, hkl2 = xtl.scatter.orientation_reflections()
19/10/23 3.1.2  xray_resonant() now works with non-cubic systems, fixed scaling issue in diffractometer.py
25/10/23 3.1.3  Fixed error with powder plot for Neutrons. Thanks Cyril!
28/03/24 3.1.4  Fixed error with site symmetries having spaces in AtomsGui, added Properties.relative_positions()
10/05/24 3.1.5  Fixed SyntaxWarnings from Unrecognized escape sequences in Python 3.12, various fixes to scattering
15/05/24 3.2.0  Added "save" and "load" methods to structure factor calculation, improved powder for large calculations
20/05/24 3.2.1  Added pyproject.toml file for installation, including dansdiffraction script
29/07/24 3.2.2  Fix for issue #19 in multiple_scattering code, other minor improvements
04/09/24 3.2.3  Updated method of generating charge states in classes_orbtials.py, Thanks Seonghun!
25/09/24 3.2.4  Fixed error of missing rotation matrices after load_spacegroup. Thanks asteppke!
26/09/24 3.3.0  Added complex neutron scattering lengths for isotopes from package periodictable. Thanks thamnos!
06/11/24 3.3.1  Fixed incorrect cell basis for triclinic cells. Added functions_lattice.py and tests. Thanks LeeRichter!
20/11/24 3.3.2  Added alternate option for neutron scattering lengths
06/02/25 3.3.3  Added scattering options for polarised neutron and x-ray scattering. Thanks dragonyanglong!
 
Acknoledgements:
    2018        Thanks to Hepesu for help with Python3 support and ideas about breaking up calculations
    Dec 2019    Thanks to Gareth Nisbet for allowing me to inlude his multiple scattering siumulation
    April 2020  Thanks to ChunHai Wang for helpful suggestions in readcif!
    May 2020    Thanks to AndreEbel for helpful suggestions on citations
    Dec 2020    Thanks to Chris Drozdowski for suggestions about reflection families
    Jan 2021    Thanks to aslarsen for suggestions about outputting the structure factor
    April 2021  Thanks to Trygve Ræder for suggestions about x-ray scattering factors
    Feb 2022    Thanks to Mirko for pointing out the error in two-theta values in Scatter.powder
    March 2022  Thanks to yevgenyr for suggesting new peak profiles in Scatter.powder
    Jan 2023    Thanks to Anuradha Vibhakar for pointing out the error in f0 + if'-if''
    Jan 2023    Thanks to Andreas Rosnes for testing the installation in jupyterlab
    May 2023    Thanks to Carmelo Prestipino for adding electron scattering factors
    June 2023   Thanks to Sergio I. Rincon for pointing out the rounding error in Scatter.powder
    July 2023   Thanks to asteppke for suggested update to Arrow3D for matplotlib V>3.4
    July 2023   Thanks to Yves Joly for helpful suggestions on FDMNES wrapper
    Oct 2023    Thanks to asteppke for pointing out scaling issue in diffractometer gui
    Oct 2023    Thanks to Cyril Cayron for pointing out the error with plotting neutron power spectra
    Jan 2024    Thanks to Carmelo Prestipino for adding search_distance and plot_distance
    May 2024    Thanks to Innbig for spotting some errors in large liquid crystal powder patterns
    May 2024    Thanks to paul-cares pointing out a silly spelling error in the title!
    Aug 2024    Thanks to Seonghun for pointing out the error with charge states in Hf
    Aug 2024    Thanks to MaxPelly for spell checks in examples
    Sep 2024    Thanks to thamnos for suggestion to add complex neutron scattering lengths
    Oct 2024    Thanks to Lee Richter for pointing out the error in triclinic basis definition
    Dec 2024    Thanks to dragonyanglong for pointing out the error with magnetic neutron scattering
 
-----------------------------------------------------------------------------
   Copyright 2024 Diamond Light Source Ltd.
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
 
       http://www.apache.org/licenses/LICENSE-2.0
 
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 
Files in this package covered by this licence:
    classes_crystal.py
    classes_scattering.py
    classes_plotting.py
    classes_properties.py
    classes_multicrystal.py
    classes_orbitals.py
    functions_general.py
    functions_plotting.py
    functions_crystallography.py
    tkgui/*.py
Other files are either covered by their own licence or not licenced for other use.
 
 Dr Daniel G Porter, dan.porter@diamond.ac.uk
 www.diamond.ac.uk
 Diamond Light Source, Chilton, Didcot, Oxon, OX11 0DE, U.K.

 
Package Contents
       
__main__
classes_crystal
classes_fdmnes
classes_multicrystal
classes_orbitals
classes_orientation
classes_plotting
classes_properties
classes_scattering
classes_structures
functions_crystallography
functions_general
functions_lattice
functions_plotting
functions_scattering
multiple_scattering
tensor_scattering
tkgui (package)

 
Classes
       
builtins.object
Dans_Diffraction.classes_crystal.Crystal
Dans_Diffraction.classes_fdmnes.Fdmnes
Dans_Diffraction.classes_fdmnes.FdmnesAnalysis
Dans_Diffraction.classes_multicrystal.MultiCrystal
Dans_Diffraction.classes_structures.Structures

 
class Crystal(builtins.object)
    Crystal(filename=None)
 
Reads the structure information from a cif file and generates the full structure.
Allows the adjustment of the structure through the lattice parameters, symmetry 
or atomic displacement.
Can calculate reflection intensities and two-theta values.
 
E.G.
  xtl = Crystal('Diamond.cif')
  xtl.Cell.lp() >> give the lattice parameters
  xtl.Atoms.uvw() >> give the symmetric atomic positions
  xtl.Symmetry.symmetry_operations >> give symmetry operations
  xtl.Structure.uvw() >> give the full, unsymmetrised structure
  xtl.Scatter.hkl([1,0,0],8.00) >> prints the intensity and two-theta of this reflection at this energy
  xtl.Scatter.print_all_reflections(8.00) >> print all allowed reflections, with intensities, at this energy
  xtl.write_cif('Diamond2.cif') >> write updated structure to file
 
To create your own crystal (BCC example):
  xtl = Crystal()
  xtl.new_latt([2.866])
  xtl.new_atoms(u=[0,0.5],
                v=[0,0.5],
                w=[0,0.5],
                type=['Fe','Fe'])
  xtl.hkl([[1,0,0],[1,1,0],[1,1,1],[2,0,0]])
 
Also, see:
    help(xtl.Cell)
    help(xtl.Atoms)
    help(xtl.Symmetry)
    help(xtl.Scatter)
 
  Methods defined here:
__add__(self, other)
__init__(self, filename=None)
Initialize self.  See help(type(self)) for accurate signature.
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
add_parent(self, parent, P)
Add parent structure, returning Crystal as superstructure
    parent = Crystal(cif_parent)
    xtl = Crystal(cif_superstructure)
    su = xtl.add_parent(parent, [[1,1,0],[0,2,0],[0,0,1]])
generate_lattice(self, U=1, V=1, W=0)
Generate a repeated lattice of the crystal structure
    latt = xtl.generate_lattice(2,0,0)
:param U: Repeat of the cell along the a axis
:param V: Repeat of the cell along the b axis
:param W: Repeat of the cell along the c axis
:return: Crystal object
generate_structure(self)
Combines the atomic positions with symmetry operations, returning the full structure as an Atoms class
:return: None
generate_superstructure(self, P)
Generate a superstructure of the current cell
    a' = n1a + n2b + n3c
    b' = m1a + m2b + m3c
    c' = o1a + o2b + o3c
            OR
    [a',b',c'] = P[a,b,c]
            Where
    P = [[n1,n2,n3],
         [m1,m2,m3],
         [o1,o2,o3]]
Returns a superstructure Crystal class:
    su = xtl.generate_superstructrue([[2,0,0],[0,2,0],[0,0,1]])
 
Superstructure Crystal classes have additional attributes:
    su.P = P as given
    su.Parent = the parent Crystal Class
 
Use >>hasattr(su,'Parent') to check if the current object is a
superstructure Crystal class
info(self)
Returns information about the crystal structure
:return: str
invert_structure(self)
Convert handedness of structure, transform from left-handed to right handed, or visa-versa
Equivlent to xtl.transform([[-1,0,0], [0,-1,0], [0,0,-1]])
:return: Superstructure Crystal class
new_atoms(self, u=[0], v=[0], w=[0], type=None, label=None, occupancy=None, uiso=None, mxmymz=None)
Replace current atomic positions with new ones and regenerate structure
:param u: array : atomic positions u
:param v: array : atomic positions v
:param w:  array : atomic positions w
:param type:  array : atomic types
:param label: array : atomic labels
:param occupancy: array : atomic occupation
:param uiso: array : atomic isotropic thermal parameters
:param mxmymz: array : atomic magnetic vectors [mu,mv,mw]
:return: None
new_cell(self, *lattice_parameters, **kwargs)
Replace the lattice parameters
:param lattice_parameters: [a,b,c,alpha,beta,gamma]
:return: None
search_distances(self, min_d=0.65, max_d=3.2, c_ele=None, elems=None, labels=None, simple=True)
Calculated atoms interatomic distances form each label.
:param c_ele (list,string): only sites with noted elements
                            if None all site
:param elems (list,string): only distances with noted elements
                            if None all site
:param min_d: minimum distance 
:param max_d: maximum distance
:return dictionary:
start_gui(self)
Start Crystal GUI
:return: None
transform(self, P)
Transform the current cell
    a' = n1a + n2b + n3c
    b' = m1a + m2b + m3c
    c' = o1a + o2b + o3c
            OR
    [a',b',c'] = P[a,b,c]
            Where
    P = [[n1,n2,n3],
         [m1,m2,m3],
         [o1,o2,o3]]
Returns a superstructure Crystal class:
    su = xtl.transform([[0,1,0],[1,0,0],[0,0,1]])
 
Superstructure Crystal classes have additional attributes:
    su.P = P as given
    su.Parent = the parent Crystal Class
 
Use >>hasattr(su,'Parent') to check if the current object is a
superstructure Crystal class
update_cif(self, cifvals=None)
Update self.cif dict with current values
:param cifvals: cif dict from readcif (None to use self.cif)
:return: cifvals
write_cif(self, filename=None, comments=None)
Write crystal structure to CIF (Crystallographic Information File)
 Only basic information is saved to the file, but enough to open in VESTA etc.
 If magnetic ions are defined, a magnetic cif (*.mcif) will be produce
:param filename: name to write too, if None, use writes to self.name (.cif/.mcif)
:param comments: str comments to add to file header
: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:
cif = {}
filename = ''
name = 'Crystal'
scale = 1.0

 
class Fdmnes(builtins.object)
    Fdmnes(xtl=Crystal with 1 atomic positions, 1 symmetries)
 
FDMNES class: Create input files for the FDMNES software and run the program inside a python console
 
FDMNES (Finite Difference Method for Near Edge Structure) is an abinitio DFT program for
simulating x-ray absorption spectra and resonant diffraction.
FDMNES is developed by Yves Joly at CNRS and can be freely downloaded from here:
  www.fdmnes.neel.cnrs.fr
 
In case of publication, please include the following citation:
  O. Bunau and Y. Joly "Self-consistent aspects of x-ray absorption calculations"
  J. Phys.: Condens. Matter 21, 345501 (2009)
 
This class creates a simple wrapper to automatically generate input files from Dans_Diffraction
Crystal structures. The output files from the calculation can also be automatically plotted.
 
E.G.
xtl = Crystal('Co.cif')
fdm = Fdmnes(xtl)
fdm.setup(folder_name='New_Calculation',
          comment='Test',
          absorber='Co',
          edge='K'
          azi_ref=[0,0,1],
          hkl_reflections=[[1,0,0],[0,1,0],[1,1,0]]
fdm.create_files()
fdm.write_fdmfile()
fdm.run_fdmnes()
###Wait for program completion###
analysis = fdm.analyse()
print(analysis)
analysis.xanes.plot()
analysis.density.plot()
for ref in analysis:
    ref.plot3D()
 
  Methods defined here:
__init__(self, xtl=Crystal with 1 atomic positions, 1 symmetries)
Initialize self.  See help(type(self)) for accurate signature.
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
analyse(self, folder_name=None)
Analyse the completed calculation
:param folder_name: str name or directory of calculation (None to use current calculation)
:return: FdmnesAnalysis Object
azimuthal_reference(self, hkl=(1, 0, 0))
Generate the azimuthal reference
:param hkl: (1*3) array [h,k,l]
:return: None
create_directory(self)
Create a directory in the FDMNES/Sim folder
:return: None
create_files(self, param_string=None)
Create FDMNES calculation directory and files
 - creates new directory
 - writes the input file to that directory
:param param_string: str text to add to indata file (None will generate)
:return: None
find_fdmnes_exe(self, initial_dir=None, fdmnes_filename='fdmnes_win64.exe', reset=False)
Find fdmnes executable
generate_input_path(self)
Returns the input file pathname
 E.G. 'c:\FDMNES\Sim\Fe2O3\FDMNES_Fe2O3.txt'
:return: filepath
generate_output_path(self, folder_name=None, overwrite=False)
Creates an automatic output path in the FDMNES/Sim directory
 If overwrite is False and the directory already exists, a number will be appended to the name
:param folder_name: str or None, if None xtl.name will be used
:param overwrite: True/False
:return: str directory E.G. 'c:\FDMNES\Sim\Fe2O3'
generate_parameters_string(self)
Create the string of parameters and comments for the input file
:return: str
info(self)
Print setup info
:return: str
run_fdmnes(self)
Run the fdmnes code, waits until the program completes
Remember to use self.create_files and self.write_fdmfile first!
:return: subprocess.call output
setup(self, exe_path=None, output_path=None, output_name=None, folder_name=None, input_name=None, comment=None, energy_range=None, radius=None, edge=None, absorber=None, green=None, scf=None, quadrupole=None, azi_ref=None, correct_azi=None, hkl_reflections=None)
Set FDMNES Parameters
:param exe_path: Location of FDMNES executable, e.g. 'c:\FDMNES\fdmnes_win64.exe'
:param output_path: Specify the output path
:param folder_name: Specify output folder name (replaces output_path)
:param output_name: Name of FDMNES output files
:param input_name: Name of FDMNES input file
:param comment: A comment written in the input file
:param energy_range: str energy range in eV relative to Fermi energy
:param radius: calculation radius
:param edge: absorptin edge, 'K', 'L3', 'L2'
:param absorber: absorbing element, 'Co'
:param green: Green's function (muffin-tin potential)
:param scf: True/False, Self consistent solution
:param quadrupole: False/True, E1E2 terms allowed
:param azi_ref: azimuthal reference, [1,0,0]
:param correct_azi: if True, correct azimuthal reference for real cell (use in hexagonal systems)
:param hkl_reflections: list of hkl reflections [[1,0,0],[0,1,0]]
:return: None
write_fdmfile(self, file_list=None)
Create fdmfile with list of calculations
:param file_list: list of parameter file names for fdmfile, or None to only calculate current parameters
:return: None
write_runfile(self, param_string=None)
Write FDMNES input data to a file
:param param_string: str text to add to indata file (None will generate)
:return: None

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

 
class FdmnesAnalysis(builtins.object)
    FdmnesAnalysis(output_path, output_name='out', calc_name=None)
 
Create fdmnes object from *_scan_conv.txt file
 
Usage:
    fdm = FdmnesAnalysis(output_path, output_name)
 
    fdm contains all calculated reflections and xanes spectra, as well as spherical tensors
    Automated plotting of azimuths, spectra and density of states.
 
    fdm.xanes.plot()
    fdm.density.plot()
    fdm.I100sp.plot3D()
    fdm.sph_I100sp.plot()
 
  Methods defined here:
__add__(self, other)
__getitem__(self, item)
Return Reflection
__init__(self, output_path, output_name='out', calc_name=None)
Loads data from an FDMNES calculation, allowing plotting and data cuts
 E.G.
 fdm = FdmnesAnalysis('c:\FDMNES\Fe2O3','out')
 fdm.xanes.plot()
 plt.show()
 
:param output_path: directory of the calculation to be loaded
:param output_name: base output name for the calculation (default='out')
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
info(self)
Returns header of calculation output fipe (*_bav.txt)
:return: str

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:
angle = array([0])
energy = array([0])
refkeys = []
reflections = {}
reflist = []
sphkeys = []

 
class MultiCrystal(builtins.object)
    MultiCrystal(crystal_list)
 
Multi_Crystal class for combining multiple phases
 
  Methods defined here:
__add__(self, other)
__get__(self, item)
__init__(self, crystal_list)
Multi-crystal class
__repr__(self)
Return repr(self).
__str__(self)
Return str(self).
find_close_reflections(self, HKL, energy_kev=None, max_twotheta=2, max_angle=10)
Find reflections close to the given one  and return list
info(self)
Display information about the contained crystals
orient_6circle(self, phi=0, chi=0, eta=0, mu=0)
Set rotation matrix using 6-circle diffractometer axes
orient_set_r(self, rotation)
Set rotation matrix in diffractometer frame
print_all_reflections(self, energy_kev=None, print_symmetric=False, min_intensity=None, 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
remove(self, index=-1)
Remove crystal [index] from crystal list
set_labframe(self, lab)
Set transformation matrix between diffractometer and lab
set_labframe_i16(self)
Set lab transformation matrix for beamline I16 at Diamond Light Source
set_scale(self, index, scale=1.0)
Set scale of crystal[index]
setup_scatter(self, **kwargs)
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'
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']
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

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

 
class Structures(builtins.object)
    Provides a database of cif files
    S = Structures() # builds database
    xtl = S.Diamond.build()
    
    Use S.list to see the available structures
    Use S.cif_files to see filenames of structures
 
    Iterating over all structures:
    for xtl in S:
        print(xtl)
 
  Methods defined here:
__getitem__(self, item)
__init__(self)
Initialize self.  See help(type(self)) for accurate signature.
__str__(self)
Return str(self).
info(self)
"Print Available Structures

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

 
Functions
       
readcif(filename=None, debug=False)
Open a Crystallographic Information File (*.cif) file and store all entries in a key:value dictionary
 Looped values are stored as lists under a single key entry
 All values are stored as strings
E.G.
  crys=readcif('somefile.cif')
  crys['_cell_length_a'] = '2.835(2)'
 
crys[key] = value
available keys are give by crys.keys()
 
To debug the file with outputted messages, use:
  cif = readcif(file, debug=True)
 
Some useful standard CIF keywords:
    _cell_length_a
    _cell_length_b
    _cell_length_c
    _cell_angle_alpha
    _cell_angle_beta
    _cell_angle_gamma
    _space_group_symop_operation_xyz
    _atom_site_label
    _atom_site_type_symbol
    _atom_site_occupancy
    _atom_site_U_iso_or_equiv
    _atom_site_fract_x
    _atom_site_fract_y
    _atom_site_fract_z

 
Data
        __all__ = ['fg', 'fp', 'fl', 'fc', 'Crystal', 'MultiCrystal', 'readcif', 'Structures', 'Fdmnes', 'FdmnesAnalysis']