Startup
This commit is contained in:
1155
script/__Lib/diffcalc_old/diffcalc/hkl/you/calc.py
Normal file
1155
script/__Lib/diffcalc_old/diffcalc/hkl/you/calc.py
Normal file
File diff suppressed because it is too large
Load Diff
370
script/__Lib/diffcalc_old/diffcalc/hkl/you/constraints.py
Normal file
370
script/__Lib/diffcalc_old/diffcalc/hkl/you/constraints.py
Normal file
@@ -0,0 +1,370 @@
|
||||
###
|
||||
# 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
|
||||
|
||||
try:
|
||||
from numpy import matrix
|
||||
except ImportError:
|
||||
from numjy import matrix
|
||||
|
||||
from diffcalc.util import DiffcalcException, bold
|
||||
|
||||
TODEG = 180 / pi
|
||||
TORAD = pi / 180
|
||||
|
||||
NUNAME = 'gam'
|
||||
|
||||
def filter_dict(d, keys):
|
||||
"""Return a copy of d containing only keys that are in keys"""
|
||||
##return {k: d[k] for k in keys} # requires Python 2.6
|
||||
return dict((k, d[k]) for k in keys if k in d.keys())
|
||||
|
||||
|
||||
det_constraints = ('delta', NUNAME, 'qaz', 'naz')
|
||||
ref_constraints = ('a_eq_b', 'alpha', 'beta', 'psi')
|
||||
samp_constraints = ('mu', 'eta', 'chi', 'phi', 'mu_is_' + NUNAME)
|
||||
|
||||
valueless_constraints = ('a_eq_b', 'mu_is_' + NUNAME)
|
||||
all_constraints = det_constraints + ref_constraints + samp_constraints
|
||||
|
||||
|
||||
number_single_sample = (len(det_constraints) * len(ref_constraints) *
|
||||
len(samp_constraints))
|
||||
|
||||
|
||||
class YouConstraintManager(object):
|
||||
|
||||
def __init__(self, hardware, fixed_constraints = {}):
|
||||
self._hardware = hardware
|
||||
self._constrained = {}
|
||||
# self._tracking = []
|
||||
self.n_phi = matrix([[0], [0], [1]])
|
||||
self._hide_detector_constraint = False # default
|
||||
self._fixed_samp_constraints = ()
|
||||
self._fix_constraints(fixed_constraints)
|
||||
|
||||
def __str__(self):
|
||||
lines = []
|
||||
# TODO: Put somewhere with access to UB matrix!
|
||||
# WIDTH = 13
|
||||
# n_phi = self.n_phi
|
||||
# fmt = "% 9.5f % 9.5f % 9.5f"
|
||||
# lines.append(" n_phi:".ljust(WIDTH) +
|
||||
# fmt % (n_phi[0, 0], n_phi[1, 0], n_phi[2, 0]))
|
||||
# if self._getUBMatrix():
|
||||
# n_cryst = self._getUMatrix().I * self.n_phi
|
||||
# lines.append(" n_cryst:".ljust(WIDTH) +
|
||||
# fmt % (n_cryst[0, 0], n_cryst[1, 0], n_cryst[2, 0]))
|
||||
# n_recip = self._getUBMatrix().I * self.n_phi
|
||||
# lines.append(" n_recip:".ljust(WIDTH) +
|
||||
# fmt % (n_recip[0, 0], n_recip[1, 0], n_recip[2, 0]))
|
||||
# else:
|
||||
# lines.append(
|
||||
# " n_cryst:".ljust(WIDTH) + ' "<<< No U matrix >>>"')
|
||||
# lines.append(
|
||||
# " n_recip:".ljust(WIDTH) + ' "<<< No UB matrix >>>"')
|
||||
|
||||
lines.extend(self.build_display_table_lines())
|
||||
lines.append("")
|
||||
lines.extend(self.report_constraints_lines())
|
||||
lines.append("")
|
||||
if (self.is_fully_constrained() and
|
||||
not self.is_current_mode_implemented()):
|
||||
lines.append(
|
||||
" Sorry, this constraint combination is not implemented")
|
||||
lines.append(" Type 'help con' for available combinations")
|
||||
else:
|
||||
lines.append(" Type 'help con' for instructions") # okay
|
||||
return '\n'.join(lines)
|
||||
|
||||
@property
|
||||
def available_constraint_names(self):
|
||||
"""list of all available constraints"""
|
||||
return all_constraints
|
||||
|
||||
@property
|
||||
def settable_constraint_names(self):
|
||||
"""list of all available constraints that have settable values"""
|
||||
all_copy = list(all_constraints)
|
||||
for valueless in valueless_constraints:
|
||||
all_copy.remove(valueless)
|
||||
return all_copy
|
||||
|
||||
@property
|
||||
def all(self): # @ReservedAssignment
|
||||
"""dictionary of all constrained values"""
|
||||
return self._constrained.copy()
|
||||
|
||||
@property
|
||||
def detector(self):
|
||||
"""dictionary of constrained detector circles"""
|
||||
return filter_dict(self.all, det_constraints[:-1])
|
||||
|
||||
@property
|
||||
def reference(self):
|
||||
"""dictionary of constrained reference circles"""
|
||||
return filter_dict(self.all, ref_constraints)
|
||||
|
||||
@property
|
||||
def sample(self):
|
||||
"""dictionary of constrained sample circles"""
|
||||
return filter_dict(self.all, samp_constraints)
|
||||
|
||||
@property
|
||||
def naz(self):
|
||||
"""dictionary with naz and value if constrained"""
|
||||
return filter_dict(self.all, ('naz',))
|
||||
|
||||
@property
|
||||
def constrained_names(self):
|
||||
"""ordered tuple of constained circles"""
|
||||
names = self.all.keys()
|
||||
names.sort(key=lambda name: list(all_constraints).index(name))
|
||||
return tuple(names)
|
||||
|
||||
def _fix_constraints(self, fixed_constraints):
|
||||
for name in fixed_constraints:
|
||||
self.constrain(name)
|
||||
self.set_constraint(name, fixed_constraints[name])
|
||||
|
||||
if self.detector or self.naz:
|
||||
self._hide_detector_constraint = True
|
||||
|
||||
fixed_samp_constraints = list(self.sample.keys())
|
||||
if 'mu' in self.sample or NUNAME in self.detector:
|
||||
fixed_samp_constraints.append('mu_is_' + NUNAME)
|
||||
self._fixed_samp_constraints = tuple(fixed_samp_constraints)
|
||||
|
||||
|
||||
def is_constrained(self, name):
|
||||
return name in self._constrained
|
||||
|
||||
def get_value(self, name):
|
||||
return self._constrained[name]
|
||||
|
||||
def build_display_table_lines(self):
|
||||
unfixed_samp_constraints = list(samp_constraints)
|
||||
for name in self._fixed_samp_constraints:
|
||||
unfixed_samp_constraints.remove(name)
|
||||
if self._hide_detector_constraint:
|
||||
constraint_types = (ref_constraints, unfixed_samp_constraints)
|
||||
else:
|
||||
constraint_types = (det_constraints, ref_constraints,
|
||||
unfixed_samp_constraints)
|
||||
num_rows = max([len(col) for col in constraint_types])
|
||||
max_name_width = max(
|
||||
[len(name) for name in sum(constraint_types[:-1], ())])
|
||||
|
||||
cells = []
|
||||
|
||||
header_cells = []
|
||||
if not self._hide_detector_constraint:
|
||||
header_cells.append(bold(' ' + 'DET'.ljust(max_name_width)))
|
||||
header_cells.append(bold(' ' + 'REF'.ljust(max_name_width)))
|
||||
header_cells.append(bold(' ' + 'SAMP'))
|
||||
cells.append(header_cells)
|
||||
|
||||
underline_cells = [' ' + '-' * max_name_width] * len(constraint_types)
|
||||
cells.append(underline_cells)
|
||||
|
||||
for n_row in range(num_rows):
|
||||
row_cells = []
|
||||
for col in constraint_types:
|
||||
name = col[n_row] if n_row < len(col) else ''
|
||||
row_cells.append(self._label_constraint(name))
|
||||
row_cells.append(('%-' + str(max_name_width) + 's') % name)
|
||||
cells.append(row_cells)
|
||||
|
||||
lines = [' '.join(row_cells).rstrip() for row_cells in cells]
|
||||
return lines
|
||||
|
||||
def _report_constraint(self, name):
|
||||
val = self.get_constraint(name)
|
||||
if name in valueless_constraints:
|
||||
return " %s" % name
|
||||
else:
|
||||
if val is None:
|
||||
return "! %-5s: ---" % name
|
||||
else:
|
||||
return " %-5s: %.4f" % (name, val)
|
||||
|
||||
def report_constraints_lines(self):
|
||||
lines = []
|
||||
required = 3 - len(self.all)
|
||||
if required == 0:
|
||||
pass
|
||||
elif required == 1:
|
||||
lines.append('! 1 more constraint required')
|
||||
else:
|
||||
lines.append('! %d more constraints required' % required)
|
||||
constraints = []
|
||||
constraints.extend(self.detector.keys())
|
||||
constraints.extend(self.naz.keys())
|
||||
constraints.extend(self.reference.keys())
|
||||
constraints.extend(sorted(self.sample.keys()))
|
||||
for name in constraints:
|
||||
lines.append(self._report_constraint(name))
|
||||
return lines
|
||||
|
||||
def is_fully_constrained(self):
|
||||
return len(self.all) == 3
|
||||
|
||||
def is_current_mode_implemented(self):
|
||||
if not self.is_fully_constrained():
|
||||
raise ValueError("Three constraints required")
|
||||
|
||||
if len(self.sample) == 3:
|
||||
if set(self.sample.keys()) == set(['chi', 'phi', 'eta']):
|
||||
return True
|
||||
return False
|
||||
|
||||
if len(self.sample) == 1:
|
||||
return True
|
||||
|
||||
if len(self.reference) == 1:
|
||||
return (set(self.sample.keys()) == set(['chi', 'phi']) or
|
||||
set(self.sample.keys()) == set(['mu', 'eta']) or
|
||||
self.sample == {'mu': 0, 'chi': pi / 2})
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _label_constraint(self, name):
|
||||
if name == '':
|
||||
label = ' '
|
||||
# elif self.is_tracking(name): # implies constrained
|
||||
# label = '~~> '
|
||||
elif (self.is_constrained(name) and (self.get_value(name) is None) and
|
||||
name not in valueless_constraints):
|
||||
label = 'o->'
|
||||
elif self.is_constrained(name):
|
||||
label = '-->'
|
||||
else:
|
||||
label = ' '
|
||||
return label
|
||||
|
||||
def constrain(self, name):
|
||||
if self.is_constraint_fixed(name):
|
||||
raise DiffcalcException('%s is not a valid constraint name' % name)
|
||||
if name in self.all:
|
||||
return "%s is already constrained." % name.capitalize()
|
||||
elif name in det_constraints:
|
||||
return self._constrain_detector(name)
|
||||
elif name in ref_constraints:
|
||||
return self._constrain_reference(name)
|
||||
elif name in samp_constraints:
|
||||
return self._constrain_sample(name)
|
||||
else:
|
||||
raise DiffcalcException("%s is not a valid constraint name. Type 'con' for a table of constraint name" % name)
|
||||
|
||||
def is_constraint_fixed(self, name):
|
||||
return ((name in det_constraints and self._hide_detector_constraint) or
|
||||
(name in samp_constraints and name in self._fixed_samp_constraints))
|
||||
|
||||
def _constrain_detector(self, name):
|
||||
if self.naz:
|
||||
del self._constrained['naz']
|
||||
self._constrained[name] = None
|
||||
return 'Naz constraint replaced.'
|
||||
elif self.detector:
|
||||
constrained_name = self.detector.keys()[0]
|
||||
del self._constrained[constrained_name]
|
||||
self._constrained[name] = None
|
||||
return'%s constraint replaced.' % constrained_name.capitalize()
|
||||
elif len(self.all) == 3: # and no detector
|
||||
raise self._could_not_constrain_exception(name)
|
||||
else:
|
||||
self._constrained[name] = None
|
||||
|
||||
def _could_not_constrain_exception(self, name):
|
||||
return DiffcalcException(
|
||||
"%s could not be constrained. First un-constrain one of the\n"
|
||||
"angles %s, %s or %s (with 'uncon')" %
|
||||
((name.capitalize(),) + self.constrained_names))
|
||||
|
||||
def _constrain_reference(self, name):
|
||||
if self.reference:
|
||||
constrained_name = self.reference.keys()[0]
|
||||
del self._constrained[constrained_name]
|
||||
self._constrained[name] = None
|
||||
return '%s constraint replaced.' % constrained_name.capitalize()
|
||||
elif len(self.all) == 3: # and no reference
|
||||
raise self._could_not_constrain_exception(name)
|
||||
else:
|
||||
self._constrained[name] = None
|
||||
|
||||
def _constrain_sample(self, name):
|
||||
if len(self._constrained) < 3:
|
||||
# okay, more to add
|
||||
self._constrained[name] = None
|
||||
# else: three constraints are set
|
||||
elif len(self.sample) == 1:
|
||||
# (detector and reference constraints set)
|
||||
# it is clear which sample constraint to remove
|
||||
constrained_name = self.sample.keys()[0]
|
||||
del self._constrained[constrained_name]
|
||||
self._constrained[name] = None
|
||||
return '%s constraint replaced.' % constrained_name.capitalize()
|
||||
else:
|
||||
raise self._could_not_constrain_exception(name)
|
||||
|
||||
def unconstrain(self, name):
|
||||
if self.is_constraint_fixed(name):
|
||||
raise DiffcalcException('%s is not a valid constraint name')
|
||||
if name in self._constrained:
|
||||
del self._constrained[name]
|
||||
else:
|
||||
return "%s was not already constrained." % name.capitalize()
|
||||
|
||||
def _check_constraint_settable(self, name):
|
||||
if name not in all_constraints:
|
||||
raise DiffcalcException(
|
||||
'Could not set %(name)s. This is not an available '
|
||||
'constraint.' % locals())
|
||||
elif name not in self.all.keys():
|
||||
raise DiffcalcException(
|
||||
'Could not set %(name)s. This is not currently '
|
||||
'constrained.' % locals())
|
||||
elif name in valueless_constraints:
|
||||
raise DiffcalcException(
|
||||
'Could not set %(name)s. This constraint takes no '
|
||||
'value.' % locals())
|
||||
|
||||
def clear_constraints(self):
|
||||
self._constrained = {}
|
||||
|
||||
def set_constraint(self, name, value): # @ReservedAssignment
|
||||
if self.is_constraint_fixed(name):
|
||||
raise DiffcalcException('%s is not a valid constraint name')
|
||||
self._check_constraint_settable(name)
|
||||
# if name in self._tracking:
|
||||
# raise DiffcalcException(
|
||||
# "Could not set %s as this constraint is configured to track "
|
||||
# "its associated\nphysical angle. First remove this tracking "
|
||||
# "(use 'untrack %s').""" % (name, name))
|
||||
old_value = self.get_constraint(name)
|
||||
old = str(old_value) if old_value is not None else '---'
|
||||
self._constrained[name] = float(value) * TORAD
|
||||
new = str(value)
|
||||
return "%(name)s : %(old)s --> %(new)s" % locals()
|
||||
|
||||
def get_constraint(self, name):
|
||||
value = self.all[name]
|
||||
return None if value is None else value * TODEG
|
||||
|
||||
178
script/__Lib/diffcalc_old/diffcalc/hkl/you/geometry.py
Normal file
178
script/__Lib/diffcalc_old/diffcalc/hkl/you/geometry.py
Normal file
@@ -0,0 +1,178 @@
|
||||
###
|
||||
# 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
|
||||
|
||||
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 ):
|
||||
self.name = name
|
||||
self.fixed_constraints = fixed_constraints
|
||||
|
||||
def physical_angles_to_internal_position(self, physicalAngles):
|
||||
raise NotImplementedError()
|
||||
|
||||
def internal_position_to_physical_angles(self, physicalAngles):
|
||||
raise NotImplementedError()
|
||||
|
||||
def create_position(self, *args):
|
||||
return YouPosition(*args)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
#==============================================================================
|
||||
# Geometry plugins for use with 'You' hkl calculation engine
|
||||
#==============================================================================
|
||||
#==============================================================================
|
||||
|
||||
|
||||
class SixCircle(YouGeometry):
|
||||
def __init__(self):
|
||||
YouGeometry.__init__(self, 'sixc', {})
|
||||
|
||||
def physical_angles_to_internal_position(self, physical_angle_tuple):
|
||||
# mu, delta, nu, eta, chi, phi
|
||||
return YouPosition(*physical_angle_tuple)
|
||||
|
||||
def internal_position_to_physical_angles(self, internal_position):
|
||||
return internal_position.totuple()
|
||||
|
||||
|
||||
class FourCircle(YouGeometry):
|
||||
"""For a diffractometer with angles:
|
||||
delta, eta, chi, phi
|
||||
"""
|
||||
def __init__(self):
|
||||
YouGeometry.__init__(self, 'fourc', {'mu': 0, NUNAME: 0})
|
||||
|
||||
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)
|
||||
|
||||
def internal_position_to_physical_angles(self, internal_position):
|
||||
_, delta, _, eta, chi, phi = internal_position.totuple()
|
||||
return delta, eta, chi, phi
|
||||
|
||||
|
||||
class FiveCircle(YouGeometry):
|
||||
"""For a diffractometer with angles:
|
||||
delta, nu, eta, chi, phi
|
||||
"""
|
||||
def __init__(self):
|
||||
YouGeometry.__init__(self, 'fivec', {'mu': 0})
|
||||
|
||||
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)
|
||||
|
||||
def internal_position_to_physical_angles(self, internal_position):
|
||||
_, delta, nu, eta, chi, phi = internal_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)
|
||||
|
||||
|
||||
class YouPosition(AbstractPosition):
|
||||
|
||||
def __init__(self, mu=None, delta=None, nu=None, eta=None, chi=None,
|
||||
phi=None):
|
||||
self.mu = mu
|
||||
self.delta = delta
|
||||
self.nu = nu
|
||||
self.eta = eta
|
||||
self.chi = chi
|
||||
self.phi = phi
|
||||
|
||||
def clone(self):
|
||||
return YouPosition(self.mu, self.delta, self.nu, self.eta, self.chi,
|
||||
self.phi)
|
||||
|
||||
def changeToRadians(self):
|
||||
self.mu *= TORAD
|
||||
self.delta *= TORAD
|
||||
self.nu *= TORAD
|
||||
self.eta *= TORAD
|
||||
self.chi *= TORAD
|
||||
self.phi *= TORAD
|
||||
|
||||
def changeToDegrees(self):
|
||||
self.mu *= TODEG
|
||||
self.delta *= TODEG
|
||||
self.nu *= TODEG
|
||||
self.eta *= TODEG
|
||||
self.chi *= TODEG
|
||||
self.phi *= TODEG
|
||||
|
||||
def totuple(self):
|
||||
return (self.mu, self.delta, self.nu, self.eta, self.chi, self.phi)
|
||||
|
||||
def __str__(self):
|
||||
return ("YouPosition(mu %r delta: %r nu: %r eta: %r chi: %r phi: %r)"
|
||||
% self.totuple())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.totuple() == other.totuple()
|
||||
178
script/__Lib/diffcalc_old/diffcalc/hkl/you/hkl.py
Normal file
178
script/__Lib/diffcalc_old/diffcalc/hkl/you/hkl.py
Normal file
@@ -0,0 +1,178 @@
|
||||
###
|
||||
# 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 __future__ import absolute_import
|
||||
|
||||
from diffcalc.hkl.common import getNameFromScannableOrString
|
||||
from diffcalc.util import command
|
||||
from diffcalc.hkl.you.calc import YouHklCalculator
|
||||
from diffcalc import settings
|
||||
|
||||
|
||||
|
||||
import diffcalc.ub.ub
|
||||
from diffcalc.hkl.you.constraints import YouConstraintManager
|
||||
|
||||
__all__ = ['allhkl', 'con', 'uncon', 'hklcalc', 'constraint_manager']
|
||||
|
||||
|
||||
_fixed_constraints = settings.geometry.fixed_constraints # @UndefinedVariable
|
||||
|
||||
constraint_manager = YouConstraintManager(settings.hardware, _fixed_constraints)
|
||||
|
||||
hklcalc = YouHklCalculator(
|
||||
diffcalc.ub.ub.ubcalc, settings.geometry, settings.hardware, constraint_manager)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return hklcalc.__str__()
|
||||
|
||||
@command
|
||||
def con(*args):
|
||||
"""
|
||||
con -- list available constraints and values
|
||||
con <name> {val} -- constrains and optionally sets one constraint
|
||||
con <name> {val} <name> {val} <name> {val} -- clears and then fully constrains
|
||||
|
||||
Select three constraints using 'con' and 'uncon'. Choose up to one
|
||||
from each of the sample and detector columns and up to three from
|
||||
the sample column.
|
||||
|
||||
Not all constraint combinations are currently available:
|
||||
|
||||
1 x samp: all 80 of 80
|
||||
2 x samp and 1 x ref: chi & phi
|
||||
mu & eta
|
||||
chi=90 & mu=0 (2.5 of 6)
|
||||
2 x samp and 1 x det: 0 of 6
|
||||
3 x samp: eta, chi & phi (1 of 4)
|
||||
|
||||
See also 'uncon'
|
||||
"""
|
||||
args = list(args)
|
||||
msg = _handle_con(args)
|
||||
if (hklcalc.constraints.is_fully_constrained() and
|
||||
not hklcalc.constraints.is_current_mode_implemented()):
|
||||
msg += ("\n\nWARNING:. The selected constraint combination is valid but "
|
||||
"is not implemented.\n\nType 'help con' to see implemented combinations")
|
||||
|
||||
if msg:
|
||||
print msg
|
||||
|
||||
def _handle_con(args):
|
||||
if not args:
|
||||
return hklcalc.constraints.__str__()
|
||||
|
||||
if len(args) > 6:
|
||||
raise TypeError("Unexpected args: " + str(args))
|
||||
|
||||
cons_value_pairs = []
|
||||
while args:
|
||||
scn_or_str = args.pop(0)
|
||||
name = getNameFromScannableOrString(scn_or_str)
|
||||
if args and isinstance(args[0], (int, long, float)):
|
||||
value = args.pop(0)
|
||||
else:
|
||||
value = None
|
||||
cons_value_pairs.append((name, value))
|
||||
|
||||
if len(cons_value_pairs) == 1:
|
||||
pass
|
||||
elif len(cons_value_pairs) == 3:
|
||||
hklcalc.constraints.clear_constraints()
|
||||
else:
|
||||
raise TypeError("Either one or three constraints must be specified")
|
||||
for name, value in cons_value_pairs:
|
||||
hklcalc.constraints.constrain(name)
|
||||
if value is not None:
|
||||
hklcalc.constraints.set_constraint(name, value)
|
||||
return '\n'.join(hklcalc.constraints.report_constraints_lines())
|
||||
|
||||
|
||||
@command
|
||||
def uncon(scn_or_string):
|
||||
"""uncon <name> -- remove constraint
|
||||
|
||||
See also 'con'
|
||||
"""
|
||||
name = getNameFromScannableOrString(scn_or_string)
|
||||
hklcalc.constraints.unconstrain(name)
|
||||
print '\n'.join(hklcalc.constraints.report_constraints_lines())
|
||||
|
||||
@command
|
||||
def allhkl(hkl, wavelength=None):
|
||||
"""allhkl [h k l] -- print all hkl solutions ignoring limits
|
||||
|
||||
"""
|
||||
hardware = hklcalc._hardware
|
||||
geometry = hklcalc._geometry
|
||||
if wavelength is None:
|
||||
wavelength = hardware.get_wavelength()
|
||||
h, k, l = hkl
|
||||
pos_virtual_angles_pairs = hklcalc.hkl_to_all_angles(
|
||||
h, k, l, wavelength)
|
||||
cells = []
|
||||
# virtual_angle_names = list(pos_virtual_angles_pairs[0][1].keys())
|
||||
# virtual_angle_names.sort()
|
||||
virtual_angle_names = ['qaz', 'psi', 'naz', 'tau', 'theta', 'alpha', 'beta']
|
||||
header_cells = list(hardware.get_axes_names()) + [' '] + virtual_angle_names
|
||||
cells.append(['%9s' % s for s in header_cells])
|
||||
cells.append([''] * len(header_cells))
|
||||
|
||||
|
||||
for pos, virtual_angles in pos_virtual_angles_pairs:
|
||||
row_cells = []
|
||||
|
||||
|
||||
angle_tuple = geometry.internal_position_to_physical_angles(pos)
|
||||
angle_tuple = hardware.cut_angles(angle_tuple)
|
||||
for val in angle_tuple:
|
||||
row_cells.append('%9.4f' % val)
|
||||
|
||||
row_cells.append('|')
|
||||
|
||||
for name in virtual_angle_names:
|
||||
row_cells.append('%9.4f' % virtual_angles[name])
|
||||
cells.append(row_cells)
|
||||
|
||||
|
||||
column_widths = []
|
||||
for col in range(len(cells[0])):
|
||||
widths = []
|
||||
for row in range(len(cells)):
|
||||
cell = cells[row][col]
|
||||
width = len(cell.strip())
|
||||
widths.append(width)
|
||||
column_widths.append(max(widths))
|
||||
|
||||
lines = []
|
||||
for row_cells in cells:
|
||||
trimmed_row_cells = []
|
||||
for cell, width in zip(row_cells, column_widths):
|
||||
trimmed_cell = cell.strip().rjust(width)
|
||||
trimmed_row_cells.append(trimmed_cell)
|
||||
lines.append(' '.join(trimmed_row_cells))
|
||||
print '\n'.join(lines)
|
||||
|
||||
|
||||
commands_for_help = ['Constraints',
|
||||
con,
|
||||
uncon,
|
||||
'Hkl',
|
||||
allhkl
|
||||
]
|
||||
Reference in New Issue
Block a user