Files
dev/script/__Lib/diffcalc-2.1/diffcalc/hkl/you/geometry.py
2019-03-20 13:52:00 +01:00

220 lines
7.0 KiB
Python
Executable File

###
# Copyright 2008-2011 Diamond Light Source Ltd.
# This file is part of Diffcalc.
#
# Diffcalc is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Diffcalc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Diffcalc. If not, see <http://www.gnu.org/licenses/>.
###
from math import pi
from diffcalc.util import AbstractPosition, DiffcalcException
TORAD = pi / 180
TODEG = 180 / pi
from diffcalc.util import x_rotation, z_rotation, y_rotation
from diffcalc.hkl.you.constraints import NUNAME
class YouGeometry(object):
def __init__(self, name, fixed_constraints, beamline_axes_transform=None):
self.name = name
self.fixed_constraints = fixed_constraints
# beamline_axes_transform matrix is composed of the diffcalc basis vector coordinates
# in the beamline coordinate system, i.e. it transforms the beamline coordinate system
# into the reference diffcalc one.
self.beamline_axes_transform = beamline_axes_transform
def physical_angles_to_internal_position(self, physical_angle_tuple):
raise NotImplementedError()
def internal_position_to_physical_angles(self, internal_position):
raise NotImplementedError()
def create_position(self, *args):
return YouPosition(*args, unit='DEG')
#==============================================================================
#==============================================================================
# Geometry plugins for use with 'You' hkl calculation engine
#==============================================================================
#==============================================================================
class SixCircle(YouGeometry):
def __init__(self, beamline_axes_transform=None):
YouGeometry.__init__(self, 'sixc', {}, beamline_axes_transform)
def physical_angles_to_internal_position(self, physical_angle_tuple):
# mu, delta, nu, eta, chi, phi
return YouPosition(*physical_angle_tuple, unit='DEG')
def internal_position_to_physical_angles(self, internal_position):
clone_position = internal_position.clone()
clone_position.changeToDegrees()
return clone_position.totuple()
class FourCircle(YouGeometry):
"""For a diffractometer with angles:
delta, eta, chi, phi
"""
def __init__(self, beamline_axes_transform=None):
YouGeometry.__init__(self, 'fourc', {'mu': 0, NUNAME: 0}, beamline_axes_transform)
def physical_angles_to_internal_position(self, physical_angle_tuple):
# mu, delta, nu, eta, chi, phi
delta, eta, chi, phi = physical_angle_tuple
return YouPosition(0, delta, 0, eta, chi, phi, 'DEG')
def internal_position_to_physical_angles(self, internal_position):
clone_position = internal_position.clone()
clone_position.changeToDegrees()
_, delta, _, eta, chi, phi = clone_position.totuple()
return delta, eta, chi, phi
class FiveCircle(YouGeometry):
"""For a diffractometer with angles:
delta, nu, eta, chi, phi
"""
def __init__(self, beamline_axes_transform=None):
YouGeometry.__init__(self, 'fivec', {'mu': 0}, beamline_axes_transform)
def physical_angles_to_internal_position(self, physical_angle_tuple):
# mu, delta, nu, eta, chi, phi
delta, nu, eta, chi, phi = physical_angle_tuple
return YouPosition(0, delta, nu, eta, chi, phi, 'DEG')
def internal_position_to_physical_angles(self, internal_position):
clone_position = internal_position.clone()
clone_position.changeToDegrees()
_, delta, nu, eta, chi, phi = clone_position.totuple()
return delta, nu, eta, chi, phi
#==============================================================================
def create_you_matrices(mu=None, delta=None, nu=None, eta=None, chi=None,
phi=None):
"""
Create transformation matrices from H. You's paper.
"""
MU = None if mu is None else calcMU(mu)
DELTA = None if delta is None else calcDELTA(delta)
NU = None if nu is None else calcNU(nu)
ETA = None if eta is None else calcETA(eta)
CHI = None if chi is None else calcCHI(chi)
PHI = None if phi is None else calcPHI(phi)
return MU, DELTA, NU, ETA, CHI, PHI
def calcNU(nu):
return x_rotation(nu)
def calcDELTA(delta):
return z_rotation(-delta)
def calcMU(mu_or_alpha):
return x_rotation(mu_or_alpha)
def calcETA(eta):
return z_rotation(-eta)
def calcCHI(chi):
return y_rotation(chi)
def calcPHI(phi):
return z_rotation(-phi)
def you_position_names():
return ('mu', 'delta', NUNAME, 'eta', 'chi', 'phi')
class YouPosition(AbstractPosition):
def __init__(self, mu, delta, nu, eta, chi, phi, unit):
self.mu = mu
self.delta = delta
self.nu = nu
self.eta = eta
self.chi = chi
self.phi = phi
if unit not in ['DEG', 'RAD']:
raise DiffcalcException("Invalid angle unit value %s." % str(unit))
else:
self.unit = unit
def clone(self):
return YouPosition(self.mu, self.delta, self.nu, self.eta, self.chi,
self.phi, self.unit)
def changeToRadians(self):
if self.unit == 'DEG':
self.mu *= TORAD
self.delta *= TORAD
self.nu *= TORAD
self.eta *= TORAD
self.chi *= TORAD
self.phi *= TORAD
self.unit = 'RAD'
elif self.unit == 'RAD':
return
else:
raise DiffcalcException("Invalid angle unit value %s." % str(self.unit))
def changeToDegrees(self):
if self.unit == 'RAD':
self.mu *= TODEG
self.delta *= TODEG
self.nu *= TODEG
self.eta *= TODEG
self.chi *= TODEG
self.phi *= TODEG
self.unit = 'DEG'
elif self.unit == 'DEG':
return
else:
raise DiffcalcException("Invalid angle unit value %s." % str(self.unit))
def totuple(self):
return (self.mu, self.delta, self.nu, self.eta, self.chi, self.phi)
def __str__(self):
mu, delta, nu, eta, chi, phi = self.totuple()
return ("YouPosition(mu %r delta: %r nu: %r eta: %r chi: %r phi: %r) in %s"
% (mu, delta, nu, eta, chi, phi, self.unit))
def __eq__(self, other):
return self.totuple() == other.totuple()
class WillmottHorizontalPosition(YouPosition):
def __init__(self, delta=None, gamma=None, omegah=None, phi=None):
self.mu = 0
self.delta = delta
self.nu = gamma
self.eta = omegah
self.chi = -90
self.phi = phi
self.unit= 'DEG'