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,62 @@
###
# 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/>.
###
try:
from gda.device.scannable import PseudoDevice
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableBase as PseudoDevice
class ScannableGroup(PseudoDevice):
def __init__(self, name, motorList):
self.setName(name)
# Set input format
motorNames = []
for scn in motorList:
motorNames.append(scn.getName())
self.setInputNames(motorNames)
# Set output format
format = []
for motor in motorList:
format.append(motor.getOutputFormat()[0])
self.setOutputFormat(format)
self.__motors = motorList
def asynchronousMoveTo(self, position):
# if input has any Nones, then replace these with the current positions
if None in position:
position = list(position)
current = self.getPosition()
for idx, val in enumerate(position):
if val is None:
position[idx] = current[idx]
for scn, pos in zip(self.__motors, position):
scn.asynchronousMoveTo(pos)
def getPosition(self):
return [scn.getPosition() for scn in self.__motors]
def isBusy(self):
for scn in self.__motors:
if scn.isBusy():
return True
return False

View File

@@ -0,0 +1,126 @@
###
# 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/>.
###
try:
from gda.device.scannable import ScannableMotionBase
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableBase as ScannableMotionBase
from diffcalc.util import getMessageFromException
# TODO: Split into a base class when making other scannables
class DiffractometerScannableGroup(ScannableMotionBase):
""""
Wraps up a scannableGroup of axis to tweak the way the resulting
object is displayed and to add a simulate move to method.
The scannable group should have the same geometry as that expected
by the diffractometer hardware geometry used in the diffraction
calculator.
The optional parameter slaveDriver can be used to provide a
slave_driver. This is useful for triggering a move of an incidental
axis whose position depends on that of the diffractometer, but whose
position need not be included in the DiffractometerScannableGroup
itself. This parameter is exposed as a field and can be set or
cleared to null at will without effecting the core calculation code.
"""
def __init__(self, name, diffcalc_module, scannableGroup,
slave_driver=None, hint_generator=None):
# if motorList is None, will create a dummy __group
self.diffcalc_module = diffcalc_module
self.__group = scannableGroup
self.slave_driver = slave_driver
self.setName(name)
self.hint_generator = hint_generator
def getInputNames(self):
return self.__group.getInputNames()
def getExtraNames(self):
if self.slave_driver is None:
return []
else:
return self.slave_driver.getScannableNames()
def getOutputFormat(self):
if self.slave_driver is None:
slave_formats = []
else:
slave_formats = self.slave_driver.getScannableNames()
return list(self.__group.getOutputFormat()) + slave_formats
def asynchronousMoveTo(self, position):
self.__group.asynchronousMoveTo(position)
if self.slave_driver is not None:
self.slave_driver.triggerAsynchronousMove(position)
def getPosition(self):
if self.slave_driver is None:
slave_positions = []
else:
slave_positions = self.slave_driver.getPositions()
return list(self.__group.getPosition()) + list(slave_positions)
def isBusy(self):
if self.slave_driver is None:
return self.__group.isBusy()
else:
return self.__group.isBusy() or self.slave_driver.isBusy()
def waitWhileBusy(self):
self.__group.waitWhileBusy()
if self.slave_driver is not None:
self.slave_driver.waitWhileBusy()
def simulateMoveTo(self, pos):
if len(pos) != len(self.getInputNames()):
raise ValueError('Wrong number of inputs')
try:
(hkl, params) = self.diffcalc_module.angles_to_hkl(pos)
except Exception, e:
return "Error: %s" % getMessageFromException(e)
width = max(len(k) for k in params)
lines = ([' ' + 'hkl'.rjust(width) + ' : % 9.4f %.4f %.4f' %
(hkl[0], hkl[1], hkl[2])])
lines[-1] = lines[-1] + '\n'
fmt = ' %' + str(width) + 's : % 9.4f'
for k in sorted(params):
lines.append(fmt % (k, params[k]))
return '\n'.join(lines)
def __repr__(self):
position = self.getPosition()
names = list(self.getInputNames()) + list(self.getExtraNames())
if self.hint_generator is None:
hint_list = [''] * len(self.getInputNames())
else:
hint_list = self.hint_generator()
lines = [self.name + ':']
width = max(len(k) for k in names)
fmt = ' %' + str(width) + 's : % 9.4f %s'
for name, pos, hint in zip(names, position, hint_list):
lines.append(fmt % (name, pos, hint))
lines[len(self.getInputNames())] += '\n'
return '\n'.join(lines)

View File

