This commit is contained in:
2019-03-20 13:52:00 +01:00
parent 3084fe0510
commit 5db0f78aee
910 changed files with 191152 additions and 322 deletions

View File

@@ -0,0 +1,253 @@
###
# 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/>.
###
import random
import unittest
from math import pi
from mock import Mock
from test.tools import mneq_
import pytest
try:
from numpy import matrix
from numpy.linalg import norm
except ImportError:
from numjy import matrix
from numjy.linalg import norm
from diffcalc.hkl.vlieg.calc import VliegHklCalculator, \
_findOmegaAndChiToRotateHchiIntoQalpha, check
from diffcalc.hkl.vlieg.geometry import createVliegMatrices
from diffcalc.util import DiffcalcException
from test.diffcalc import scenarios
TORAD = pi / 180
TODEG = 180 / pi
def createMockUbcalc(UB):
ubcalc = Mock()
ubcalc.tau = 0
ubcalc.sigma = 0
ubcalc.UB = UB
ubcalc.n_phi = matrix([[0], [0], [1]])
return ubcalc
def createMockHardwareMonitor():
hardware = Mock()
hardware.get_position.return_value = (0.0, 0.0, 0.0)
hardware.get_axes_names.return_value = 'madeup', 'alpha', 'gamma'
return hardware
def createMockDiffractometerGeometry():
geometry = Mock()
geometry.parameter_fixed.return_value = False
geometry.supports_mode_group.return_value = True
geometry.fixed_parameters = {}
geometry.name = 'mock'
geometry.gamma_location = 'arm'
return geometry
class TestVliegCoreMathBits(object):
def setup_method(self):
self.many = [-91, -90, -89, -46, -45, -44, -1,
0, 1, 44, 45, 46, 89, 90, 91]
self.many = (self.many +
map(lambda x: x + 180, self.many) +
map(lambda x: x - 180, self.many))
def test_check(self):
check(True, 'Should not throw')
with pytest.raises(Exception):
check(False, 'string')
with pytest.raises(DiffcalcException):
check(False, DiffcalcException('dce'))
def acallable(toPrint=None):
if toPrint is None:
print "Not throwing exception"
else:
print toPrint
check(False, acallable)
check(False, acallable, 'this should be printed')
# TODO: Removed 2017-03-06, deprecated started code failing -- RobW.
def SKIP__findOmegaAndChiToRotateHchiIntoQalpha_WithIntegerValues(self):
for omega in self.many:
for chi in self.many:
print str(omega), ",", str(chi)
self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)
def SKIP_findOmegaAndChiToRotateHchiIntoQalpha_WithRandomValues(self):
for _ in range(10):
for omega in self.many:
for chi in self.many:
omega = omega + random.uniform(-.001, .001)
chi = chi + random.uniform(-.001, .001)
self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)
#print str(omega), ",", str(chi)
def test__findOmegaAndChiToRotateHchiIntoQalpha_WithTrickyOnes(self):
tricky_ones = [(-45., -180.), (45., -180.), (135., -180.), (2000, 0.),
(225., 0.), (225., -180.), (-225., 0.), (-225., 0.),
(-225., -180.), (-135., -180.), (89.998894, -44.999218)]
for omega, chi in tricky_ones:
self.try__findOmegaAndChiToRotateHchiIntoQalpha(omega, chi)
def try__findOmegaAndChiToRotateHchiIntoQalpha(self, omega, chi):
h_chi = matrix([[1], [1], [1]])
h_chi = h_chi * (1 / norm(h_chi))
[_, _, _, OMEGA, CHI, _] = createVliegMatrices(
None, None, None, omega * TORAD, chi * TORAD, None)
q_alpha = OMEGA * CHI * h_chi
try:
omega_calc, chi_calc = _findOmegaAndChiToRotateHchiIntoQalpha(
h_chi, q_alpha)
except ValueError, e:
raise ValueError(str(e) + "\n, resulting from test where omega:%f"
" chi%f" % (self.omega, self.chi))
[_, _, _, OMEGA, CHI, _] = createVliegMatrices(
None, None, None, omega_calc, chi_calc, None)
self.assertArraysNearlyEqual(OMEGA * CHI * h_chi, q_alpha, .000001,
"omega: %f chi:%f" % (omega, chi))
def assertArraysNearlyEqual(self, first, second, tolerance,
contextString=''):
"""
Fail if the norm of the difference between two arrays is greater than
the given tolerance.
"""
diff = first - second
if norm(diff) >= tolerance:
raise self.failureException(
'\n%r !=\n %r\ncontext: %s' %
(first.tolist(), second.tolist(), contextString))
class BaseTestHklCalculator():
def setSessionAndCalculation(self):
raise Exception("Abstract")
def setup_method(self):
self.ac = VliegHklCalculator(None, createMockDiffractometerGeometry(),
createMockHardwareMonitor())
self.ac.raiseExceptionsIfAnglesDoNotMapBackToHkl = True
self.setSessionAndCalculation()
def testAnglesToHkl(self):
mockUbcalc = createMockUbcalc(
matrix(self.sess.umatrix) * matrix(self.sess.bmatrix))
self.ac = VliegHklCalculator(mockUbcalc,
createMockDiffractometerGeometry(),
createMockHardwareMonitor())
self.ac.raiseExceptionsIfAnglesDoNotMapBackToHkl = True
# Check the two given reflections
(hklactual1, params) = self.ac.anglesToHkl(self.sess.ref1.pos,
self.sess.ref1.wavelength)
del params
(hklactual2, params) = self.ac.anglesToHkl(self.sess.ref2.pos,
self.sess.ref2.wavelength)
mneq_(matrix([hklactual1]), matrix([self.sess.ref1calchkl]), 3)
mneq_(matrix([hklactual2]), matrix([self.sess.ref2calchkl]), 3)
# ... znd in each calculation through the hkl/posiiont pairs
if self.calc:
for hkl, pos, param in zip(self.calc.hklList,
self.calc.posList,
self.calc.paramList):
(hkl_actual, params) = self.ac.anglesToHkl(pos,
self.calc.wavelength)
note = ("wrong hkl calcualted for scenario.name=%s, "
"calculation.tag=%s\n expected hkl=(%f,%f,%f)\n"
"calculated hkl=(%f,%f,%f)" %
(self.sess.name, self.calc.tag, hkl[0], hkl[1], hkl[2],
hkl_actual[0], hkl_actual[1], hkl_actual[2]))
mneq_(matrix([hkl_actual]), matrix([hkl]), 3, note=note)
print "***anglesToHkl***"
print "*** ", str(hkl), " ***"
print params
print param
def testHklToAngles(self):
if self.calc:
# Configure the angle calculator for this session scenario
UB = matrix(self.sess.umatrix) * matrix(self.sess.bmatrix)
mockUbcalc = createMockUbcalc(UB)
hw = createMockHardwareMonitor()
ac = VliegHklCalculator(mockUbcalc,
createMockDiffractometerGeometry(), hw)
ac.raiseExceptionsIfAnglesDoNotMapBackToHkl = True
## configure the angle calculator for this calculation
ac.mode_selector.setModeByName(self.calc.modeToTest)
# Set fixed parameters
if self.calc.modeToTest in ('4cBeq', '4cFixedw'):
#ac.setParameter('alpha', self.calc.alpha )
ac.parameter_manager.setTrackParameter('alpha', True)
hw.get_position.return_value = 888, self.calc.alpha, 999
ac.parameter_manager.set_constraint('gamma', self.calc.gamma)
# Test each hkl/position pair
for idx in range(len(self.calc.hklList)):
hkl = self.calc.hklList[idx]
expectedpos = self.calc.posList[idx]
(pos, params) = ac.hklToAngles(hkl[0], hkl[1], hkl[2],
self.calc.wavelength)
note = ("wrong positions calculated for TestScenario=%s, "
"AngleTestScenario=%s, hkl=(%f,%f,%f):\n"
" expected pos=%s;\n"
" returned pos=%s " %
(self.sess.name, self.calc.tag, hkl[0], hkl[1], hkl[2],
str(expectedpos), str(pos)))
assert pos.nearlyEquals(expectedpos, 0.01), note
print "*** hklToAngles ***"
print "*** ", str(hkl), " ***"
print params
try:
print self.calc.paramList[idx]
except IndexError: # Not always specified
pass
class TestVliegHklCalculatorSess1NoCalc(BaseTestHklCalculator):
def setSessionAndCalculation(self):
self.sess = scenarios.sessions()[0]
self.calc = None
class TestVliegHklCalculatorSess2Calc0(BaseTestHklCalculator):
def setSessionAndCalculation(self):
self.sess = scenarios.sessions()[1]
self.calc = self.sess.calculations[0]
class TestVliegHklCalculatorSess3Calc0(
BaseTestHklCalculator):
def setSessionAndCalculation(self):
self.sess = scenarios.sessions()[2]
self.calc = self.sess.calculations[0]

