##############################################################################
##
# This file is part of Sardana
##
# http://www.sardana-controls.org/
##
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
# Sardana is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Sardana 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 Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Sardana. If not, see <http://www.gnu.org/licenses/>.
##
##############################################################################
"""
Macro library containning diffractometer related macros for the macros
server Tango device server as part of the Sardana project.
"""
# TODO: use taurus instead of PyTango API e.g. read_attribute,
# write_attribute. This module is full of PyTango centric calls.
# TODO: use explicit getters to obtain Sardana elements
# (controller - getController, pseudomotor - getPseudoMotor, ...) instead of
# using getDevice. However this getter seems to accept only the elements names
# and not the full names.
__all__ = ["addreflection", "affine", "br", "ca", "caa", "ci", "computeub",
"freeze", "getmode", "hklscan", "hscan", "kscan", "latticecal",
"loadcrystal", "lscan", "newcrystal", "or0", "or1", "orswap",
"pa", "savecrystal", "setaz", "setlat", "setmode", "setor0",
"setor1", "setorn", "th2th", "ubr", "wh"]
import time
import math
import os
import re
import numpy as np
from sardana.sardanautils import py2_round
from sardana.macroserver.macro import Hookable, Macro, iMacro, Type
from sardana.macroserver.macros.scan import aNscan
from sardana.macroserver.msexception import UnknownEnv
from taurus.core.util.log import Logger
logger = Logger.getLogger("MacroManager")
logger.info(
"Diffractometer macros are at early stage. They can slightly change. Macro luppsi is not tested.")
class _diffrac:
"""Internal class used as a base class for the diffractometer macros"""
env = ('DiffracDevice',)
def prepare(self):
dev_name = self.getEnv('DiffracDevice')
self.diffrac = self.getDevice(dev_name)
try:
dev_name = self.getEnv('Psi')
self.psidevice = self.getDevice(dev_name)
except:
pass
motorlist = self.diffrac.motorlist
pseudo_motor_names = []
for motor in self.diffrac.hklpseudomotorlist:
pseudo_motor_names.append(motor.split(' ')[0])
self.h_device = self.getDevice(pseudo_motor_names[0])
self.k_device = self.getDevice(pseudo_motor_names[1])
self.l_device = self.getDevice(pseudo_motor_names[2])
motor_list = self.diffrac.motorlist
self.nb_motors = len(motor_list)
try:
self.angle_names = self.diffrac.motorroles
except: # Only for compatibility
self.angle_names = []
if self.nb_motors == 4:
self.angle_names.append("omega")
self.angle_names.append("chi")
self.angle_names.append("phi")
self.angle_names.append("tth")
elif self.nb_motors == 6:
self.angle_names.append("mu")
self.angle_names.append("omega")
self.angle_names.append("chi")
self.angle_names.append("phi")
self.angle_names.append("gamma")
self.angle_names.append("delta")
if self.nb_motors == 4:
self.labelmotor = {'Omega': "omega",
'Chi': "chi", 'Phi': "phi", 'Tth': "tth"}
elif self.nb_motors == 6:
self.labelmotor = {'Mu': "mu", 'Theta': "omega", 'Chi': "chi",
'Phi': "phi", 'Gamma': "gamma",
'Delta': "delta"}
prop = self.diffrac.get_property(['DiffractometerType'])
for v in prop['DiffractometerType']:
self.type = v
self.angle_device_names = {}
for i, motor in enumerate(motor_list):
self.angle_device_names[self.angle_names[i]] = motor.split(' ')[0]
# TODO: it should not be necessary to implement on_stop methods in the
# macros in order to stop the moveables. Macro API should provide this kind
# of emergency stop (if the moveables are correctly reserved with the
# getMotion method) in case of aborting a macro.
def on_stop(self):
for angle in self.angle_names:
angle_dev = self.getDevice(self.angle_device_names[angle])
angle_dev.Stop()
def check_collinearity(self, h0, k0, l0, h1, k1, l1):
print(h0)
cpx = k0 * l1 - l0 * k1
cpy = l0 * h1 - h0 * l1
cpz = h0 * k1 - k0 * h1
cp_square = math.sqrt(cpx * cpx + cpy * cpy + cpz * cpz)
collinearity = False
if cp_square < 0.01:
collinearity = True
return collinearity
def get_hkl_ref0(self):
reflections = []
try:
reflections = self.diffrac.reflectionlist
except:
pass
hkl = []
if reflections is not None:
for i in range(1, 4):
hkl.append(reflections[0][i])
return hkl
def get_hkl_ref1(self):
reflections = []
try:
reflections = self.diffrac.reflectionlist
except:
pass
hkl = []
if reflections is not None:
if len(reflections) > 1:
for i in range(1, 4):
hkl.append(reflections[1][i])
return hkl
def fl(self, ch,
regx=re.compile(
'(?<![\d.])'
'(?![1-9]\d*(?![\d.])|\d*\.\d*\.)'
'0*(?!(?<=0)\.)'
'([\d.]+?)'
'\.?0*'
'(?![\d.])'
),
repl=lambda mat: mat.group(mat.lastindex)
if mat.lastindex != 3
else '0' + mat.group(3)):
mat = regx.search(ch)
if mat:
return regx.sub(repl, ch)
[docs]
class br(Macro, _diffrac, Hookable):
"""Move the diffractometer to the reciprocal space coordinates given by
H, K and L.
If a fourth parameter is given, the combination of angles to be set is
the correspondig to the given index. The index of the
angles combinations are then changed."""
hints = {'allowsHooks': ('pre-move', 'post-move')}
param_def = [
['H', Type.String, None, "H value"],
['K', Type.String, None, "K value"],
['L', Type.String, None, "L value"],
['AnglesIndex', Type.Integer, -1, "Angles index"],
['FlagNotBlocking', Type.Integer, 0,
"If 1 not block. Return without finish movement"],
['FlagPrinting', Type.Integer, 0,
"If 1 printing. Used by ubr"]
]
[docs]
def prepare(self, H, K, L, AnglesIndex, FlagNotBlocking, FlagPrinting):
_diffrac.prepare(self)
self.motors = []
for motor_name in self.angle_device_names.values():
self.motors.append(self.getMotor(motor_name))
[docs]
def run(self, H, K, L, AnglesIndex, FlagNotBlocking, FlagPrinting):
h_idx = 0
k_idx = 1
l_idx = 2
if AnglesIndex != -1:
sel_tr = AnglesIndex
else:
sel_tr = self.diffrac.selectedtrajectory
hkl_labels = ["H", "K", "L"]
if H in hkl_labels or K in hkl_labels or L in hkl_labels:
try:
q_vector = self.getEnv('Q')
except UnknownEnv:
self.error("Environment Q not defined. Run wh to define it")
return
try:
if H in hkl_labels:
H = float(q_vector[h_idx])
if K in hkl_labels:
K = float(q_vector[k_idx])
if L in hkl_labels:
L = float(q_vector[l_idx])
except:
self.error("Wrong format of Q vector")
return
hkl_values = [float(H), float(K), float(L)]
self.diffrac.write_attribute("computetrajectoriessim", hkl_values)
angles_list = self.diffrac.trajectorylist[sel_tr]
if FlagNotBlocking == 0:
cmd = "mv"
for name, angle in zip(self.angle_names, angles_list):
cmd = cmd + " " + str(self.angle_device_names[name])
cmd = cmd + " " + str(angle)
if FlagPrinting == 1:
cmd = "u" + cmd
mv, _ = self.createMacro(cmd)
mv._setHooks(self.hooks)
self.runMacro(mv)
else:
for name, angle in zip(self.angle_names, angles_list):
angle_dev = self.getObj(self.angle_device_names[name])
angle_dev.write_attribute("Position", angle)
self.setEnv('Q', [hkl_values[h_idx], hkl_values[k_idx],
hkl_values[l_idx], self.diffrac.WaveLength])
[docs]
class ubr(Macro, _diffrac, Hookable):
"""Move the diffractometer to the reciprocal space coordinates given by
H, K and L und update.
"""
hints = {'allowsHooks': ('pre-move', 'post-move')}
param_def = [
["hh", Type.String, "Not set", "H position"],
["kk", Type.String, "Not set", "K position"],
["ll", Type.String, "Not set", "L position"],
['AnglesIndex', Type.Integer, -1, "Angles index"]
]
[docs]
def prepare(self, hh, kk, ll, AnglesIndex):
_diffrac.prepare(self)
self.motors = []
for motor_name in self.angle_device_names.values():
self.motors.append(self.getMotor(motor_name))
[docs]
def run(self, hh, kk, ll, AnglesIndex):
if ll != "Not set":
br, _ = self.prepareMacro("br", hh, kk, ll, AnglesIndex, 0, 1)
br._setHooks(self.hooks)
self.runMacro(br)
else:
self.output("usage: ubr H K L [Trajectory]")
class _ca(Macro, _diffrac):
"""Calculate motor positions for given H K L according to the current
operation mode, for all trajectories or for the first one"""
param_def = [
['H', Type.Float, None, "H value for the azimutal vector"],
['K', Type.Float, None, "K value for the azimutal vector"],
['L', Type.Float, None, "L value for the azimutal vector"],
['Trajectory', Type.Float, -1, "If -1, all trajectories"],
]
def prepare(self, H, K, L, Trajectory):
_diffrac.prepare(self)
def run(self, H, K, L, Trajectory):
hkl_values = [H, K, L]
self.diffrac.write_attribute("computetrajectoriessim", hkl_values)
if Trajectory == -1:
start_range = 0
end_range = len(self.diffrac.trajectorylist)
else:
start_range = Trajectory
end_range = Trajectory + 1
for i in range(int(start_range), int(end_range)):
angles_list = self.diffrac.trajectorylist[i]
self.output("")
self.output("Trajectory %2d " % i)
self.output("H K L = %9.5f %9.5f %9.5f " %
(self.h_device.position, self.k_device.position,
self.l_device.position))
try:
self.output("Azimuth (Psi) = %7.5f" %
(self.psidevice.Position))
except:
self.warning(
"Not able to read psi. Check if environment Psi is defined")
self.output("Wavelength = %7.5f" % (self.diffrac.WaveLength))
self.output("")
str_pos = {}
j = 0
for name in self.angle_names:
str_pos[name] = "%7.5f" % angles_list[j]
j = j + 1
if self.nb_motors == 6:
self.output("%10s %11s %12s %11s %10s %11s" %
("Delta", "Theta", "Chi", "Phi",
"Mu", "Gamma"))
self.output("%10s %11s %12s %11s %10s %11s" %
(str_pos[self.labelmotor["Delta"]],
str_pos[self.labelmotor["Theta"]],
str_pos[self.labelmotor["Chi"]],
str_pos[self.labelmotor["Phi"]],
str_pos[self.labelmotor["Mu"]],
str_pos[self.labelmotor["Gamma"]]))
elif self.nb_motors == 4:
self.output("%10s %11s %12s %11s" %
("Tth", "Omega", "Chi", "Phi"))
self.output("%10s %11s %12s %11s" %
(str_pos[self.labelmotor["Tth"]],
str_pos[self.labelmotor["Omega"]],
str_pos[self.labelmotor["Chi"]],
str_pos[self.labelmotor["Phi"]]))
elif self.nb_motors == 7:
self.output("%10s %11s %12s %11s %11s %11s %11s" %
(self.angle_names[0],
self.angle_names[1],
self.angle_names[2],
self.angle_names[3],
self.angle_names[4],
self.angle_names[5],
self.angle_names[6]))
self.output("%10s %11s %12s %11s %11s %11s %11s" %
(str_pos[self.angle_names[0]],
str_pos[self.angle_names[1]],
str_pos[self.angle_names[2]],
str_pos[self.angle_names[3]],
str_pos[self.angle_names[4]],
str_pos[self.angle_names[5]],
str_pos[self.angle_names[6]]))
[docs]
class ca(Macro, _diffrac):
"""Calculate motor positions for given H K L according to the current
operation mode (trajectory 0)."""
param_def = [
['H', Type.Float, None, "H value for the azimutal vector"],
['K', Type.Float, None, "K value for the azimutal vector"],
['L', Type.Float, None, "L value for the azimutal vector"],
]
[docs]
def prepare(self, H, K, L):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L):
hkl_values = [H, K, L]
self.execMacro("_ca", H, K, L, 0)
[docs]
class caa(Macro, _diffrac):
"""Calculate motor positions for given H K L according to the current
operation mode (all trajectories)"""
param_def = [
['H', Type.Float, None, "H value for the azimutal vector"],
['K', Type.Float, None, "K value for the azimutal vector"],
['L', Type.Float, None, "L value for the azimutal vector"],
]
[docs]
def prepare(self, H, K, L):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L):
hkl_values = [H, K, L]
self.execMacro("_ca", H, K, L)
[docs]
class ci(Macro, _diffrac):
""" Calculate hkl for given angle values """
param_def = [
['mu', Type.Float, None, "Mu value"],
['theta', Type.Float, None, "Theta value"],
['chi', Type.Float, None, "Chi value"],
['phi', Type.Float, None, "Phi value"],
['gamma', Type.Float, -999, "Gamma value"],
['delta', Type.Float, -999, "Delta value"],
['omega_t', Type.Float, -999, "Omega_t value"],
]
[docs]
def prepare(self, mu, theta, chi, phi, gamma, delta, omega_t):
_diffrac.prepare(self)
[docs]
def run(self, mu, theta, chi, phi, gamma, delta, omega_t):
if delta == -999 and self.nb_motors == 6:
self.error("Six angle values are need as argument")
elif omega_t == -999 and self.nb_motors == 7:
msg = ("Seven angle values are need as argument (omega_t is "
"missed - last argument)")
self.error(msg)
else:
if self.nb_motors != 7:
angles = [mu, theta, chi, phi, gamma, delta]
else:
angles = [omega_t, mu, theta, chi, phi, gamma, delta]
self.diffrac.write_attribute("computehkl", angles)
hkl_values = self.diffrac.computehkl
self.output("h %f k %f l %f" %
(hkl_values[0], hkl_values[1], hkl_values[2]))
[docs]
class pa(Macro, _diffrac):
"""Prints information about the active diffractometer."""
suffix = ("st", "nd", "rd", "th")
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
str_type = "Eulerian 6C"
if self.type == 'E4CV':
str_type = "Eulerian 4C Vertical"
elif self.type == 'E4CH':
str_type = "Eulerian 4C Horizontal"
elif self.type == 'K6C':
str_type = "Kappa 6C"
elif self.type == 'K4CV':
str_type = "Kappa 4C Vertical"
self.output("%s Geometry (%s), %s" %
(str_type, self.type, self.diffrac.enginemode))
#self.output("Sector %s" % "[ToDo]")
self.output("")
reflections = self.diffrac.reflectionlist
nb_ref = 0
if reflections is not None:
for ref in reflections:
if nb_ref < len(self.suffix):
sf = self.suffix[nb_ref]
else:
sf = self.suffix[3]
self.output(" %d%s Reflection (index %d): " %
(nb_ref + 1, sf, ref[0]))
#self.output(" Affinement, Relevance : %d %d" % (ref[4], ref[5]))
if len(ref) > 10 and len(self.angle_names) == 6:
self.output(" %s %s %s %s %s %s: %s %s %s %s %s %s" %
(self.angle_names[5], self.angle_names[1],
self.angle_names[2], self.angle_names[3],
self.angle_names[4], self.angle_names[0],
_diffrac.fl(self, str(ref[11])),
_diffrac.fl(self, str(ref[7])),
_diffrac.fl(self, str(ref[8])),
_diffrac.fl(self, str(ref[9])),
_diffrac.fl(self, str(ref[10])),
_diffrac.fl(self, str(ref[6]))))
elif len(ref) > 10 and len(self.angle_names) == 7:
self.output(
" %s %s %s %s %s %s %s: %s %s %s %s %s %s %s" %
(self.angle_names[0], self.angle_names[1],
self.angle_names[2], self.angle_names[3],
self.angle_names[4], self.angle_names[5],
self.angle_names[6],
_diffrac.fl(self, str(ref[6])),
_diffrac.fl(self, str(ref[7])),
_diffrac.fl(self, str(ref[8])),
_diffrac.fl(self, str(ref[9])),
_diffrac.fl(self, str(ref[10])),
_diffrac.fl(self, str(ref[11])),
_diffrac.fl(self, str(ref[12]))))
else:
self.output(" %s %s %s %s: %s %s %s %s" %
(self.angle_names[0], self.angle_names[1],
self.angle_names[2], self.angle_names[3],
_diffrac.fl(self, str(ref[6])),
_diffrac.fl(self, str(ref[7])),
_diffrac.fl(self, str(ref[8])),
_diffrac.fl(self, str(ref[9]))))
nb_ref = nb_ref + 1
self.output(" %33s %s %s %s" % ("H K L =",
_diffrac.fl(
self, str(ref[1])),
_diffrac.fl(
self, str(ref[2])),
_diffrac.fl(
self, str(ref[3]))))
self.output("")
# self.output("")
self.output(" Lattice Constants (lengths / angles):")
self.output("%32s = %s %s %s / %s %s %s" % ("real space", self.diffrac.a,
self.diffrac.b, self.diffrac.c, _diffrac.fl(
self, str(self.diffrac.alpha)),
_diffrac.fl(self, str(
self.diffrac.beta)),
_diffrac.fl(self, str(
self.diffrac.gamma))))
self.output("")
self.output(" Azimuthal reference:")
self.output("%34s %s %s %s " %
("H K L =", _diffrac.fl(self, str(self.diffrac.psirefh)), _diffrac.fl(self, str(self.diffrac.psirefk)), _diffrac.fl(self, str(self.diffrac.psirefl))))
self.output("")
self.output(" Lambda = %s" % (self.diffrac.WaveLength))
lst = self.diffrac.ubmatrix
self.output(" UB-Matrix")
self.output(" %15g %15g %15g" % (lst[0][0], lst[0][1], lst[0][2]))
self.output(" %15g %15g %15g" % (lst[1][0], lst[1][1], lst[1][2]))
self.output(" %15g %15g %15g" % (lst[2][0], lst[2][1], lst[2][2]))
[docs]
class wh(Macro, _diffrac):
"""Show principal axes and reciprocal space positions.
Prints the current reciprocal space coordinates (H K L) and the user
positions of the principal motors. Depending on the diffractometer
geometry, other parameters such as the angles of incidence and
reflection (ALPHA and BETA) and the incident wavelength (LAMBDA)
may be displayed."""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.output("")
self.output("Engine: %s" % self.diffrac.engine)
self.output("")
self.output("Mode: %s" % self.diffrac.enginemode)
self.output("")
self.output("%s %s %3s %9.5f %9.5f %9.5f " %
("H", "K", "L = ", self.h_device.position,
self.k_device.position, self.l_device.position))
if self.diffrac.psirefh == -999:
self.output("")
else:
self.output("%8s %9.5f %9.5f %9.5f " %
("Ref = ", self.diffrac.psirefh, self.diffrac.psirefk, self.diffrac.psirefl))
psirefh_in = self.diffrac.psirefh
psirefk_in = self.diffrac.psirefk
psirefl_in = self.diffrac.psirefl
engine_restore = self.diffrac.engine
mode_restore = self.diffrac.enginemode
self.diffrac.write_attribute("engine", "psi")
psirefh_psi = self.diffrac.psirefh
psirefk_psi = self.diffrac.psirefk
psirefl_psi = self.diffrac.psirefl
self.diffrac.write_attribute("engine", engine_restore)
self.diffrac.write_attribute("enginemode", mode_restore)
if psirefh_in != psirefh_psi or psirefk_in != psirefk_psi or psirefl_in != psirefl_psi:
self.warning(
"Psiref vector missmatch. Calculated value corresponds to:")
self.warning("%8s %9.5f %9.5f %9.5f " %
("Ref = ", psirefh_psi, psirefk_psi, psirefl_psi))
self.warning("Use setaz for setting it consistently")
try:
self.output("%s %7.5f" % (
"Azimuth (Psi - calculated) = ", self.psidevice.Position))
except:
self.warning(
"Not able to read psi. Check if environment Psi is defined")
parameter_names = self.diffrac.modeparametersnames
if parameter_names is not None:
i = 0
for par in parameter_names:
if par == "psi":
parameter_values = self.diffrac.modeparametersvalues
self.info("%s %7.5f" %
("Azimuth (Psi - set) = ", parameter_values[i]))
i = i + 1
self.output("%s %7.5f" % ("Wavelength = ", self.diffrac.WaveLength))
self.output("")
if self.nb_motors == 6:
str_pos1 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Delta"]]).Position
str_pos2 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Theta"]]).Position
str_pos3 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Chi"]]).Position
str_pos4 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Phi"]]).Position
str_pos5 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Mu"]]).Position
str_pos6 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Gamma"]]).Position
self.output("%10s %11s %12s %11s %10s %11s" %
("Delta", "Theta", "Chi", "Phi", "Mu", "Gamma"))
self.output("%10s %11s %12s %11s %10s %11s" %
(str_pos1, str_pos2, str_pos3, str_pos4, str_pos5,
str_pos6))
elif self.nb_motors == 4:
str_pos1 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Tth"]]).Position
str_pos2 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Omega"]]).Position
str_pos3 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Chi"]]).Position
str_pos4 = "%7.5f" % self.getDevice(
self.angle_device_names[self.labelmotor["Phi"]]).Position
self.output("%10s %11s %12s %11s" %
("Tth", "Omega", "Chi", "Phi"))
self.output("%10s %11s %12s %11s" %
(str_pos1, str_pos2, str_pos3, str_pos4))
elif self.nb_motors == 7:
str_pos1 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[0]]).Position
str_pos2 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[1]]).Position
str_pos3 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[2]]).Position
str_pos4 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[3]]).Position
str_pos5 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[4]]).Position
str_pos6 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[5]]).Position
str_pos7 = "%7.5f" % self.getDevice(
self.angle_device_names[self.angle_names[6]]).Position
self.output("%10s %11s %12s %11s %11s %11s %11s" %
(self.angle_names[0],
self.angle_names[1],
self.angle_names[2],
self.angle_names[3],
self.angle_names[4],
self.angle_names[5],
self.angle_names[6]))
self.output("%10s %11s %12s %11s %11s %11s %11s" %
(str_pos1,
str_pos2,
str_pos3,
str_pos4,
str_pos5,
str_pos6,
str_pos7))
self.setEnv('Q', [self.h_device.position, self.k_device.position,
self.l_device.position, self.diffrac.WaveLength])
[docs]
class freeze(Macro, _diffrac):
""" Set psi value for psi constant modes """
param_def = [
['parameter', Type.String, None, "Parameter to freeze"],
['value', Type.Float, None, "Value to be frozen"]
]
[docs]
def prepare(self, parameter, value):
_diffrac.prepare(self)
[docs]
def run(self, parameter, value):
if parameter == "psi":
engine_restore = self.diffrac.engine
mode_restore = self.diffrac.enginemode
if mode_restore != "psi_constant_vertical" and mode_restore != "psi_constant_horizontal":
self.warning(
"Psi frozen to set value. But current mode is not set to psi_constant_vertical or psi_constant_horizontal ")
self.diffrac.write_attribute("engine", "hkl")
self.diffrac.write_attribute("enginemode", "psi_constant_vertical")
parameter_values = self.diffrac.modeparametersvalues
parameter_values[3] = value
self.diffrac.write_attribute(
"modeparametersvalues", parameter_values)
self.diffrac.write_attribute(
"enginemode", "psi_constant_horizontal")
parameter_values = self.diffrac.modeparametersvalues
parameter_values[3] = value
self.diffrac.write_attribute(
"modeparametersvalues", parameter_values)
self.diffrac.write_attribute("engine", engine_restore)
self.diffrac.write_attribute("enginemode", mode_restore)
else:
self.error("Only implemented for parameter psi. Nothing done")
[docs]
class setmode(iMacro, _diffrac):
"""Set operation mode."""
param_def = [
['new_mode', Type.Integer, -1, "Mode to be set"]
]
[docs]
def prepare(self, new_mode):
_diffrac.prepare(self)
[docs]
def run(self, new_mode):
modes = self.diffrac.enginemodelist
if new_mode == -1:
self.output("Available modes:")
imode = 1
old_mode = self.diffrac.read_attribute("enginemode").value
for mode in modes:
if mode == old_mode:
def_mode = imode
self.output(" %d -> %s " % (imode, mode))
imode = imode + 1
old_mode = self.diffrac.read_attribute("enginemode").value
self.output("")
a = self.input("Your choice?", default_value=def_mode)
imode = 1
for mode in modes:
if imode == int(a):
def_mode = imode
imode = imode + 1
self.diffrac.write_attribute("enginemode", modes[def_mode - 1])
self.output("")
self.output("Now using %s mode" % modes[def_mode - 1])
return
if new_mode > len(modes):
self.output(
"Wrong index mode -> only from 1 to %d allowed:" % len(modes))
imode = 1
for mode in modes:
self.output(" %d -> %s " % (imode, mode))
imode = imode + 1
return
else:
self.diffrac.write_attribute("enginemode", modes[new_mode - 1])
self.output("Now using %s mode" % modes[new_mode - 1])
self.execMacro('savecrystal')
[docs]
class getmode(Macro, _diffrac):
"""Get operation mode."""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.output(self.diffrac.enginemode)
[docs]
class setlat(iMacro, _diffrac):
"""Set the crystal lattice parameters a, b, c, alpha, beta and gamma
for the currently active diffraction pseudo motor controller."""
param_def = [
['a', Type.Float, -999, "Lattice 'a' parameter"],
['b', Type.Float, -999, "Lattice 'b' parameter"],
['c', Type.Float, -999, "Lattice 'c' parameter"],
['alpha', Type.Float, -999, "Lattice 'alpha' parameter"],
['beta', Type.Float, -999, "Lattice 'beta' parameter"],
['gamma', Type.Float, -999, "Lattice 'gamma' parameter"]
]
[docs]
def prepare(self, a, b, c, alpha, beta, gamma):
_diffrac.prepare(self)
[docs]
def run(self, a, b, c, alpha, beta, gamma):
if gamma == -999:
a = self.diffrac.a
b = self.diffrac.b
c = self.diffrac.c
alpha = self.diffrac.alpha
beta = self.diffrac.beta
gamma = self.diffrac.gamma
self.output("")
self.output("Enter real space lattice parameters:")
a = self.input(" Lattice a?", default_value=a,
data_type=Type.String)
b = self.input(" Lattice b?", default_value=b,
data_type=Type.String)
c = self.input(" Lattice c?", default_value=c,
data_type=Type.String)
alpha = self.input(" Lattice alpha?",
default_value=alpha, data_type=Type.String)
beta = self.input(" Lattice beta?",
default_value=beta, data_type=Type.String)
gamma = self.input(" Lattice gamma?",
default_value=gamma, data_type=Type.String)
self.output("")
self.diffrac.write_attribute("a", float(a))
self.diffrac.write_attribute("b", float(b))
self.diffrac.write_attribute("c", float(c))
self.diffrac.write_attribute("alpha", float(alpha))
self.diffrac.write_attribute("beta", float(beta))
self.diffrac.write_attribute("gamma", float(gamma))
else:
self.diffrac.write_attribute("a", a)
self.diffrac.write_attribute("b", b)
self.diffrac.write_attribute("c", c)
self.diffrac.write_attribute("alpha", alpha)
self.diffrac.write_attribute("beta", beta)
self.diffrac.write_attribute("gamma", gamma)
self.execMacro('computeub')
[docs]
class or0(Macro, _diffrac):
"""Set primary orientation reflection."""
param_def = [
['H', Type.Float, None, "H value"],
['K', Type.Float, None, "K value"],
['L', Type.Float, None, "L value"],
]
[docs]
def prepare(self, H, K, L):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L):
# Check collinearity
hkl_ref1 = _diffrac.get_hkl_ref1(self)
if len(hkl_ref1) > 1:
check = _diffrac.check_collinearity(
self, H, K, L, hkl_ref1[0], hkl_ref1[1], hkl_ref1[2])
if check:
self.warning(
"Can not orient: or0 %9.5f %9.5f %9.5f are parallel to or1" % (H, K, L))
return
values = [0, H, K, L]
self.diffrac.write_attribute("SubstituteReflection", values)
self.execMacro('computeub')
[docs]
class or1(Macro, _diffrac):
"""Set secondary orientation reflection."""
param_def = [
['H', Type.Float, None, "H value"],
['K', Type.Float, None, "K value"],
['L', Type.Float, None, "L value"],
]
[docs]
def prepare(self, H, K, L):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L):
# Check collinearity
hkl_ref0 = _diffrac.get_hkl_ref0(self)
if len(hkl_ref0) > 1:
check = _diffrac.check_collinearity(
self, hkl_ref0[0], hkl_ref0[1], hkl_ref0[2], H, K, L)
if check:
self.warning(
"Can not orient: or0 is parallel to or1 %9.5f %9.5f %9.5f" % (H, K, L))
return
values = [1, H, K, L]
self.diffrac.write_attribute("SubstituteReflection", values)
self.execMacro('computeub')
[docs]
class setor0(Macro, _diffrac):
"""Set primary orientation reflection choosing hkl and angle values.
Run it without any argument to see the order real positions"""
param_def = [
['H', Type.Float, -999, "H value"],
['K', Type.Float, -999, "K value"],
['L', Type.Float, -999, "L value"],
['ang1', Type.Float, -999, "Real position"],
['ang2', Type.Float, -999, "Real position"],
['ang3', Type.Float, -999, "Real position"],
['ang4', Type.Float, -999, "Real position"],
['ang5', Type.Float, -999, "Real position"],
['ang6', Type.Float, -999, "Real position"],
['ang7', Type.Float, -999, "Real position"],
]
[docs]
def prepare(self, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7):
setorn, pars = self.createMacro(
"setorn", 0, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7)
self.runMacro(setorn)
[docs]
class setor1(Macro, _diffrac):
"""Set secondary orientation reflection choosing hkl and angle values.
Run it without any argument to see the order real positions"""
param_def = [
['H', Type.Float, -999, "H value"],
['K', Type.Float, -999, "K value"],
['L', Type.Float, -999, "L value"],
['ang1', Type.Float, -999, "Real position"],
['ang2', Type.Float, -999, "Real position"],
['ang3', Type.Float, -999, "Real position"],
['ang4', Type.Float, -999, "Real position"],
['ang5', Type.Float, -999, "Real position"],
['ang6', Type.Float, -999, "Real position"],
['ang7', Type.Float, -999, "Real position"],
]
[docs]
def prepare(self, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7):
self.output("setor1 prepare")
self.output(ang3)
self.output(ang7)
_diffrac.prepare(self)
[docs]
def run(self, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7):
setorn, pars = self.createMacro(
"setorn", 1, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7)
self.runMacro(setorn)
[docs]
class setorn(iMacro, _diffrac):
"""Set orientation reflection indicated by the index.
Run it without any argument to see the order of the angles to be set"""
param_def = [
['ref_id', Type.Integer, None, "reflection index (starting at 0)"],
['H', Type.Float, -999, "H value"],
['K', Type.Float, -999, "K value"],
['L', Type.Float, -999, "L value"],
['ang1', Type.Float, -999, "Real position"],
['ang2', Type.Float, -999, "Real position"],
['ang3', Type.Float, -999, "Real position"],
['ang4', Type.Float, -999, "Real position"],
['ang5', Type.Float, -999, "Real position"],
['ang6', Type.Float, -999, "Real position"],
['ang7', Type.Float, -999, "Real position"],
]
[docs]
def prepare(self, ref_id, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6,
ang7):
_diffrac.prepare(self)
[docs]
def run(self, ref_id, H, K, L, ang1, ang2, ang3, ang4, ang5, ang6, ang7):
if H == -999.0:
msg = "Order of the real motor positions to be given as argument:"
self.output(msg)
for el in self.angle_names:
self.output(el)
return
if ((ang6 == -999 and self.nb_motors == 6)
or (ang4 == -999 and self.nb_motors == 4)
or (ang7 == -999 and self.nb_motors == 7)):
reflections = []
try:
reflections = self.diffrac.reflectionlist
except:
pass
tmp_ref = {}
hkl_names = ["h", "k", "l"]
if reflections is not None:
if len(reflections) > ref_id:
for i in range(1, 4):
tmp_ref[hkl_names[i - 1]] = reflections[ref_id][i]
for i in range(6, 6 + self.nb_motors):
tmp_ref[
self.angle_names[i - 6]] = reflections[ref_id][i]
else:
for i in range(0, 3):
tmp_ref[hkl_names[i]] = 0
for i in range(0, self.nb_motors):
tmp_ref[self.angle_names[i]] = 0
else:
for i in range(0, 3):
tmp_ref[hkl_names[i]] = 0
for i in range(0, self.nb_motors):
tmp_ref[self.angle_names[i]] = 0
self.output("")
if ref_id == 0:
ref_txt = "primary-reflection"
elif ref_id == 1:
ref_txt = "secondary-reflection"
else:
ref_txt = "reflection " + str(ref_id)
self.output("Enter %s angles" % ref_txt)
angles_to_set = []
for el in self.angle_names:
angles_to_set.append(
float(self.input(el+"?",
default_value=tmp_ref[el],
data_type=Type.String)
)
)
self.output("")
self.output("Enter %s HKL coordinates" % ref_txt)
H = float(self.input(" H?", default_value=tmp_ref[
"h"], data_type=Type.String))
K = float(self.input(" K?", default_value=tmp_ref[
"k"], data_type=Type.String))
L = float(self.input(" L?", default_value=tmp_ref[
"l"], data_type=Type.String))
self.output("")
else:
angles = [ang1, ang2, ang3, ang4, ang5, ang6, ang7]
angles_to_set = []
for i in range(0, self.nb_motors):
angles_to_set.append(angles[i])
# Check collinearity
if ref_id == 0:
hkl_ref = _diffrac.get_hkl_ref1(self)
if ref_id == 1:
hkl_ref = _diffrac.get_hkl_ref0(self)
if ref_id < 2:
if len(hkl_ref) > 1:
check = _diffrac.check_collinearity(
self, hkl_ref[0], hkl_ref[1], hkl_ref[2], H, K, L)
if check:
self.warning(
"Can not orient: ref0 is parallel to ref1 %9.5f %9.5f %9.5f" % (H, K, L))
return
# Set reflection
values = [ref_id, H, K, L]
self.diffrac.write_attribute("SubstituteReflection", values)
values = []
values.append(ref_id)
for el in angles_to_set:
values.append(el)
self.diffrac.write_attribute("AdjustAnglesToReflection", values)
# Recompute u
self.execMacro('computeub')
[docs]
class setaz(iMacro, _diffrac):
""" Set hkl values of the psi reference vector"""
param_def = [
['PsiH', Type.Float, -999, "H value of psi reference vector"],
['PsiK', Type.Float, -999, "K value of psi reference vector"],
['PsiL', Type.Float, -999, "L value of psi reference vector"],
]
[docs]
def prepare(self, PsiH, PsiK, PsiL):
_diffrac.prepare(self)
[docs]
def run(self, PsiH, PsiK, PsiL):
engine_restore = self.diffrac.engine
mode_restore = self.diffrac.enginemode
if PsiL == -999:
self.diffrac.write_attribute("engine", "hkl")
self.diffrac.write_attribute("enginemode", "psi_constant_vertical")
azh = self.diffrac.read_attribute("psirefh").value
azk = self.diffrac.read_attribute("psirefk").value
azl = self.diffrac.read_attribute("psirefl").value
self.output("")
self.output("Enter azimuthal reference H K L:")
a1 = self.input(" Azimuthal H?", default_value=azh,
data_type=Type.String)
a2 = self.input(" Azimuthal K?", default_value=azk,
data_type=Type.String)
a3 = self.input(" Azimuthal L?", default_value=azl,
data_type=Type.String)
PsiH = float(a1)
PsiK = float(a2)
PsiL = float(a3)
self.diffrac.write_attribute("engine", "hkl")
self.diffrac.write_attribute("enginemode", "psi_constant_vertical")
self.diffrac.write_attribute("psirefh", PsiH)
self.diffrac.write_attribute("psirefk", PsiK)
self.diffrac.write_attribute("psirefl", PsiL)
self.diffrac.write_attribute("enginemode", "psi_constant_horizontal")
self.diffrac.write_attribute("psirefh", PsiH)
self.diffrac.write_attribute("psirefk", PsiK)
self.diffrac.write_attribute("psirefl", PsiL)
self.diffrac.write_attribute("engine", "psi")
self.diffrac.write_attribute("psirefh", PsiH)
self.diffrac.write_attribute("psirefk", PsiK)
self.diffrac.write_attribute("psirefl", PsiL)
self.diffrac.write_attribute("engine", engine_restore)
self.diffrac.write_attribute("enginemode", mode_restore)
self.execMacro('savecrystal')
[docs]
class computeub(Macro, _diffrac):
""" Compute UB matrix with reflections 0 and 1 """
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
reflections = self.diffrac.reflectionlist
if reflections is not None:
if len(reflections) > 1:
self.output("Computing UB with reflections 0 and 1")
values = [0, 1]
self.diffrac.write_attribute("ComputeUB", values)
self.execMacro('savecrystal')
else:
self.warning("UB can not be computed. Only one reflection")
else:
self.warning("UB can not be computed. No reflection")
[docs]
class addreflection(Macro, _diffrac):
""" Add reflection at the botton of reflections list """
param_def = [
['H', Type.Float, None, "H value"],
['K', Type.Float, None, "K value"],
['L', Type.Float, None, "L value"],
['affinement', Type.Float, -999., "Affinement"]
]
[docs]
def prepare(self, H, K, L, affinement):
_diffrac.prepare(self)
[docs]
def run(self, H, K, L, affinement):
values = [H, K, L]
if affinement != -999.:
values.append(affinement)
self.diffrac.write_attribute("AddReflection", values)
[docs]
class affine(Macro, _diffrac):
"""Affine current crystal.
Fine tunning of lattice parameters and UB matrix based on
current crystal reflections. Reflections with affinement
set to 0 are not used. A new crystal with the post fix
(affine) is created and set as current crystal"""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.diffrac.write_attribute("AffineCrystal", 0)
[docs]
class orswap(Macro, _diffrac):
"""Swap values for primary and secondary vectors."""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.diffrac.write_attribute("SwapReflections01", 0)
self.output("Orientation vectors swapped.")
self.execMacro('computeub')
[docs]
class newcrystal(iMacro, _diffrac):
""" Create a new crystal (if it does not exist) and select it. """
param_def = [
['crystal_name', Type.String, "", 'Name of the crystal to add and select']
]
[docs]
def prepare(self, crystal_name):
_diffrac.prepare(self)
[docs]
def run(self, crystal_name):
crystal_list = self.diffrac.crystallist
to_add = 1
i = 1
if crystal_name == "":
crystal_name = self.diffrac.crystal
self.output("Available crystals:")
for crystal in crystal_list:
self.output("(%s) %s" % (i, crystal))
if crystal_name == crystal:
iselname = crystal
i = i + 1
a = self.input("New crystal?", default_value=iselname,
data_type=Type.String)
try:
a1 = int(a)
i = 1
for crystal in crystal_list:
if a1 == i:
a = crystal
i = i + 1
if a1 > i - 1:
a = iselname
except:
pass
if a != iselname:
crystal_name = a
else:
crystal_name = iselname
for crystal in crystal_list:
if crystal_name == crystal:
to_add = 0
if to_add:
self.diffrac.write_attribute("addcrystal", crystal_name)
self.diffrac.write_attribute("crystal", crystal_name)
self.output("")
self.output("Crystal selected: %s " % crystal_name)
if to_add:
a = self.input(" Lattice a?", default_value=5.43,
data_type=Type.String)
b = self.input(" Lattice b?", default_value=5.43,
data_type=Type.String)
c = self.input(" Lattice c?", default_value=5.43,
data_type=Type.String)
alpha = self.input(" Lattice alpha?",
default_value=90, data_type=Type.String)
beta = self.input(" Lattice beta?",
default_value=90, data_type=Type.String)
gamma = self.input(" Lattice gamma?",
default_value=90, data_type=Type.String)
self.output("")
self.diffrac.write_attribute("a", float(a))
self.diffrac.write_attribute("b", float(b))
self.diffrac.write_attribute("c", float(c))
self.diffrac.write_attribute("alpha", float(alpha))
self.diffrac.write_attribute("beta", float(beta))
self.diffrac.write_attribute("gamma", float(gamma))
[docs]
class hscan(aNscan, Macro, _diffrac):
"Scan h axis"
param_def = [
['start_pos', Type.Float, None, 'Scan start position'],
['final_pos', Type.Float, None, 'Scan final position'],
['nr_interv', Type.Integer, None, 'Number of scan intervals'],
['integ_time', Type.Float, None, 'Integration time'],
]
[docs]
def prepare(self, start_pos, final_pos, nr_interv, integ_time):
_diffrac.prepare(self)
aNscan._prepare(self, [self.h_device], [start_pos],
[final_pos], nr_interv, integ_time)
[docs]
class kscan(aNscan, Macro, _diffrac):
"Scan k axis"
param_def = [
['start_pos', Type.Float, None, 'Scan start position'],
['final_pos', Type.Float, None, 'Scan final position'],
['nr_interv', Type.Integer, None, 'Number of scan intervals'],
['integ_time', Type.Float, None, 'Integration time'],
]
[docs]
def prepare(self, start_pos, final_pos, nr_interv, integ_time):
_diffrac.prepare(self)
aNscan._prepare(self, [self.k_device], [start_pos],
[final_pos], nr_interv, integ_time)
[docs]
class lscan(aNscan, Macro, _diffrac):
"Scan l axis"
param_def = [
['start_pos', Type.Float, None, 'Scan start position'],
['final_pos', Type.Float, None, 'Scan final position'],
['nr_interv', Type.Integer, None, 'Number of scan intervals'],
['integ_time', Type.Float, None, 'Integration time'],
]
[docs]
def prepare(self, start_pos, final_pos, nr_interv, integ_time):
_diffrac.prepare(self)
aNscan._prepare(self, [self.l_device], [start_pos],
[final_pos], nr_interv, integ_time)
[docs]
class hklscan(aNscan, Macro, _diffrac):
"Scan h k l axes"
param_def = [
['h_start_pos', Type.Float, None, 'Scan h start position'],
['h_final_pos', Type.Float, None, 'Scan h final position'],
['k_start_pos', Type.Float, None, 'Scan k start position'],
['k_final_pos', Type.Float, None, 'Scan k final position'],
['l_start_pos', Type.Float, None, 'Scan l start position'],
['l_final_pos', Type.Float, None, 'Scan l final position'],
['nr_interv', Type.Integer, None, 'Number of scan intervals'],
['integ_time', Type.Float, None, 'Integration time'],
]
[docs]
def prepare(self, h_start_pos, h_final_pos, k_start_pos, k_final_pos, l_start_pos, l_final_pos, nr_interv, integ_time):
_diffrac.prepare(self)
aNscan._prepare(self, [self.h_device, self.k_device, self.l_device],
[h_start_pos, k_start_pos, l_start_pos], [h_final_pos,
k_final_pos,
l_final_pos],
nr_interv, integ_time)
[docs]
class th2th(Macro):
"""th2th - scan:
Relative scan around current position in del and th with d_th=2*d_delta
"""
param_def = [
['rel_start_pos', Type.Float, -999, 'Scan start position'],
['rel_final_pos', Type.Float, -999, 'Scan final position'],
['nr_interv', Type.Integer, -999, 'Number of scan intervals'],
['integ_time', Type.Float, -999, 'Integration time']
]
[docs]
def run(self, rel_start_pos, rel_final_pos, nr_interv, integ_time):
if ((integ_time != -999)):
motor_del = self.getObj("del")
motor_th = self.getObj("th")
pos_del = motor_del.getPosition()
pos_th = motor_th.getPosition()
scan = self.d2scan(motor_del, rel_start_pos, rel_final_pos,
motor_th, rel_start_pos / 2, rel_final_pos / 2,
nr_interv, integ_time)
else:
self.output(
"Usage: th2th tth_start_rel tth_stop_rel intervals time")
count_scan = 1
class HookPars:
pass
def hook_pre_move(self, hook_pars):
global count_scan
self.execMacro('freeze', 'psi', hook_pars.psi_save + +
hook_pars.angle_start + (count_scan - 1) * hook_pars.angle_interv)
self.execMacro('ubr', hook_pars.h, hook_pars.k, hook_pars.l)
count_scan = count_scan + 1
class luppsi(Macro, _diffrac):
"""psi scan:
Relative scan psi angle
[TODO] Still not tested
"""
param_def = [
['rel_start_angle', Type.Float, -999, 'Relative start scan angle'],
['rel_final_angle', Type.Float, -999, 'Relative final scan angle'],
['nr_interv', Type.Integer, -999, 'Number of scan intervals'],
['integ_time', Type.Float, -999, 'Integration time']
]
def prepare(self, H, K, L, AnglesIndex):
_diffrac.prepare(self)
def run(self, rel_start_angle, rel_final_angle, nr_interv, integ_time):
global count_scan
count_scan = 1
if ((integ_time != -999)):
self.diffrac.write_attribute("engine", "hkl")
self.diffrac.write_attribute("enginemode", "psi_constant_vertical")
h = self.h_device.position
k = self.k_device.position
l = self.l_device.position
psi_positions = []
try:
psi_save = self.psidevice.Position
except:
self.error(
"Not able to read psi. Check if environment Psi is defined")
return
angle_interv = abs(rel_final_angle - rel_start_angle) / nr_interv
# Construct scan macro
self.output(self.psidevice.alias())
psi_motor = self.getMotor(self.psidevice.alias())
self.output(psi_motor)
macro, pars = self.createMacro('dscan %s %f %f %d %f ' %
(self.psidevice.alias(), rel_start_angle, rel_final_angle, nr_interv, integ_time))
# Parameters for scan hook function
hook_pars = HookPars()
hook_pars.psi_save = psi_save
hook_pars.angle_interv = angle_interv
hook_pars.angle_start = rel_start_angle
hook_pars.h = h
hook_pars.k = k
hook_pars.l = l
f = lambda: hook_pre_move(self, hook_pars)
macro.hooks = [
(f, ["pre-move"]),
]
# Start the scan
self.runMacro(macro)
# Return to start position
self.info("Return to start position " + str(psi_save))
self.execMacro('freeze', 'psi', psi_save)
self.execMacro('ubr', h, k, l)
self.psidevice.write_attribute("Position", psi_save)
else:
self.output(
"Usage: luppsi rel_startangle rel_stopangle n_intervals time")
[docs]
class savecrystal(Macro, _diffrac):
"""
Save crystal information to file
"""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.info("Be aware: changes in crystal file format are still possible.")
self.diffrac.write_attribute("SaveCrystal", 1)
[docs]
class loadcrystal(iMacro, _diffrac):
"""
Load crystal information from file
"""
[docs]
def prepare(self):
_diffrac.prepare(self)
[docs]
def run(self):
self.info("Be aware: changes in crystal file format are still possible.")
active_dir = ""
try:
files = os.listdir(os.path.expanduser('~') + '/crystals/')
active_dir = os.path.expanduser('~') + '/crystals/'
except:
self.output(
"Directory for loading files %s/crystals does not exist" % os.path.expanduser('~'))
newdir = self.input("Type new directory")
try:
files = os.listdir(newdir)
active_dir = newdir
except:
self.output("New directory %s not found" % newdir)
return
res = [x for x in files if x.endswith('.txt')]
if len(res) == 0:
self.output("No crystals available in set directory. Nothing done")
return
i = 1
for filename in res:
filename = filename.split('.')[0]
self.output("(%s) %s" % (i, filename))
i = i + 1
a0 = self.input("Your choice? ")
try:
a1 = int(a0)
i = 1
for filename in res:
if i == int(a0) and i < len(res) + 1:
file = filename
i = i + 1
if a1 < len(res) + 1:
self.output("")
self.output("File to load %s" % active_dir + file)
else:
self.output("Input out of range!")
self.diffrac.write_attribute("loadcrystal", active_dir + file)
self.diffrac.read_attribute("loadcrystal")
except:
if a0 != "":
self.output("Wrong input!")
else:
self.output("An input file has to be given. Nothing done")
[docs]
class latticecal(iMacro, _diffrac):
"""
Calibrate lattice parameters a, b or c to current 2theta value
"""
param_def = [
["parameter", Type.String, "", "Parameter"],
]
[docs]
def prepare(self, parameter):
_diffrac.prepare(self)
[docs]
def run(self, parameter):
if parameter != "":
if parameter == "a" or parameter == "b" or parameter == "c":
if parameter == "a":
a0 = self.diffrac.a
self.output("Old lattice parameter %s = %s" %
(parameter, a0))
h0 = self.h_device.position
h1 = py2_round(h0) # TODO: check if round would be fine?
a1 = h1 / h0 * a0
self.output("New lattice parameter %s = %s" %
(parameter, a1))
self.diffrac.write_attribute("a", a1)
if parameter == "b":
a0 = self.diffrac.b
self.output("Old lattice parameter %s = %s" %
(parameter, a0))
h0 = self.k_device.position
h1 = py2_round(h0) # TODO: check if round would be fine?
a1 = h1 / h0 * a0
self.output("New lattice parameter %s = %s" %
(parameter, a1))
self.diffrac.write_attribute("b", a1)
if parameter == "c":
a0 = self.diffrac.c
self.output("Old lattice parameter %s = %s" %
(parameter, a0))
h0 = self.l_device.position
h1 = py2_round(h0) # TODO: check if round would be fine?
a1 = h1 / h0 * a0
self.output("New lattice parameter %s = %s" %
(parameter, a1))
self.diffrac.write_attribute("c", a1)
self.execMacro('computeub')
else:
self.output("Lattice parameter a, b or c")
else:
self.output(
"Calibration of lattice parameters a, b or c to current 2theta value")
self.output("usage: latticecal parameter")
class _blockprintmove(Macro, _diffrac):
"""This macro is internal and reserved to the hkl infrastucture
"""
param_def = [
['flagprint', Type.Integer, 0, '1 for printing']
]
def prepare(self, flagprint):
_diffrac.prepare(self)
def run(self, flagprint):
moving = 1
tmp_dev = {}
for angle in self.angle_names:
tmp_dev[angle] = self.getDevice(self.angle_device_names[angle])
while(moving):
moving = 0
for angle in self.angle_names:
angle_state = tmp_dev[angle].stateObj.read().rvalue
if angle_state == 6:
moving = 1
if flagprint == 1:
self.outputBlock(" %7.5f %7.5f %7.5f" % (
self.h_device.position, self.k_device.position, self.l_device.position))
self.flushOutput()
self.checkPoint()
time.sleep(1.0)
if flagprint == 1:
self.outputBlock(" %7.5f %7.5f %7.5f" % (
self.h_device.position, self.k_device.position, self.l_device.position))
self.flushOutput()
class _diff_scan(Macro):
"""Perfoms an scan keeping the data for further analysis/moves.
This macro is internal and reserved to the hkl infrastucture.
"""
param_def = [
['motor', Type.Motor, None, 'Motor to move'],
['start_pos', Type.Float, None, 'Scan start position'],
['final_pos', Type.Float, None, 'Scan final position'],
['nr_interv', Type.Integer, None, 'Number of scan intervals'],
['integ_time', Type.Float, None, 'Integration time'],
['channel', Type.ExpChannel, None, 'Channel to analize']
]
def run(self, motor, start_pos, final_pos, nr_interv, integ_time, channel):
ascan, pars = self.createMacro(
"ascan", motor, start_pos, final_pos, nr_interv, integ_time)
self.runMacro(ascan)
channel_fullname = channel.getFullName()
motor_name = motor.getName()
arr_data = []
arr_motpos = []
for record in ascan.data.records:
record_data = record.data
arr_data.append(record_data[channel_fullname])
arr_motpos.append(record_data[motor_name])
# Find motor position corresponding to the maximum of channel values
idx_max = np.argmax(arr_data)
pos_max = arr_motpos[idx_max]
self.output("Position to move")
self.output(pos_max)