@@ -0,0 +1,135 @@
###
# 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 platform
DEBUG = False
try:
from gda.device.scannable.scannablegroup import \
ScannableMotionWithScannableFieldsBase
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableMotionWithScannableFieldsBase
from diffcalc.util import getMessageFromException, DiffcalcException
class _DynamicDocstringMetaclass(type):
def _get_doc(self):
return Hkl.dynamic_docstring
__doc__ = property(_get_doc) # @ReservedAssignment
class Hkl(ScannableMotionWithScannableFieldsBase):
if platform.system() != 'Java':
__metaclass__ = _DynamicDocstringMetaclass # TODO: Removed to fix Jython
dynamic_docstring = 'Hkl Scannable'
def _get_doc(self):
return Hkl.dynamic_docstring
__doc__ = property(_get_doc) # @ReservedAssignment
def __init__(self, name, diffractometerObject, diffcalcObject,
virtualAnglesToReport=None):
self.diffhw = diffractometerObject
self._diffcalc = diffcalcObject
if type(virtualAnglesToReport) is str:
virtualAnglesToReport = (virtualAnglesToReport,)
self.vAngleNames = virtualAnglesToReport
self.setName(name)
self.setInputNames(['h', 'k', 'l'])
self.setOutputFormat(['%7.5f'] * 3)
if self.vAngleNames:
self.setExtraNames(self.vAngleNames)
self.setOutputFormat(['%7.5f'] * (3 + len(self.vAngleNames)))
self.completeInstantiation()
self.setAutoCompletePartialMoveToTargets(True)
self.dynamic_class_doc = 'Hkl Scannable xyz'
def rawAsynchronousMoveTo(self, hkl):
if len(hkl) != 3: raise ValueError('Hkl device expects three inputs')
try:
(pos, _) = self._diffcalc.hkl_to_angles(hkl[0], hkl[1], hkl[2])
except DiffcalcException, e:
if DEBUG:
raise
else:
raise DiffcalcException(e.message)
self.diffhw.asynchronousMoveTo(pos)
def rawGetPosition(self):
pos = self.diffhw.getPosition() # a tuple
(hkl , params) = self._diffcalc.angles_to_hkl(pos)
result = list(hkl)
if self.vAngleNames:
for vAngleName in self.vAngleNames:
result.append(params[vAngleName])
return result
def getFieldPosition(self, i):
return self.getPosition()[i]
def isBusy(self):
return self.diffhw.isBusy()
def waitWhileBusy(self):
return self.diffhw.waitWhileBusy()
def simulateMoveTo(self, hkl):
if type(hkl) not in (list, tuple):
raise ValueError('Hkl device expects three inputs')
if len(hkl) != 3:
raise ValueError('Hkl device expects three inputs')
(pos, params) = self._diffcalc.hkl_to_angles(hkl[0], hkl[1], hkl[2])
width = max(len(k) for k in (params.keys() + list(self.diffhw.getInputNames())))
fmt = ' %' + str(width) + 's : % 9.4f'
lines = [self.diffhw.getName() + ' would move to:']
for idx, name in enumerate(self.diffhw.getInputNames()):
lines.append(fmt % (name, pos[idx]))
lines[-1] = lines[-1] + '\n'
for k in sorted(params):
lines.append(fmt % (k, params[k]))
return '\n'.join(lines)
def __str__(self):
return self.__repr__()
def __repr__(self):
lines = ['hkl:']
pos = self.diffhw.getPosition()
try:
(hkl, params) = self._diffcalc.angles_to_hkl(pos)
except Exception, e:
return "<hkl: %s>" % getMessageFromException(e)
width = max(len(k) for k in params)
lines.append(' ' + 'hkl'.rjust(width) + ' : %9.4f %.4f %.4f' % (hkl[0], hkl[1], hkl[2]))
lines[-1] = lines[-1] + '\n'
fmt = ' %' + str(width) + 's : % 9.4f'
for k in sorted(params):
lines.append(fmt % (k, params[k]))
return '\n'.join(lines)

View File

@@ -0,0 +1,47 @@
###
# 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/>.
###
try:
from gda.device.scannable import ScannableMotionBase
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableBase as ScannableMotionBase
class MockMotor(ScannableMotionBase):
def __init__(self, name='mock'):
self.pos = 0.0
self._busy = False
self.name = name
def asynchronousMoveTo(self, pos):
self._busy = True
self.pos = float(pos)
def getPosition(self):
return self.pos
def isBusy(self):
return self._busy
def makeNotBusy(self):
self._busy = False
def getOutputFormat(self):
return ['%f']

View File