View File

@@ -0,0 +1,92 @@
###
# 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/>.
###
import unittest
from diffcalc.hkl.vlieg.constraints import ModeSelector, VliegParameterManager
from diffcalc.util import DiffcalcException
from test.diffcalc.hkl.vlieg.test_calc import \
createMockHardwareMonitor, createMockDiffractometerGeometry
import pytest
class TestModeSelector(object):
def setup_method(self):
self.ms = ModeSelector(createMockDiffractometerGeometry(),
parameterManager=None)
self.pm = VliegParameterManager(createMockDiffractometerGeometry(),
None, self.ms)
self.ms.setParameterManager(self.pm)
def testSetModeByIndex(self):
self.ms.setModeByIndex(0)
assert self.ms.getMode().name == '4cFixedw'
self.ms.setModeByIndex(1)
assert self.ms.getMode().name == '4cBeq'
def testGetMode(self):
# tested implicetely by testSetmode
pass
def testShowAvailableModes(self):
print self.ms.reportAvailableModes()
class TestParameterManager(object):
def setup_method(self):
self.hw = createMockHardwareMonitor()
self.ms = ModeSelector(createMockDiffractometerGeometry())
self.pm = VliegParameterManager(createMockDiffractometerGeometry(),
self.hw, self.ms)
def testDefaultParameterValues(self):
assert self.pm.get_constraint('alpha') == 0
assert self.pm.get_constraint('gamma') == 0
with pytest.raises(DiffcalcException):
self.pm.get_constraint('not-a-parameter-name')
def testSetParameter(self):
self.pm.set_constraint('alpha', 10.1)
assert self.pm.get_constraint('alpha') == 10.1
def testSetTrackParameter_isParameterChecked(self):
assert not self.pm.isParameterTracked('alpha')
self.pm.set_constraint('alpha', 9)
self.pm.setTrackParameter('alpha', True)
assert self.pm.isParameterTracked('alpha') == True
with pytest.raises(DiffcalcException):
self.pm.set_constraint('alpha', 10)
self.hw.get_position.return_value = 888, 11, 999
assert self.pm.get_constraint('alpha') == 11
print self.pm.reportAllParameters()
print "**"
print self.ms.reportCurrentMode()
print self.pm.reportParametersUsedInCurrentMode()
self.pm.setTrackParameter('alpha', False)
assert not self.pm.isParameterTracked('alpha')
assert self.pm.get_constraint('alpha') == 11
self.hw.get_position.return_value = 888, 12, 999
assert self.pm.get_constraint('alpha') == 11
self.pm.set_constraint('alpha', 13)
assert self.pm.get_constraint('alpha') == 13

