"""
TITLE
MultiplePositions Hardware Object
DESCRIPTION
This object manages the movement of several motors to predefined positions.
<username> : name of the multiplepositions object
<mode> : there is two ways of managing the change of predefined positions
absolute: change the value of a predefined position by another
absolute position
relative: do not change the absolute value of the predefined
position but the user value of the motors concerned
<motors>
<object role="role1" ... :list of motors to be moved to reach a predefined
<object role="role2" ... position. the "role" will be used to referenced
... the motors in the definitions of the predefined
<motors> positions
<deltas> : for each motor you define the windows used to
<role1>val1</role1> determine that a motor as reach a position
<role2>val2</role2>
...
</deltas>
<positions>
<position>
<name> : name of a predefined position. Must be unique in the file
<role1>val1 : position of the motor "role1" for the predefined position
"name"
<role2>val2 : position of the motor "role2" for the predefined position
"name"
<resoy>8.69565217391e-07</resoy> : for all the position, independent
<beamx>100</beamx> value with keyword can be added,
saved, read ...
</position>
...
</position>
METHOD
name: get_state
input par.: None
output par.: state
description: return an and on the state of all the motor used in the
object
name: moveToPosition
input par.: name
output par.: None
description: move all motors to the predefined position "position"
name: get_value
input par.: None
output par.: position
description: return the name of the current predefined position.
return None if all motors are not in their psotion
name: setNewPositions
input par.: name, newPositions
output par.: None
description: For the position "name", change the motors positions set
in "newPositions", a dictionary with motor role as keys
and new motor position as values.
Save the new values in the xml file
name: getPositionKeyValue
input par.: name, key
output par.: value
description: return the value of the independent "key" field of
the predefined position "name"
name: setPositionKeyValue
input par.: name, key, value
output par.: None
description: Change in the object and in the xml file the value of the
independent field "key" in the predefined position "name"
name: getRoles
input par.: None
output par.: roles[]
description: return the list of motor's role used in the objects
SIGNAL
name: stateChanged
parameter: state
description: send the new state of the object when it changes
name: noPosition
parameter: None
description: sent when after a position change of any of the motor
the object is not in any of the predefined positions
name: positionReached
parameter: positionName
description: sent when after a position change of any of the motor
the object has reach a predefined position.
The parameter is the name of this position.
TEMPLATE
<object class="MultiplePositions">
<username>VLM Zoom</username>
<mode>absolute</mode>
<motors>
<object role="zoom" hwrid="/berru/zoom"></object>
</motors>
<deltas>
<zoom>0.1</zoom>
</deltas>
<positions>
<position>
<name>1X</name>
<zoom>0</zoom>
<resox>-4.16666666667e-07</resox>
<resoy>7.35294117647e-07</resoy>
<beamx>537</beamx>
<beamy>313</beamy>
</position>
<position>
<name>6X</name>
<zoom>1</zoom>
<resox>-5.52486187845e-07</resox>
<resoy>8.69565217391e-07</resoy>
<beamx>100</beamx>
<beamy>100</beamy>
</position>
<position>
<name>12X</name>
<zoom>2</zoom>
<resox>0.0000004</resox>
<resoy>0.0000004</resoy>
<beamx>200</beamx>
<beamy>200</beamy>
</position>
</positions>
</object>"""
try:
from xml.etree import cElementTree # python2.5
except ImportError:
import cElementTree
import logging
from mxcubecore.BaseHardwareObjects import HardwareObject
[docs]class MultiplePositions(HardwareObject):
[docs] def init(self):
try:
self.mode
except AttributeError:
self.mode = "absolute"
motors = self["motors"]
self.roles = motors.get_roles()
self.deltas = {}
try:
# WARNING self.deltas is a LINK to the INTERNAL properties dictionary
# modifying it modifies the GLOBAL properties, not just the local copy
# Maybe do self["deltas"].get_properties().copy()?
self.deltas = self["deltas"].get_properties()
except Exception:
logging.getLogger().error("No deltas.")
self.positions = {}
self.positionsIndex = []
try:
positions = self["positions"]
except Exception:
logging.getLogger().error("No positions.")
else:
for position in positions:
name = position.get_property("name")
if name is not None:
self.positionsIndex.append(name)
self.positions[name] = {}
motpos = position.get_properties()
motroles = list(motpos.keys())
for role in self.roles:
self.positions[name][role] = motpos[role]
else:
logging.getLogger().error("No name for position.")
self.motors = {}
for mot in self["motors"]:
self.motors[mot.get_motor_mnemonic()] = mot
self.connect(mot, "moveDone", self.checkPosition)
self.connect(mot, "valueChanged", self.checkPosition)
self.connect(mot, "stateChanged", self.stateChanged)
[docs] def get_state(self):
if not self.is_ready():
return ""
state = "READY"
for mot in self.motors.values():
if mot.get_state() == mot.MOVING:
state = "MOVING"
elif mot.get_state() == mot.UNUSABLE:
return "UNUSABLE"
return state
def stateChanged(self, state):
self.emit("stateChanged", (self.get_state(),))
self.checkPosition()
def moveToPosition(self, name, wait=False):
move_list = []
for role in self.roles:
device = self.get_deviceby_role(role)
pos = self.positions[name][role]
move_list.append((device, pos))
for mot, pos in move_list:
if mot is not None:
mot.set_value(pos)
if wait:
[mot.waitEndOfMove() for mot, pos in move_list if mot is not None]
"""
for mne,pos in self.positions[name].items():
self.motors[mne].set_value(pos)
"""
def get_value(self):
if not self.is_ready():
return None
for posName, position in self.positions.items():
findPosition = 0
for role in self.roles:
pos = position[role]
mot = self.get_deviceby_role(role)
if mot is not None:
motpos = mot.get_value()
try:
if (
motpos < pos + self.deltas[role]
and motpos > pos - self.deltas[role]
):
findPosition += 1
except Exception:
continue
if findPosition == len(self.roles):
return posName
return None
def checkPosition(self, *args):
if not self.is_ready():
return None
posName = self.get_value()
if posName is None:
self.emit("noPosition", ())
return None
else:
self.emit("positionReached", (posName,))
return posName
def setNewPositions(self, name, newPositions):
position = self.__getPositionObject(name)
if position is None:
self.checkPosition()
return
for role, pos in list(newPositions.items()):
self.positions[name][role] = pos
position.setProperty(role, pos)
self.checkPosition()
self.commit_changes()
def getPositionKeyValue(self, name, key):
position = self.__getPositionObject(name)
if position is None:
return None
return position.get_property(key)
def setPositionKeyValue(self, name, key, value):
xml_tree = cElementTree.fromstring(self.xml_source())
positions = xml_tree.find("positions")
pos_list = positions.findall("position")
for pos in pos_list:
if pos.find("name").text == name:
if pos.find(key) is not None:
position = self.__getPositionObject(name)
position.setProperty(key, str(value))
self.commit_changes()
return True
else:
key_el = cElementTree.SubElement(pos, key)
key_el.text = value
print((cElementTree.tostring(xml_tree)))
self.rewrite_xml(cElementTree.tostring(xml_tree))
return True
return False
def __getPositionObject(self, name):
for position in self["positions"]:
if position.get_property("name") == name:
return position
return None
def getRoles(self):
return self.roles
def addPosition(self, el_dict):
xml_tree = cElementTree.fromstring(self.xml_source())
positions = xml_tree.find("positions")
pos = cElementTree.SubElement(positions, "position")
for key, val in el_dict.items():
sel = cElementTree.SubElement(pos, key)
sel.text = val
self.rewrite_xml(cElementTree.tostring(xml_tree))
def remPosition(self, name):
xml_tree = cElementTree.fromstring(self.xml_source())
positions = xml_tree.find("positions")
pos_list = positions.findall("position")
for pos in pos_list:
if pos.find("name").text == name:
positions.remove(pos)
self.rewrite_xml(cElementTree.tostring(xml_tree))
def addField(self, name, key, val):
pass
def remField(self, name, key):
pass
"""
xml_tree = cElementTree.fromstring(self.xml_source())
for elt in xml_tree.findall(".//position"):
if elt.find("name").text=="12X":
new_elt = cElementTree.Element("bidule")
new_elt.text = "HELLO"
elt.append(new_elt)
self.rewrite_xml(cElementTree.tostring(xml_tree))
"""