@@ -0,0 +1,45 @@
###
# 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/>.
###
try:
from gda.device.scannable import ScannableMotionBase
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableBase as ScannableMotionBase
class DiffractionCalculatorParameter(ScannableMotionBase):
def __init__(self, name, parameterName, parameter_manager):
self.parameter_manager = parameter_manager
self.parameterName = parameterName
self.setName(name)
self.setInputNames([parameterName])
self.setOutputFormat(['%5.5f'])
self.setLevel(3)
def asynchronousMoveTo(self, value):
self.parameter_manager.set_constraint(self.parameterName, value)
def getPosition(self):
return self.parameter_manager.get_constraint(self.parameterName)
def isBusy(self):
return False

View File

@@ -0,0 +1,21 @@
'''
Created on 7 May 2016
@author: walton
'''
from diffcalc.util import allnum
def sim(scn, hkl):
"""sim hkl scn -- simulates moving scannable (not all)
"""
if not isinstance(hkl, (tuple, list)):
raise TypeError
if not allnum(hkl):
raise TypeError()
try:
print scn.simulateMoveTo(hkl)
except AttributeError:
raise TypeError(
"The first argument does not support simulated moves")

View File

@@ -0,0 +1,139 @@
###
# 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 time
from math import sqrt, pi, exp
try:
from gda.device.scannable import PseudoDevice
except ImportError:
from diffcalc.gdasupport.minigda.scannable import \
ScannableBase as PseudoDevice
from diffcalc.ub.crystal import CrystalUnderTest
from diffcalc.hkl.you.calc import youAnglesToHkl
from diffcalc.hkl.vlieg.calc import vliegAnglesToHkl
from diffcalc.hkl.you.geometry import calcCHI, calcPHI
TORAD = pi / 180
TODEG = 180 / pi
class Equation(object):
def __call__(self, dh, dk, dl):
raise Exception('Abstract')
def __str__(self):
"Abstract equation"
class Gaussian(Equation):
def __init__(self, variance):
self.variance = float(variance)
def __call__(self, dh, dk, dl):
dr_squared = dh * dh + dk * dk + dl * dl
return (1 / sqrt(2 * pi * self.variance) *
exp(-dr_squared / (2 * self.variance)))
class SimulatedCrystalCounter(PseudoDevice):
def __init__(self, name, diffractometerScannable, geometryPlugin,
wavelengthScannable, equation=Gaussian(.01), engine='you'):
self.setName(name)
self.setInputNames([name + '_count'])
self.setOutputFormat(['%7.5f'])
self.exposureTime = 1
self.pause = True
self.diffractometerScannable = diffractometerScannable
self.geometry = geometryPlugin
self.wavelengthScannable = wavelengthScannable
self.equation = equation
self.engine = engine
self.cut = None
self.UB = None
self.chiMissmount = 0.
self.phiMissmount = 0.
self.setCrystal('cubic', 1, 1, 1, 90, 90, 90)
def setCrystal(self, name, a, b, c, alpha, beta, gamma):
self.cut = CrystalUnderTest(name, a, b, c, alpha, beta, gamma)
self.calcUB()
def setChiMissmount(self, chi):
self.chiMissmount = chi
self.calcUB()
def setPhiMissmount(self, phi):
self.phiMissmount = phi
self.calcUB()
def calcUB(self):
CHI = calcCHI(self.chiMissmount * TORAD)
PHI = calcPHI(self.phiMissmount * TORAD)
self.UB = CHI * PHI * self.cut.B
def asynchronousMoveTo(self, exposureTime):
self.exposureTime = exposureTime
if self.pause:
time.sleep(exposureTime) # Should not technically block!
def getPosition(self):
h, k, l = self.getHkl()
dh, dk, dl = h - round(h), k - round(k), l - round(l)
count = self.equation(dh, dk, dl)
#return self.exposureTime, count*self.exposureTime
return count * self.exposureTime
def getHkl(self):
pos = self.geometry.physical_angles_to_internal_position(
self.diffractometerScannable.getPosition())
pos.changeToRadians()
wavelength = self.wavelengthScannable.getPosition()
if self.engine.lower() == 'vlieg':
return vliegAnglesToHkl(pos, wavelength, self.UB)
elif self.engine.lower() == 'you':
return youAnglesToHkl(pos, wavelength, self.UB)
else:
raise ValueError(self.engine)
def isBusy(self):
return False
def __str__(self):
return self.__repr__()
def __repr__(self):
s = 'simulated crystal detector: %s\n' % self.getName()
h, k, l = self.getHkl()
s += ' h : %f\n' % h
s += ' k : %f\n' % k
s += ' l : %f\n' % l
s += self.cut.__str__() + '\n'
s += "chi orientation: %s\n" % self.chiMissmount
s += "phi orientation: %s\n" % self.phiMissmount
ub = self.UB.tolist()
s += "UB:\n"
s += " % 18.13f% 18.13f% 18.12f\n" % (ub[0][0], ub[0][1], ub[0][2])
s += " % 18.13f% 18.13f% 18.12f\n" % (ub[1][0], ub[1][1], ub[1][2])
s += " % 18.13f% 18.13f% 18.12f\n" % (ub[2][0], ub[2][1], ub[2][2])
return s