View File

@@ -0,0 +1,248 @@
###
# 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/>.
###
import random
import unittest
from math import pi
try:
from numpy import matrix
from numpy.linalg import norm
except ImportError:
from numjy import matrix
from numjy.linalg import norm
from test.tools import mneq_
from diffcalc.hkl.vlieg.geometry import SixCircleGammaOnArmGeometry, \
gammaOnArmToBase, gammaOnBaseToArm, SixCircleGeometry, Fivec, Fourc
from diffcalc.hkl.vlieg.geometry import createVliegMatrices
from diffcalc.hkl.vlieg.geometry import VliegPosition
from diffcalc.util import nearlyEqual, radiansEquivilant as radeq
random.seed() # uses time
TORAD = pi / 180
TODEG = 180 / pi
class TestSixCirclePlugin(object):
def setup_method(self):
self.geometry = SixCircleGeometry()
def testGetName(self):
assert self.geometry.name == "sixc"
def testPhysicalAnglesToInternalPosition(self):
pos = [0, 0, 0, 0, 0, 0]
expected = self.geometry.physical_angles_to_internal_position(pos)
assert VliegPosition(*pos) == expected
def testInternalPositionToPhysicalAngles(self):
pos = VliegPosition(0, 0, 0, 0, 0, 0)
result = self.geometry.internal_position_to_physical_angles(pos)
assert norm(matrix([pos.totuple()]) - matrix([result])) < 0.001
def testGammaOn(self):
assert self.geometry.gamma_location == 'base'
def testSupportsModeGroup(self):
assert self.geometry.supports_mode_group('fourc')
assert not self.geometry.supports_mode_group('made up mode')
def testGetFixedParameters(self):
self.geometry.fixed_parameters # check for exceptions
def isParamaterUnchangable(self):
assert not self.geometry.isParamaterUnchangable('made up parameter')
class TestSixCircleGammaOnArmGeometry(object):
def setup_method(self):
self.geometry = SixCircleGammaOnArmGeometry()
def testGetName(self):
assert self.geometry.name == "sixc_gamma_on_arm"
def testPhysicalAnglesToInternalPosition(self):
pos = [1, 2, 3, 4, 5, 6]
expected = self.geometry.physical_angles_to_internal_position(pos)
assert VliegPosition(*pos) == expected
def testInternalPositionToPhysicalAngles(self):
pos = VliegPosition(1, 2, 3, 4, 5, 6)
result = self.geometry.internal_position_to_physical_angles(pos)
mneq_(matrix([pos.totuple()]), matrix([result]), 4)
def testSupportsModeGroup(self):
assert self.geometry.supports_mode_group('fourc')
assert not self.geometry.supports_mode_group('made up mode')
def testGetFixedParameters(self):
self.geometry.fixed_parameters # check for exceptions
def isParamaterUnchangable(self):
assert not self.geometry.isParamaterUnchangable('made up parameter')
y_vector = matrix([[0], [1], [0]])
TOLERANCE = 1e-5
def armAnglesToLabVector(alpha, delta, gamma):
[ALPHA, DELTA, GAMMA, _, _, _] = createVliegMatrices(
alpha, delta, gamma, None, None, None)
return ALPHA * DELTA * GAMMA * y_vector
def baseAnglesToLabVector(delta, gamma):
[_, DELTA, GAMMA, _, _, _] = createVliegMatrices(
None, delta, gamma, None, None, None)
return GAMMA * DELTA * y_vector
def checkGammaOnArmToBase(alpha, deltaA, gammaA):
deltaB, gammaB = gammaOnArmToBase(deltaA, gammaA, alpha)
labA = armAnglesToLabVector(alpha, deltaA, gammaA)
labB = baseAnglesToLabVector(deltaB, gammaB)
if not nearlyEqual(labA, labB, TOLERANCE):
strLabA = ("[%f, %f, %f]" %
(labA.get(0, 0), labA.get(1, 0), labA.get(2, 0)))
strLabB = ("[%f, %f, %f]" %
(labB.get(0, 0), labB.get(1, 0), labB.get(2, 0)))
rep = ("alpha=%f, delta=%f, gamma=%f" %
(alpha * TODEG, deltaB * TODEG, gammaB * TODEG))
raise AssertionError('\nArm-->Base ' + rep + '\n' +
"arm (delta, gamma) = (%f,%f) <==>\t labA = %s\n" %
(deltaA * TODEG, gammaA * TODEG, strLabA) +
"base(delta, gamma) = (%f,%f) <==>\t labB = %s\n" %
(deltaB * TODEG, gammaB * TODEG, strLabB))
def checkBaseArmBaseReciprocity(alpha, delta_orig, gamma_orig):
(deltaB, gammaB) = (delta_orig, gamma_orig)
(deltaA, gammaA) = gammaOnBaseToArm(deltaB, gammaB, alpha)
(deltaB, gammaB) = gammaOnArmToBase(deltaA, gammaA, alpha)
if ((not radeq(deltaB, delta_orig, TOLERANCE)) or
(not radeq(gammaB, gamma_orig, TOLERANCE))):
s = "\nBase-Arm-Base reciprocity\n"
s += 'alpha=%f\n' % (alpha * TODEG,)
s += (' (deltaB, gammaB) = (%f, %f)\n' %
(delta_orig * TODEG, gamma_orig * TODEG))
s += (' ->(deltaA, gammaA) = (%f, %f)\n' %
(deltaA * TODEG, gammaA * TODEG))
s += (' ->(deltaB, gammaB) = (%f, %f)\n' %
(deltaB * TODEG, gammaB * TODEG))
raise AssertionError(s)
def checkArmBaseArmReciprocity(alpha, delta_orig, gamma_orig):
(deltaA, gammaA) = (delta_orig, gamma_orig)
(deltaB, gammaB) = gammaOnArmToBase(deltaA, gammaA, alpha)
(deltaA, gammaA) = gammaOnBaseToArm(deltaB, gammaB, alpha)
if ((not radeq(deltaA, delta_orig, TOLERANCE)) or
(not radeq(gammaA, gamma_orig, TOLERANCE))):
s = "\nArm-Base-Arm reciprocity\n"
s += "alpha=%f\n" % (alpha * TODEG,)
s += (" (deltaA, gammaA) = (%f, %f)\n" %
(delta_orig * TODEG, gamma_orig * TODEG))
s += (" ->(deltaB, gammaB) = (%f, %f)\n" %
(deltaB * TODEG, gammaB * TODEG))
s += (" ->(deltaA, gammaA) = (%f, %f)\n" %
(deltaA * TODEG, gammaA * TODEG))
raise AssertionError(s)
def test_generator_for_cases():
for alpha in [-89.9, -45, -1, 0, 1, 45, 89.9]:
for gamma in [-89.9, -46, -45, -44, -1, 0, 1, 44, 45, 46, 89.9]:
for delta in [-179.9, -135, -91, -89.9, -89, -46, -45, -44, -1, 0,
1, 44, 45, 46, 89, 89.9, 91, 135, 179.9]:
yield (checkGammaOnArmToBase, alpha * TORAD, delta * TORAD,
gamma * TORAD)
yield (checkArmBaseArmReciprocity, alpha * TORAD,
delta * TORAD, gamma * TORAD)
class TestFiveCirclePlugin(object):
def setup_method(self):
self.geometry = Fivec()
def testGetName(self):
assert self.geometry.name == "fivec"
def testPhysicalAnglesToInternalPosition(self):
expected = self.geometry.physical_angles_to_internal_position(
(1, 2, 4, 5, 6))
assert VliegPosition(1, 2, 0, 4, 5, 6) == expected
def testInternalPositionToPhysicalAngles(self):
result = self.geometry.internal_position_to_physical_angles(
VliegPosition(1, 2, 0, 4, 5, 6))
assert (norm(matrix([[1, 2, 4, 5, 6]]) - (matrix([list(result)])))
< 0.001)
def testSupportsModeGroup(self):
assert self.geometry.supports_mode_group('fourc')
assert not self.geometry.supports_mode_group('fivecFixedAlpha')
assert self.geometry.supports_mode_group('fivecFixedGamma')
def testGetFixedParameters(self):
self.geometry.fixed_parameters # check for exceptions
def testisParamaterFixed(self):
assert not self.geometry.parameter_fixed('made up parameter')
assert self.geometry.parameter_fixed('gamma')
class TestFourCirclePlugin(object):
def setup_method(self):
self.geometry = Fourc()
def testGetName(self):
assert self.geometry.name == "fourc"
def testPhysicalAnglesToInternalPosition(self):
expected = self.geometry.physical_angles_to_internal_position((2, 4, 5, 6))
assert VliegPosition(0, 2, 0, 4, 5, 6) == expected
def testInternalPositionToPhysicalAngles(self):
result = self.geometry.internal_position_to_physical_angles(
VliegPosition(0, 2, 0, 4, 5, 6))
assert (norm(matrix([[2, 4, 5, 6]]) - matrix([list(result)]))
< 0.001)
def testSupportsModeGroup(self):
assert self.geometry.supports_mode_group('fourc')
assert not self.geometry.supports_mode_group('fivecFixedAlpha')
assert not self.geometry.supports_mode_group('fivecFixedGamma')
def testGetFixedParameters(self):
self.geometry.fixed_parameters # check for exceptions
def testisParamaterFixed(self):
assert not self.geometry.parameter_fixed('made up parameter')
assert self.geometry.parameter_fixed('gamma')
assert self.geometry.parameter_fixed('alpha')

