1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
# This program is in the public domain
# Author: Paul Kienzle
"""
Helper functions
"""
from math import sqrt
def parse_uncertainty(s):
"""
Given a floating point value plus uncertainty return the pair (val, unc).
Format is val, val(unc), [nominal] or [low,high].
The val(unc) form is like 23.0035(12), but also 23(1), 23.0(1.0), or
maybe even 23(1.0). This parser does not handle exponential notation
such as 1.032(4)E10
The nominal form has zero uncertainty, as does a bare value.
The [low,high] form is assumed to be a rectangular distribution of 1-sigma
equivalent width (high-low)/sqrt(12).
An empty string is returned as None,None rather than 0,inf.
"""
if s == "": # missing
# TODO: maybe 0 +/- inf ?
return None, None
# Parse [nominal] or [low,high]
if s.startswith('['):
s = s[1:-1]
parts = s.split(',')
if len(parts) > 1:
low, high = float(parts[0]), float(parts[1])
# Use equivalent 1-sigma width for a rectangular distribution
return (high+low)/2, (high-low)/sqrt(12)
else:
return float(parts[0]), 0
# Parse value(unc) with perhaps '#' at the end
parts = s.split('(')
if len(parts) > 1:
# Split the value and uncertainty.
value, unc = parts[0], parts[1].split(')')[0]
# Count digits after the decimal for value and produce
# 0.00...0{unc} with the right number of zeros.
# e.g., 23.0035(12) but not 23(1) or 23.0(1.0) or 23(1.0)
if '.' not in unc and '.' in value:
zeros = len(value.split('.')[1]) - len(unc)
unc = "0." + ("0"*zeros) + unc
return float(value), float(unc)
# Plain value with no uncertainty
return float(s), 0
def cell_volume(a=None, b=None, c=None, alpha=None, beta=None, gamma=None):
r"""
Compute cell volume from lattice parameters.
:Parameters:
*a*, *b*, *c* : float | |Ang|
Lattice spacings. *a* is required.
*b* and *c* default to *a*.
*alpha*, *beta*, *gamma* : float | |deg|
Lattice angles. *alpha* defaults to 90\ |deg|.
*beta* and *gamma* default to *alpha*.
:Returns:
*V* : float | |Ang^3|
Cell volume
:Raises:
*TypeError* : missing or invalid parameters
The following formula works for all lattice types:
.. math::
V = a b c \sqrt{1 - \cos^2 \alpha - \cos^2 \beta - \cos^2 \gamma
+ 2 \cos \alpha \cos \beta \cos \gamma}
"""
from math import cos, radians, sqrt
if a is None:
raise TypeError('missing lattice parameters')
if b is None:
b = a
if c is None:
c = a
calpha = cos(radians(alpha)) if alpha is not None else 0
cbeta = cos(radians(beta)) if beta is not None else calpha
cgamma = cos(radians(gamma)) if gamma is not None else calpha
V = a*b*c*sqrt(1 - calpha**2 - cbeta**2 - cgamma**2 + 2*calpha*cbeta*cgamma)
return V
|