View File

@@ -0,0 +1,109 @@
###
# 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, tan, sin, atan, cos, atan2
TORAD = pi / 180
TODEG = 180 / pi
class SlaveScannableDriver(object):
def __init__(self, scannables):
self.scannables = scannables
def isBusy(self):
for scn in self.scannables:
if scn.isBusy():
return True
return False
def waitWhileBusy(self):
for scn in self.scannables:
scn.waitWhileBusy()
def triggerAsynchronousMove(self, triggerPos):
nu = self.slaveFromTriggerPos(triggerPos)
for scn in self.scannables:
scn.asynchronousMoveTo(nu)
def getPosition(self):
return self.scannables[0].getPosition()
def slaveFromTriggerPos(self, triggerPos):
raise Exception("Abstract")
def getScannableNames(self):
return [scn.name for scn in self.scannables]
def getOutputFormat(self):
return [list(scn.outputFormat)[0] for scn in self.scannables]
def getPositions(self):
return [float(scn.getPosition()) for scn in self.scannables]
"""
Based on: Elias Vlieg, "A (2+3)-Type Surface Diffractometer: Mergence of the
z-axis and (2+2)-Type Geometries", J. Appl. Cryst. (1998). 31. 198-203
"""
class NuDriverForSixCirclePlugin(SlaveScannableDriver):
def slaveFromTriggerPos(self, triggerPos):
alpha, delta, gamma, _, _, _ = triggerPos
alpha = alpha * TORAD
delta = delta * TORAD
gamma = gamma * TORAD
### Equation16 RHS ###
rhs = -1 * tan(gamma - alpha) * sin(delta)
nu = atan(rhs) # -pi/2 <= nu <= pi/2
return nu * TODEG
class NuDriverForWillmottHorizontalGeometry(SlaveScannableDriver):
"""
Based on: Phillip Willmott, "Angle calculations for a (2+3)-type
diffractometer: focus on area detectors", J. Appl. Cryst. (2011). 44.
73-83
"""
def __init__(self, scannables, area_detector=False):
SlaveScannableDriver.__init__(self, scannables)
self.area_detector = area_detector
def slaveFromTriggerPos(self, triggerPos):
delta, gamma, omegah, _ = triggerPos
delta *= TORAD
gamma *= TORAD
omegah *= TORAD
if self.area_detector:
nu = atan2(sin(delta - omegah), tan(gamma)) # (66)
else:
top = -sin(gamma) * sin(omegah)
bot = (sin(omegah) * cos(gamma) * sin(delta) +
cos(omegah) * cos(delta))
nu = atan2(top, bot) # (61)
print 'nu:', nu * TODEG
return nu * TODEG

View File