View File

@@ -0,0 +1,84 @@
###
# 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/>.
###
import unittest
from mock import Mock
import diffcalc.util # @UnusedImport to overide raw_input
from diffcalc.hkl.vlieg.geometry import SixCircleGammaOnArmGeometry
from diffcalc.hardware import DummyHardwareAdapter
from diffcalc.util import MockRawInput
from diffcalc.hkl.vlieg.calc import VliegHklCalculator
from diffcalc.ub.calc import UBCalculation
from diffcalc.ub.persistence import UbCalculationNonPersister
import pytest
try:
from gdascripts.pd.dummy_pds import DummyPD # @UnusedImport
except ImportError:
from diffcalc.gdasupport.minigda.scannable import DummyPD
def prepareRawInput(listOfStrings):
diffcalc.util.raw_input = MockRawInput(listOfStrings)
prepareRawInput([])
class TestHklCommands(object):
def setup_method(self):
self.geometry = SixCircleGammaOnArmGeometry()
dummy = 'alpha', 'delta', 'gamma', 'omega', 'chi', 'phi'
self.hardware = DummyHardwareAdapter(dummy)
self.mock_ubcalc = Mock(spec=UBCalculation)
self.hklcalc = VliegHklCalculator(self.mock_ubcalc, self.geometry,
self.hardware, True)
from diffcalc import settings
settings.hardware = self.hardware
settings.geometry = self.geometry
settings.ubcalc_persister = UbCalculationNonPersister()
from diffcalc.hkl.vlieg import hkl
reload(hkl)
hkl.hklcalc = self.hklcalc
self.hkl = hkl
prepareRawInput([])
def testHklmode(self):
with pytest.raises(TypeError):
self.hkl.hklmode(1, 2)
with pytest.raises(ValueError):
self.hkl.hklmode('unwanted_string')
print self.hkl.hklmode()
print self.hkl.hklmode(1)
def testSetWithString(self):
self.hkl.setpar()
self.hkl.setpar('alpha')
self.hkl.setpar('alpha', 1)
self.hkl.setpar('alpha', 1.1)
pm = self.hkl.hklcalc.parameter_manager
assert pm.get_constraint('alpha') == 1.1
def testSetWithScannable(self):
alpha = DummyPD('alpha')
self.hkl.setpar(alpha, 1.1)
pm = self.hkl.hklcalc.parameter_manager
assert pm.get_constraint('alpha') == 1.1

