Files
dev/script/__Lib/diffcalc-2.1/startup/i21.py
2019-03-20 13:52:00 +01:00

466 lines
17 KiB
Python
Executable File

from startup._common_imports import * # @UnusedWildImport
from diffcalc.gdasupport.minigda.scannable import ScannableMotionWithScannableFieldsBase # @UnusedImport
from startup.beamlinespecific.i21 import I21SampleStage, I21DiffractometerStage, I21TPLab
from diffcalc.hkl.you.geometry import YouGeometry, YouPosition
from diffcalc.hkl.you.constraints import NUNAME
try:
from numpy import matrix
except ImportError:
from numjy import matrix
if not GDA:
import startup._demo
else:
# import __main__ # @UnresolvedImport
from __main__ import x,y,z,th,chi,phi,delta,m5tth, energy, simx,simy,simz,simth,simchi,simphi,simdelta,simm5tth # @UnresolvedImport
LOCAL_MANUAL = "http://confluence.diamond.ac.uk/x/UoIQAw"
# Diffcalc i21
# ======== ===
# delta delta or m5tth
# eta th
# chi 90deg-chi
# phi phi
SIM_MODE=False
class FourCircleI21(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_phys, eta_phys, chi_phys, phi_phys = physical_angle_tuple
return YouPosition(0, delta_phys, 0, eta_phys, 90 - chi_phys, phi_phys, 'DEG')
def internal_position_to_physical_angles(self, internal_position):
clone_position = internal_position.clone()
clone_position.changeToDegrees()
_, delta_phys, _, eta_phys, chi_phys, phi_phys = clone_position.totuple()
return delta_phys, eta_phys, 90 - chi_phys, phi_phys
### Create dummy scannables ###
if GDA:
xyz_eta = ScannableGroup('xyz_eta', [x, y, z]) # @UndefinedVariable
else:
delta = Dummy('delta')
m5tth = Dummy('m5tth')
th = Dummy('th')
chi = Dummy('chi')
phi = Dummy('phi')
x = Dummy('x')
y = Dummy('y')
z = Dummy('z')
xyz_eta = ScannableGroup('xyz_eta', [x, y, z])
#support i21 non-concentric rotation motions
sa = I21SampleStage('sa', th, chi, phi, xyz_eta)
#th = sa.th
#chi = sa.chi
#phi = sa.phi
tp_phi = sa.tp_phi_scannable
tp_lab = I21TPLab('tp_lab', sa)
tp_labx = tp_lab.tp_labx
tp_laby = tp_lab.tp_laby
tp_labz = tp_lab.tp_labz
### Wrap i21 names to get diffcalc names - sample chamber
_fourc = I21DiffractometerStage('_fourc', delta, sa)
delta = _fourc.delta
eta = _fourc.eta
chi = _fourc.chi
phi = _fourc.phi
if GDA:
en=energy
if float(en.getPosition()) == 0: # no energy value - dummy?
en(800)
else:
en = Dummy('en')
en(800)
en.level = 3
### Configure and import diffcalc objects ###
ESMTGKeV = 0.001
settings.hardware = ScannableHardwareAdapter(_fourc, en, ESMTGKeV)
beamline_axes_transform = matrix('0 0 1; 0 1 0; 1 0 0')
settings.geometry = FourCircleI21(beamline_axes_transform=beamline_axes_transform) # @UndefinedVariable
settings.energy_scannable = en
settings.axes_scannable_group= _fourc
settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV
from diffcalc.gdasupport.you import * # @UnusedWildImport
# fourc is created in diffcalc.gdasupport.you. Add some I21 hints into it
fourc.hint_generator = _fourc.get_hints # (the callablemethod) # @UndefinedVariable
if GDA:
print "Running in GDA --- aliasing commands"
alias_commands(globals())
### Load the last ub calculation used
from diffcalc.ub.ub import lastub
lastub()
### Set i21 specific limits
print "INFO: diffcalc limits set in $diffcalc/startup/i21.py taken from http://confluence.diamond.ac.uk/pages/viewpage.action?pageId=51413586"
def setLimitsAndCuts(delta_angle, chi_angle, eta_angle, phi_angle):
''' set motor limits for diffcalc, these are within the actual motor limits
'''
setmin(delta_angle, 0.0)
setmax(delta_angle, 180.0) #default to diode delta limits
setmin(chi_angle, -41.0)
setmax(chi_angle, 36.0)
setmin(eta_angle, 0.0)
setmax(eta_angle, 150.0)
setmin(phi_angle, -100.0)
setmax(phi_angle, 100.0)
#http://jira.diamond.ac.uk/browse/I21-361
setcut(eta_angle, 0.0)
setcut(phi_angle, -180.0)
print "Current hardware limits set to:"
hardware()
setLimitsAndCuts(delta, chi, eta, phi)
### Create i21 bespoke secondary hkl devices
# Warning: this breaks the encapsulation provided by the diffcalc.dc.you public
# interface, and may be prone to breakage in future.
print 'Creating i21 bespoke scannables:'
from diffcalc.dc import dcyou as _dc
from diffcalc.gdasupport.scannable.diffractometer import DiffractometerScannableGroup
from diffcalc.gdasupport.scannable.hkl import Hkl
print '- fourc_vessel & hkl_vessel'
_fourc_vessel = I21DiffractometerStage('_fourc_vessel', m5tth, sa)
fourc_vessel = DiffractometerScannableGroup('fourc_vessel', _dc, _fourc_vessel)
fourc_vessel.hint_generator = _fourc_vessel.get_hints
hkl_vessel = Hkl('hkl_vessel', _fourc_vessel, _dc)
h_vessel, k_vessel, l_vessel = hkl_vessel.h, hkl_vessel.k, hkl_vessel.l
print '- fourc_lowq & hkl_lowq'
LOWQ_OFFSET_ADDED_TO_DELTA_WHEN_READING = -8
_fourc_lowq = I21DiffractometerStage('_fourc_lowq', m5tth, sa,delta_offset=LOWQ_OFFSET_ADDED_TO_DELTA_WHEN_READING)
fourc_lowq = DiffractometerScannableGroup('fourc_lowq', _dc, _fourc_lowq)
fourc_lowq.hint_generator = _fourc_lowq.get_hints
hkl_lowq = Hkl('hkl_lowq', _fourc_lowq, _dc)
h_lowq, k_lowq, l_lowq = hkl_lowq.h, hkl_lowq.k, hkl_lowq.l
print '- fourc_highq & hkl_highq'
highq_OFFSET_ADDED_TO_DELTA_WHEN_READING = 0
_fourc_highq = I21DiffractometerStage('_fourc_highq', m5tth, sa,delta_offset=highq_OFFSET_ADDED_TO_DELTA_WHEN_READING)
fourc_highq = DiffractometerScannableGroup('fourc_highq', _dc, _fourc_highq)
fourc_highq.hint_generator = _fourc_highq.get_hints
hkl_highq = Hkl('hkl_highq', _fourc_highq, _dc)
h_highq, k_highq, l_highq = hkl_highq.h, hkl_highq.k, hkl_highq.l
# sample chamber
print '- fourc_diode & hkl_diode'
_fourc_diode = I21DiffractometerStage('_fourc_diode', delta, sa)
fourc_diode = DiffractometerScannableGroup('fourc_diode', _dc, _fourc_diode)
fourc_diode.hint_generator = _fourc_diode.get_hints
hkl_diode = Hkl('hkl_diode', _fourc_diode, _dc)
h_diode, k_diode, l_diode = hkl_diode.h, hkl_diode.k, hkl_diode.l
def centresample():
sa.centresample()
def zerosample():
'''zero on the currently centred sample location
'''
sa.zerosample()
def toolpoint_on():
'''Switch on tool point
'''
sa.centre_toolpoint = True
def toolpoint_off():
'''Switch off tool point
'''
sa.centre_toolpoint = False
def usediode():
'''Use photo diode in sample chamber
'''
if SIM_MODE:
_fourc.delta_scn=simdelta
setmin(simdelta, 0)
setmax(simdelta, 180)
else:
_fourc.delta_scn = delta
setmin(delta, 0)
setmax(delta, 180)
def usevessel():
'''Use spectrometer
'''
if SIM_MODE:
_fourc.delta_scn=simm5tth
setmin(simm5tth, 0)
setmax(simm5tth, 150)
else:
_fourc.delta_scn = m5tth # note, if changed also update in _fourc_vessel constructor!
setmin(m5tth, 0)
setmax(m5tth, 150)
print "Created i21 bespoke commands: usediode, usevessel, centresample, zerosample, toolpoint_on, toolpoint_off"
if GDA:
def swithMotors(sax, say, saz, sath, sachi, saphi, diodedelta, specm5tth):
import __main__
__main__.xyz_eta = ScannableGroup('xyz_eta', [sax, say, saz]) # @UndefinedVariable
#update support for i21 non-concentric rotation motions
__main__.sa = I21SampleStage('sa', sath, sachi, saphi,__main__.xyz_eta) # @UndefinedVariable
__main__.tp_phi = sa.tp_phi_scannable
__main__.tp_lab = I21TPLab('tp_lab', __main__.sa) # @UndefinedVariable
__main__.tp_labx = __main__.tp_lab.tp_labx # @UndefinedVariable
__main__.tp_laby = __main__.tp_lab.tp_laby # @UndefinedVariable
__main__.tp_labz = __main__.tp_lab.tp_labz # @UndefinedVariable
### update Wrap i21 names to get diffcalc names
_fourc = I21DiffractometerStage('_fourc', diodedelta, __main__.sa) # @UndefinedVariable
__main__.delta = _fourc.delta
__main__.eta = _fourc.eta
__main__.chi = _fourc.chi
__main__.phi = _fourc.phi
#update diffcalc objects
__main__.settings.hardware = ScannableHardwareAdapter(_fourc, __main__.en, ESMTGKeV) # @UndefinedVariable
__main__.settings.geometry = FourCircleI21(beamline_axes_transform=beamline_axes_transform) # @UndefinedVariable
__main__.settings.energy_scannable = __main__.en # @UndefinedVariable
__main__.settings.axes_scannable_group= _fourc
__main__.settings.energy_scannable_multiplier_to_get_KeV = ESMTGKeV
__main__.fourc=DiffractometerScannableGroup('fourc', _dc, _fourc)
__main__.fourc.hint_generator = _fourc.get_hints # (the callabl emethod) # @UndefinedVariable
__main__.hkl = Hkl('hkl', _fourc, _dc)
__main__.h, __main__.k, __main__.l = hkl.h, hkl.k, hkl.l
from diffcalc.gdasupport.you import _virtual_angles
from diffcalc.gdasupport.scannable.simulation import SimulatedCrystalCounter
from diffcalc.gdasupport.scannable.wavelength import Wavelength
__main__.hklverbose = Hkl('hklverbose', _fourc, _dc, _virtual_angles)
__main__.wl = Wavelength('wl',__main__.en,ESMTGKeV) # @UndefinedVariable
__main__.ct = SimulatedCrystalCounter('ct', _fourc, __main__.settings.geometry,__main__.wl) # @UndefinedVariable
#update scannales: fourc_vessel & hkl_vessel'
_fourc_vessel = I21DiffractometerStage('_fourc_vessel', specm5tth, __main__.sa) # @UndefinedVariable
__main__.fourc_vessel = DiffractometerScannableGroup('fourc_vessel', _dc, _fourc_vessel)
__main__.fourc_vessel.hint_generator = _fourc_vessel.get_hints
__main__.hkl_vessel = Hkl('hkl_vessel', _fourc_vessel, _dc)
__main__.h_vessel, __main__.k_vessel, __main__.l_vessel = hkl_vessel.h, hkl_vessel.k, hkl_vessel.l
#Update scannables: fourc_lowq & hkl_lowq'
_fourc_lowq = I21DiffractometerStage('_fourc_lowq', specm5tth, __main__.sa,delta_offset=LOWQ_OFFSET_ADDED_TO_DELTA_WHEN_READING) # @UndefinedVariable
__main__.fourc_lowq = DiffractometerScannableGroup('fourc_lowq', _dc, _fourc_lowq)
__main__.fourc_lowq.hint_generator = _fourc_lowq.get_hints
__main__.hkl_lowq = Hkl('hkl_lowq', _fourc_lowq, _dc)
__main__.h_lowq, __main__.k_lowq, __main__.l_lowq = hkl_lowq.h, hkl_lowq.k, hkl_lowq.l
#Update scannables: fourc_highq & hkl_highq'
_fourc_highq = I21DiffractometerStage('_fourc_highq', specm5tth, __main__.sa,delta_offset=highq_OFFSET_ADDED_TO_DELTA_WHEN_READING) # @UndefinedVariable
__main__.fourc_highq = DiffractometerScannableGroup('fourc_highq', _dc, _fourc_highq)
__main__.fourc_highq.hint_generator = _fourc_highq.get_hints
__main__.hkl_highq = Hkl('hkl_highq', _fourc_highq, _dc)
__main__.h_highq, __main__.k_highq, __main__.l_highq = hkl_highq.h, hkl_highq.k, hkl_highq.l
#Update scannables: fourc_diode & hkl_diode'
_fourc_diode = I21DiffractometerStage('_fourc_diode', diodedelta, __main__.sa) # @UndefinedVariable
__main__.fourc_diode = DiffractometerScannableGroup('fourc_diode', _dc, _fourc_diode)
__main__.fourc_diode.hint_generator = _fourc_diode.get_hints
__main__.hkl_diode = Hkl('hkl_diode', _fourc_diode, _dc)
__main__.h_diode, __main__.k_diode, __main__.l_diode = hkl_diode.h, hkl_diode.k, hkl_diode.l
def stopMotors(sax, say, saz, sath, sachi, saphi, diodedelta, specm5tth):
sax.stop()
say.stop()
saz.stop()
sath.stop()
sachi.stop()
saphi.stop()
diodedelta.stop()
specm5tth.stop()
def simdc():
''' switch to use dummy motors in diffcalc
'''
print "Stop real motors"
stopMotors(x, y, z, th, chi, phi, delta, m5tth)
global SIM_MODE
SIM_MODE=True
import __main__
__main__.en=Dummy("en")
print "Set energy to 12398.425 eV in simulation mode!"
__main__.en(12398.425) #1 Angstrom wavelength @UndefinedVariable
print "Switch to simulation motors"
swithMotors(simx,simy,simz,simth,simchi,simphi,simdelta,simm5tth)
# __main__.th = __main__.sa.simth # @UndefinedVariable
# __main__.chi = __main__.sa.simchi # @UndefinedVariable
# __main__.phi = __main__.sa.simphi # @UndefinedVariable
setLimitsAndCuts(simdelta,simchi,simth,simphi)
def realdc():
''' switch to use real motors in diffcalc
'''
print "Stop simulation motors"
stopMotors(simx,simy,simz,simth,simchi,simphi,simdelta,simm5tth)
global SIM_MODE
SIM_MODE=False
import __main__
print "Set energy to current beamline energy in real mode!"
__main__.en=energy
print "Switch to real motors"
swithMotors(x,y,z,th,chi,phi,delta,m5tth)
# __main__.th = __main__.sa.th # @UndefinedVariable
# __main__.chi = __main__.sa.chi # @UndefinedVariable
# __main__.phi = __main__.sa.phi # @UndefinedVariable
setLimitsAndCuts(delta,chi,eta,phi)
from gda.jython.commands.GeneralCommands import alias # @UnresolvedImport
alias("usediode")
alias("usevessel")
alias("centresample")
alias("zerosample")
alias("toolpoint_on")
alias("toolpoint_off")
print "Created i21 bespoke commands: simdc, realdc"
alias("simdc")
alias("realdc")
else:
from IPython.core.magic import register_line_magic # @UnresolvedImport
from diffcmd.ipython import parse_line
if IPYTHON:
from IPython import get_ipython # @UnresolvedImport @UnusedImport
register_line_magic(parse_line(usediode, globals()))
del usediode
register_line_magic(parse_line(usevessel, globals()))
del usevessel
register_line_magic(parse_line(centresample, globals()))
del centresample
register_line_magic(parse_line(zerosample, globals()))
del zerosample
register_line_magic(parse_line(toolpoint_on, globals()))
del toolpoint_on
register_line_magic(parse_line(toolpoint_off, globals()))
del toolpoint_off
### Demo ###
if not GDA:
class I21Demo(startup._demo.Demo):
def __init__(self, namespace):
startup._demo.Demo.__init__(self, namespace, 'i21')
def i21(self):
startup._demo.print_heading('i21 scannables demo')
self.echorun_magiccmd_list([
'sa',
'pos th 1',
'pos chi 2',
'pos phi 3',
'pos m5tth 4',
'usevessel',
'fourc'])
demo = I21Demo(globals())
else:
print "DIFFCALC demo:"
class I21Demo(object):
def __init__(self, namespace):
self.namespace = namespace
def all(self):
self.orient()
self.constrain()
self.scan()
def remove_test_ubcalc(self):
try:
eval("rmub('test')", self.namespace)
except (OSError, KeyError):
pass
def executeCommand(self, cmd_list):
for cmd in cmd_list:
if cmd == 'help ub':
print("help ub")
exec("print ub.__doc__", self.namespace)
elif cmd == 'help hkl':
print("help(hkl)")
exec("print hkl.__doc__", self.namespace)
else:
exec(cmd, self.namespace)
def orient(self):
print
print "-"*100
print 'Orientation demo'
print
self.remove_test_ubcalc()
cmd_list=[
'help ub',
"from gda.jython.commands.ScannableCommands import pos; pos(wl, 10)",
"newub('test')",
"setlat('cubic', 1,1, 1, 90, 90, 90)",
'ub',
'c2th([0, 0, .1])',
'from gda.jython.commands.ScannableCommands import pos; pos(fourc, [60, 30, 0, 0])',
'addref([0, 0, .1])',
'c2th([0, .1, .1])',
'from gda.jython.commands.ScannableCommands import pos; pos(fourc, [90, 90, 0, 0])',
'addref([0, .1, .1])',
'ub',
'checkub']
self.executeCommand(cmd_list)
def constrain(self):
print
print "-"*100
print 'Constraint demo'
print
cmd_list=[
'help hkl',
'con(a_eq_b)',
'con',
'setmin(delta, 0)',
'setmin(chi, -180)',
'setmin(phi, -180)',
'setmax(phi, 180)']
self.executeCommand(cmd_list)
def scan(self):
print
print "-"*100
print 'Scanning demo'
print
cmd_list=[
'setnphi([0, 0, 1])',
'pos hkl([0, 0, .1])',
'scan(delta, 40, 90, 10, hkl, ct, 1)',
'pos(hkl, [0, .1, 0])',
'scan(h, 0, .1, .02, k, l, fourc, ct, 1)',
'con(psi)',
'scan(psi, 0, 90, 10, hkl, [.1, 0, .1], eta, chi, phi, ct, .1)']
self.executeCommand(cmd_list)