@@ -0,0 +1,184 @@
###
# 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 time
import threading
import socket
PORT = 4567
from gda.device.scannable import ScannableMotionWithScannableFieldsBaseTest
#import scannable.vrmlModelDriver
#reload(scannable.vrmlModelDriver);from scannable.vrmlModelDriver import \
# VrmlModelDriver, LinearProfile, MoveThread
#fc=VrmlModelDriver(
# 'fc',['alpha','delta','omega', 'chi','phi'], speed=30, host='diamrl5104')
#alpha = fc.alpha
#delta = fc.delta
#omega = fc.omega
#chi = fc.chi
#phi = fc.phi
def connect_to_socket(host, port):
print "Connecting to %s on port %d" % (host, port)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.connect((host, port))
print "Connected"
socketfile = sock.makefile('rw', 0)
return socketfile
class LinearProfile(object):
def __init__(self, v, t_accel, startList, endList):
assert len(startList) == len(endList)
self.v = float(v)
self.start = startList
self.end = endList
self.t_accel = t_accel
distances = [e - s for e, s in zip(self.end, self.start)]
max_distance = max([abs(d) for d in distances])
if max_distance == 0:
self.delta_time = 0
else:
self.delta_time = abs(max_distance / self.v)
self.speeds = [d / self.delta_time for d in distances]
self.start_time = time.time()
def getPosition(self):
if self.start_time is None:
return self.start
if not self.isMoving():
return self.end
t = abs(float(time.time() - self.start_time))
if t > self.delta_time:
# we are in the deceleration phase (i.e paused for now)
return self.end
return [s + v * t for s, v in zip(self.start, self.speeds)]
def isMoving(self):
return time.time() < self.start_time + self.delta_time + self.t_accel
class MoveThread(threading.Thread):
def __init__(self, profile, socketfile, axisNames):
threading.Thread.__init__(self)
self.profile = profile
self.socketfile = socketfile
self.axisNames = axisNames
def run(self):
while self.profile.isMoving():
self.update()
time.sleep(.1)
self.update()
def update(self):
pos = self.profile.getPosition()
d = dict(zip(map(str, self.axisNames), pos))
if self.socketfile:
self.socketfile.write(repr(d) + '\n')
class VrmlModelDriver(ScannableMotionWithScannableFieldsBaseTest):
def __init__(self, name, axes_names, host=None, speed=60, t_accel=.1,
format='%.3f'):
self.name = name
self.inputNames = list(axes_names)
self.extraNames = []
self.outputFormat = [format] * len(self.inputNames)
self.completeInstantiation()
self.__last_target = [0.] * len(self.inputNames)
self.verbose = False
self.move_thread = None
self.speed = speed
self.host = host
self.t_accel = t_accel
self.socketfile = None
if self.host:
try:
self.connect()
except socket.error:
print "Failed to connect to %s:%r" % (self.host, PORT)
print "Connect with: %s.connect()" % self.name
def connect(self):
self.socketfile = connect_to_socket(self.host, PORT)
self.rawAsynchronousMoveTo(self.__last_target)
def isBusy(self):
if self.move_thread is None:
return False
return self.move_thread.profile.isMoving()
def rawGetPosition(self):
if self.move_thread is None:
return self.__last_target
else:
return self.move_thread.profile.getPosition()
def rawAsynchronousMoveTo(self, targetList):
if self.isBusy():
raise Exception(self.name + ' is already moving')
if self.verbose:
print self.name + ".rawAsynchronousMoveTo(%r)" % targetList
for i, target in enumerate(targetList):
if target is None:
targetList[i] = self.__last_target[i]
profile = LinearProfile(
self.speed, self.t_accel, self.__last_target, targetList)
self.move_thread = MoveThread(
profile, self.socketfile, self.inputNames)
self.move_thread.start()
self.__last_target = targetList
def getFieldPosition(self, index):
return self.getPosition()[index]
def __del__(self):
self.socketfile.close()
#class TrapezoidProfile(object):
#
# def __init__(self, t_accel, v_max, delta_x):
# self.t_a = t_accel
# self.v_m = v_max
# self.delta_x = delta_x
#
# self.t_c = (self.X - self.v_m*self.t_a) / self.v_m
#
# def x(self, t):
# if self.t_c <=0:
# return self.__xshort(t)
# else:
# return self.__xlong(t)
#
# def __xshort(self, t):
# delta_t = 2 * sqrt(self.delta_x*self.t_a/self.v_m)
# if t <= .5*delta_t:
# return (.5*self.v_m/self.t_a) * t**2
# else:
# v_peak = (self.v_m/self.t_a) * .5*delta_t
# return (t-.5*delta_t)*v_peak - (t-.5*delta_t)**2 ####HERE, bugged
# self.delta_x/2

View File

@@ -0,0 +1,50 @@
###
# 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/>.
###
try:
from gdascripts.pd.dummy_pds import DummyPD
except ImportError:
from diffcalc.gdasupport.minigda.scannable import DummyPD
class Wavelength(DummyPD):
def __init__(self, name, energyScannable,
energyScannableMultiplierToGetKeV=1):
self.energyScannable = energyScannable
self.energyScannableMultiplierToGetKeV = \
energyScannableMultiplierToGetKeV
DummyPD.__init__(self, name)
def asynchronousMoveTo(self, pos):
self.energyScannable.asynchronousMoveTo(
(12.39842 / pos) / self.energyScannableMultiplierToGetKeV)
def getPosition(self):
energy = self.energyScannable.getPosition()
if energy == 0:
raise Exception(
"The energy is 0, so no wavelength could be calculated.run_All()")
return 12.39842 / (energy * self.energyScannableMultiplierToGetKeV)
def isBusy(self):
return self.energyScannable.isBusy()
def waitWhileBusy(self):
return self.energyScannable.waitWhileBusy()