View File

@@ -0,0 +1,463 @@
###
# 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 nose.tools import eq_
import unittest
from mock import Mock
from diffcalc.hkl.vlieg.geometry import SixCircleGammaOnArmGeometry
from diffcalc.hardware import DummyHardwareAdapter
from diffcalc.hkl.vlieg.geometry import VliegPosition as P, \
VliegPosition as Pos
from diffcalc.hkl.vlieg.transform import TransformA, TransformB, TransformC, \
transformsFromSector, TransformCommands, \
VliegTransformSelector, VliegPositionTransformer
import diffcalc.util # @UnusedImport
import pytest
class TestVliegPositionTransformer(object):
def setup_method(self):
names = 'a', 'd', 'g', 'o', 'c', 'phi'
self.hardware = DummyHardwareAdapter(names)
self.geometry = SixCircleGammaOnArmGeometry()
self.transform_selector = VliegTransformSelector()
self.transformer = VliegPositionTransformer(
self.geometry, self.hardware, self.transform_selector)
self.transform_commands = TransformCommands(self.transform_selector)
diffcalc.util.RAISE_EXCEPTIONS_FOR_ALL_ERRORS = True
def map(self, pos): # @ReservedAssignment
pos = self.transformer.transform(pos)
angle_tuple = self.geometry.internal_position_to_physical_angles(pos)
angle_tuple = self.hardware.cut_angles(angle_tuple)
return angle_tuple
def testMapDefaultSector(self):
eq_(self.map(Pos(1, 2, 3, 4, 5, 6)),
(1, 2, 3, 4, 5, 6))
eq_(self.map(Pos(-180, -179, 0, 179, 180, 359)),
(-180, -179, 0, 179, 180, 359))
eq_(self.map(Pos(0, 0, 0, 0, 0, 0)),
(0, 0, 0, 0, 0, 0))
eq_(self.map(Pos(-270, 270, 0, 0, 0, -90)),
(90, -90, 0, 0, 0, 270))
def testMapSector1(self):
self.transform_commands._sectorSelector.setSector(1)
eq_(self.map(Pos(1, 2, 3, 4, 5, 6)),
(1, 2, 3, 4 - 180, -5, (6 - 180) + 360))
eq_(self.map(Pos(-180, -179, 0, 179, 180, 359)),
(-180, -179, 0, 179 - 180, -180, 359 - 180))
eq_(self.map(Pos(0, 0, 0, 0, 0, 0)),
(0, 0, 0, 0 - 180, 0, (0 - 180) + 360))
eq_(self.map(Pos(-270, 270, 0, 0, 0, -90)),
(90, -90, 0, 0 - 180, 0, 270 - 180))
def testMapAutoSector(self):
self.transform_commands._sectorSelector.addAutoTransorm(1)
self.hardware.set_lower_limit('c', 0)
eq_(self.map(Pos(1, 2, 3, 4, -5, 6)),
(1, 2, 3, 4 - 180, 5, (6 - 180) + 360))
eq_(self.map(Pos(-180, -179, 0, 179, -180, 359)),
(-180, -179, 0, 179 - 180, 180, 359 - 180))
eq_(self.map(Pos(0, 0, 0, 0, -5, 0)),
(0, 0, 0, 0 - 180, 5, (0 - 180) + 360))
eq_(self.map(Pos(-270, 270, 0, 0, -5, -90)),
(90, -90, 0, 0 - 180, 5, 270 - 180))
def testTransform(self):
# mapper
self.transform_commands.transform() # should print its state
with pytest.raises(TypeError):
self.transform_commands.transform(1)
with pytest.raises(TypeError):
self.transform_commands.transform('a', 1)
def testTransformsOnOff(self):
# transforma [on/off/auto/manual]
ss = self.transform_commands._sectorSelector
self.transform_commands.transforma() # should print mapper state
eq_(ss.transforms, [], "test assumes transforms are off to start")
self.transform_commands.transforma('on')
eq_(ss.transforms, ['a'])
self.transform_commands.transformb('on')
eq_(ss.transforms, ['a', 'b'])
self.transform_commands.transformc('off')
eq_(ss.transforms, ['a', 'b'])
self.transform_commands.transformb('off')
eq_(ss.transforms, ['a'])
def testTransformsAuto(self):
ss = self.transform_commands._sectorSelector
eq_(ss.autotransforms, [], "test assumes transforms are off to start")
self.transform_commands.transforma('auto')
eq_(ss.autotransforms, ['a'])
self.transform_commands.transformb('auto')
eq_(ss.autotransforms, ['a', 'b'])
self.transform_commands.transformc('manual')
eq_(ss.autotransforms, ['a', 'b'])
self.transform_commands.transformb('manual')
eq_(ss.autotransforms, ['a'])
def testTransformsBadInput(self):
transforma = self.transform_commands.transforma
with pytest.raises(TypeError):
transforma(1)
with pytest.raises(TypeError):
transforma('not_valid')
with pytest.raises(TypeError):
transforma('auto', 1)
def testSector(self):
#sector [0-7]
ss = self.transform_commands._sectorSelector
self.transform_commands.sector() # should print mapper state
eq_(ss.sector, 0, "test assumes sector is 0 to start")
self.transform_commands.sector(1)
eq_(ss.sector, 1)
with pytest.raises(TypeError):
self.transform_commands.sector(1, 2)
with pytest.raises(TypeError):
self.transform_commands.sector('a')
def testAutosectors(self):
#autosector [0-7]
ss = self.transform_selector
self.transform_commands.autosector() # should print mapper state
eq_(ss.autosectors, [], "test assumes no auto sectors to start")
self.transform_commands.autosector(1)
eq_(ss.autosectors, [1])
self.transform_commands.autosector(1, 2)
eq_(ss.autosectors, [1, 2])
self.transform_commands.autosector(1)
eq_(ss.autosectors, [1])
self.transform_commands.autosector(3)
eq_(ss.autosectors, [3])
with pytest.raises(TypeError):
self.transform_commands.autosector(1, 'a')
with pytest.raises(TypeError):
self.transform_commands.autosector('a')
class MockLimitChecker(object):
def __init__(self):
self.okay = True
def isPoswithiLimits(self, pos):
return self.okay
def isDeltaNegative(self, pos):
return pos.delta <= 0
class TestVliegTransformSelector(object):
def setup_method(self):
self.limitChecker = MockLimitChecker()
self.ss = VliegTransformSelector()
self.ss.limitCheckerFunction = self.limitChecker.isPoswithiLimits
def test__init__(self):
assert (self.ss.sector, 0)
def testCutPosition(self):
d = .1
tocut = P(-180., 180., 180. - d, 180. + d, -180. + d, -180. - d)
expected = P(-180., 180., 180. - d, -180. + d, -180. + d, 180. - d)
assert (self.ss.cutPosition(tocut) == expected)
def testTransformNWithoutCut(self):
pos = P(1, 2, 3, 4, 5, 6)
assert (self.ss.transformNWithoutCut(0, pos) == pos)
def testTransformPosition(self):
pos = P(0 - 360, .1 + 360, .2 - 360, .3 + 360, .4, 5)
res = self.ss.transformPosition(pos)
des = P(0, .1, .2, .3, .4, 5)
assert (res == des, '%s!=\n%s' % (res, des))
def testSetSector(self):
self.ss.setSector(4)
assert (self.ss.sector, 4)
assert (self.ss.transforms, ['b', 'c'])
def testSetTransforms(self):
self.ss.setTransforms(('c', 'b'))
assert (self.ss.sector, 4)
assert (self.ss.transforms, ['b', 'c'])
def testAddAutoTransormWithBadInput(self):
assert (self.ss.autosectors, [])
assert (self.ss.autotransforms, [])
with pytest.raises(ValueError):
self.ss.addAutoTransorm('not transform')
with pytest.raises(ValueError):
self.ss.addAutoTransorm(9999)
with pytest.raises(ValueError):
self.ss.addAutoTransorm([])
def testAddAutoTransormWithTransforms(self):
self.ss.autosectors = [1, 2, 3, 4, 5]
self.ss.addAutoTransorm('a')
print "Should now print a warning..."
self.ss.addAutoTransorm('a') # twice
self.ss.addAutoTransorm('b')
assert (self.ss.autosectors, [])
assert (self.ss.autotransforms, ['a', 'b'])
def testAddAutoTransormWithSectors(self):
self.ss.autotransforms = ['a', 'c']
self.ss.addAutoTransorm(2)
print "Should now print a warning..."
self.ss.addAutoTransorm(2) # twice
self.ss.addAutoTransorm(3)
assert (self.ss.autosectors, [2, 3])
assert (self.ss.autotransforms, [])
def testis_position_within_limits(self):
assert (self.ss.is_position_within_limits(None), True)
self.limitChecker.okay = False
assert (self.ss.is_position_within_limits(None), False)
def test__repr__(self):
self.ss.setSector(0)
print "************************"
print self.ss
print "************************"
self.ss.setTransforms('a')
print self.ss
print "************************"
self.ss.setTransforms(('a', 'b', 'c'))
print self.ss
print "************************"
class TestSectorSelectorAutoCode(object):
def setup_method(self):
self.limitChecker = MockLimitChecker()
self.ss = VliegTransformSelector()
self.ss.limitCheckerFunction = self.limitChecker.isDeltaNegative
self.pos = P(0, .1, .2, .3, .4, 5)
self.pos_in2 = self.ss.cutPosition(
self.ss.transformNWithoutCut(2, self.pos))
self.pos_in3 = self.ss.cutPosition(
self.ss.transformNWithoutCut(3, self.pos))
def testAddautoTransformWithSectors(self):
self.ss.addAutoTransorm(2)
self.ss.addAutoTransorm(3)
assert (self.ss.autosectors, [2, 3])
assert (self.ss.autotransforms, [])
self.ss.removeAutoTransform(3)
assert (self.ss.autosectors, [2])
def testAddautoTransformTransforms(self):
self.ss.addAutoTransorm('a')
self.ss.addAutoTransorm('b')
assert (self.ss.autosectors, [])
assert (self.ss.autotransforms, ['a', 'b'])
def testRemoveAutoTransformWithSectors(self):
self.ss.addAutoTransorm(2)
self.ss.addAutoTransorm(3)
self.ss.removeAutoTransform(3)
assert (self.ss.autosectors, [2])
self.ss.removeAutoTransform(2)
assert (self.ss.autosectors, [])
def testRemoveAutoTransformTransforms(self):
self.ss.addAutoTransorm('a')
self.ss.addAutoTransorm('b')
self.ss.removeAutoTransform('b')
assert (self.ss.autotransforms, ['a'])
self.ss.removeAutoTransform('a')
assert (self.ss.autotransforms, [])
def testTransformPosition(self):
# Check that with no transforms set to autoapply, the limit
# checker function is ignored
ss = VliegTransformSelector()
ss.limitCheckerFunction = self.limitChecker.isPoswithiLimits
self.limitChecker.okay = False
ss.transformPosition(P(0, .1, .2, .3, .4, 5))
def testMockLimitChecker(self):
assert not self.limitChecker.isDeltaNegative(P(0, .1, .2, .3, .4, 5))
assert self.limitChecker.isDeltaNegative(P(0, -.1, .2, .3, .4, 5))
def testAutoTransformPositionWithSectors(self):
self.ss.addAutoTransorm(2)
print "Should print 'INFO: Autosector changed sector from 0 to 2':"
result = self.ss.autoTransformPositionBySector(self.pos)
assert (result == self.pos_in2)
assert (self.ss.sector, 2)
def testAutoTransformPositionWithSectorChoice(self):
self.ss.addAutoTransorm(2)
self.ss.addAutoTransorm(3)
print "Should print 'WARNING: Autosector found multiple sectors...':"
print "Should print 'INFO: Autosector changed sector from 0 to 2':"
result = self.ss.autoTransformPositionBySector(self.pos)
assert (result == self.pos_in2)
assert (self.ss.sector, 2)
def testAutoTransformPositionWithSectorsFails(self):
self.ss.addAutoTransorm(0)
self.ss.addAutoTransorm(1)
self.ss.addAutoTransorm(4)
self.ss.addAutoTransorm(5)
print "Should print 'INFO: Autosector changed sector from 0 to 2':"
with pytest.raises(Exception):
self.ss.autoTransformPositionBySector(self.pos)
#self.ss.autoTransformPositionBySector(self.pos)
assert (self.ss.sector, 0) # unchanged
def testCreateListOfPossibleTransforms(self):
self.ss.addAutoTransorm('a')
assert (self.ss.createListOfPossibleTransforms(),
[(), ['a', ]])
self.ss.addAutoTransorm('b')
assert (self.ss.createListOfPossibleTransforms(),
[(), ['b', ], ['a', ], ['a', 'b']])
self.ss.transforms = ['a', 'c']
def testAutoTransformPositionWithTransforms(self):
self.ss.addAutoTransorm('a')
print "Should print 'INFO: ':"
result = self.ss.autoTransformPositionByTransforms(self.pos)
assert (result == self.pos_in2)
assert (self.ss.sector, 2)
def testAutoTransformPositionWithTansformsChoice(self):
self.ss.addAutoTransorm('a')
self.ss.addAutoTransorm('c')
print "Should print 'WARNING:':"
print "Should print 'INFO: ':"
result = self.ss.autoTransformPositionByTransforms(self.pos)
assert (result == self.pos_in2)
assert (self.ss.sector, 2)
def testTransformPositionWithAutoTransforms(self):
self.ss.addAutoTransorm('a')
assert (self.ss.transformPosition(self.pos) == self.pos_in2)
assert (self.ss.sector, 2)
print "Should not print 'INFO...'"
assert (self.ss.transformPosition(self.pos) == self.pos_in2)
assert (self.ss.sector, 2)
def testTransformPositionWithAutoTransforms2(self):
self.ss.addAutoTransorm(2)
assert (self.ss.transformPosition(self.pos) == self.pos_in2)
assert (self.ss.sector, 2)
print "Should not print 'INFO...'"
assert (self.ss.transformPosition(self.pos) == self.pos_in2)
assert (self.ss.sector, 2)
def test__repr__(self):
self.ss.setSector(0)
print "************************"
print self.ss
print "************************"
self.ss.setTransforms('a')
print self.ss
print "************************"
self.ss.setTransforms(('a', 'b', 'c'))
print self.ss
print "************************"
self.ss.addAutoTransorm(1)
self.ss.addAutoTransorm(2)
self.ss.addAutoTransorm(3)
print self.ss
print "************************"
self.ss.addAutoTransorm('a')
self.ss.addAutoTransorm('c')
print self.ss
print "************************"
class TestTransforms(object):
def setup_method(self):
self.limitCheckerFunction = Mock()
self.ss = VliegTransformSelector()
self.ss.limitCheckerFunction = self.limitCheckerFunction
def applyTransforms(self, transforms, pos):
result = pos.clone()
for transform in transforms:
if transform == 'a':
result = TransformA().transform(result)
if transform == 'b':
result = TransformB().transform(result)
if transform == 'c':
result = TransformC().transform(result)
return self.ss.cutPosition(result)
def _testTransformN(self, n):
transforms = transformsFromSector[n]
pos = P(1, 2, 3, 4, 5, 6)
self.ss.setSector(n)
fromss = self.ss.transformPosition(pos)
fromhere = self.applyTransforms(transforms, pos)
assert (fromss == fromhere,
("sector: %i\ntransforms:%s\n%s !=\n%s" %
(n, transforms, fromss, fromhere)))
def testTransform0(self):
self._testTransformN(0)
def testTransform1(self):
self._testTransformN(1)
def testTransform2(self):
self._testTransformN(2)
def testTransform3(self):
self._testTransformN(3)
def testTransform4(self):
self._testTransformN(5)
def testTransform5(self):
self._testTransformN(5)
def testTransform6(self):
self._testTransformN(6)
def testTransform7(self):
self._testTransformN(7)