summaryrefslogtreecommitdiff
path: root/src/sardana/pool/poolacquisition.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/sardana/pool/poolacquisition.py')
-rw-r--r--src/sardana/pool/poolacquisition.py558
1 files changed, 0 insertions, 558 deletions
diff --git a/src/sardana/pool/poolacquisition.py b/src/sardana/pool/poolacquisition.py
deleted file mode 100644
index 9833ce3c..00000000
--- a/src/sardana/pool/poolacquisition.py
+++ /dev/null
@@ -1,558 +0,0 @@
-#!/usr/bin/env python
-
-##############################################################################
-##
-## 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/>.
-##
-##############################################################################
-
-"""This module is part of the Python Pool libray. It defines the class for an
-acquisition"""
-
-__all__ = ["AcquisitionState", "AcquisitionMap", "PoolCTAcquisition",
- "Pool0DAcquisition", "Channel", "PoolIORAcquisition"]
-
-__docformat__ = 'restructuredtext'
-
-import time
-
-from taurus.core.util.log import DebugIt
-from taurus.core.util.enumeration import Enumeration
-
-from sardana import State, ElementType, TYPE_TIMERABLE_ELEMENTS
-from sardana.sardanathreadpool import get_thread_pool
-from sardana.pool.poolaction import ActionContext, PoolActionItem, PoolAction
-
-#: enumeration representing possible motion states
-AcquisitionState = Enumeration("AcquisitionState", (\
- "Stopped",
-# "StoppedOnError",
-# "StoppedOnAbort",
- "Acquiring",
- "Invalid"))
-
-AS = AcquisitionState
-AcquiringStates = AS.Acquiring,
-StoppedStates = AS.Stopped, #MS.StoppedOnError, MS.StoppedOnAbort
-
-AcquisitionMap = {
- #AS.Stopped : State.On,
- AS.Acquiring : State.Moving,
- AS.Invalid : State.Invalid,
-}
-
-class PoolAcquisition(PoolAction):
-
- def __init__(self, main_element, name="Acquisition"):
- PoolAction.__init__(self, main_element, name)
- ctname = name + ".CTAcquisition"
- zerodname = name + ".0DAcquisition"
- self._0d_acq = zd_acq = Pool0DAcquisition(main_element, name=zerodname)
- self._ct_acq = PoolCTAcquisition(main_element, name=ctname, slaves=(zd_acq,))
-
- def run(self, *args, **kwargs):
- n = kwargs.get('multiple', 1)
- if n == 1:
- return self._run_single(*args, **kwargs)
- return self._run_multiple(*args, **kwargs)
-
- def _run_multiple(self, *args, **kwargs):
- n = kwargs['multiple']
- synch = kwargs.get("synch", False)
- if synch:
- for _ in range(n):
- self._run_single(self, *args, **kwargs)
- else:
- kwargs["synch"] = True
- get_thread_pool().add(self._run_multiple, None, *args, **kwargs)
-
- def _run_single(self, *args, **kwargs):
- """Runs this action"""
- synch = kwargs.get("synch", False)
- ct_acq = self._ct_acq
- zd_acq = self._0d_acq
- if synch:
- ct_acq.run(*args, **kwargs)
- else:
- ct_acq.run(*args, **kwargs)
- zd_acq.run(*args, **kwargs)
-
- def _get_acq_for_element(self, element):
- elem_type = element.get_type()
- if elem_type in TYPE_TIMERABLE_ELEMENTS:
- return self._ct_acq
- elif elem_type == ElementType.ZeroDExpChannel:
- return self._0d_acq
-
- def clear_elements(self):
- """Clears all elements from this action"""
-
- def add_element(self, element):
- """Adds a new element to this action.
-
- :param element: the new element to be added
- :type element: sardana.pool.poolelement.PoolElement"""
- return self._get_acq_for_element(element).add_element(element)
-
- def remove_element(self, element):
- """Removes an element from this action. If the element is not part of
- this action, a ValueError is raised.
-
- :param element: the new element to be removed
- :type element: sardana.pool.poolelement.PoolElement
-
- :raises: ValueError"""
- return self._get_acq_for_element(element).add_element(element)
-
- def get_elements(self, copy_of=False):
- """Returns a sequence of all elements involved in this action.
-
- :param copy_of: If False (default) the internal container of elements is
- returned. If True, a copy of the internal container is
- returned instead
- :type copy_of: bool
- :return: a sequence of all elements involved in this action.
- :rtype: seq<sardana.pool.poolelement.PoolElement>"""
- return self._ct_acq.get_elements() + self._0d_acq.get_elements()
-
- def get_pool_controller_list(self):
- """Returns a list of all controller elements involved in this action.
-
- :return: a list of all controller elements involved in this action.
- :rtype: list<sardana.pool.poolelement.PoolController>"""
- return self._pool_ctrl_list
-
- def get_pool_controllers(self):
- """Returns a dict of all controller elements involved in this action.
-
- :return: a dict of all controller elements involved in this action.
- :rtype: dict<sardana.pool.poolelement.PoolController, seq<sardana.pool.poolelement.PoolElement>>"""
- ret = {}
- ret.update(self._ct_acq.get_pool_controllers())
- ret.update(self._0d_acq.get_pool_controllers())
- return ret
-
- def read_value(self, ret=None, serial=False):
- """Reads value information of all elements involved in this action
-
- :param ret: output map parameter that should be filled with value
- information. If None is given (default), a new map is
- created an returned
- :type ret: dict
- :param serial: If False (default) perform controller HW value requests
- in parallel. If True, access is serialized.
- :type serial: bool
- :return: a map containing value information per element
- :rtype: dict<:class:~`sardana.pool.poolelement.PoolElement`,
- :class:~`sardana.sardanavalue.SardanaValue`>"""
- ret = self._ct_acq.read_value(ret=ret, serial=serial)
- ret.update(self._0d_acq.read_value(ret=ret, serial=serial))
- return ret
-
-
-class Channel(PoolActionItem):
-
- def __init__(self, acquirable, info=None):
- PoolActionItem.__init__(self, acquirable)
- if info:
- self.__dict__.update(info)
-
- def __getattr__(self, name):
- return getattr(self.element, name)
-
-
-class PoolCTAcquisition(PoolAction):
-
- def __init__(self, main_element, name="CTAcquisition", slaves=None):
- self._channels = None
-
- if slaves is None:
- slaves = ()
- self._slaves = slaves
-
- PoolAction.__init__(self, main_element, name)
-
- def get_read_value_loop_ctrls(self):
- return self._pool_ctrl_dict_loop
-
- def start_action(self, *args, **kwargs):
- """Prepares everything for acquisition and starts it.
-
- :param: config"""
-
- pool = self.pool
-
- # prepare data structures
- self._aborted = False
- self._stopped = False
-
- self._acq_sleep_time = kwargs.pop("acq_sleep_time",
- pool.acq_loop_sleep_time)
- self._nb_states_per_value = \
- kwargs.pop("nb_states_per_value",
- pool.acq_loop_states_per_value)
-
- self._integ_time = integ_time = kwargs.get("integ_time")
- self._mon_count = mon_count = kwargs.get("monitor_count")
- if integ_time is None and mon_count is None:
- raise Exception("must give integration time or monitor counts")
- if integ_time is not None and mon_count is not None:
- raise Exception("must give either integration time or monitor counts (not both)")
-
- _ = kwargs.get("items", self.get_elements())
- cfg = kwargs['config']
-
- # determine which is the controller which holds the master channel
-
- if integ_time is not None:
- master_key = 'timer'
- master_value = integ_time
- if mon_count is not None:
- master_key = 'monitor'
- master_value = -mon_count
-
- master = cfg[master_key]
- master_ctrl = master.controller
-
- pool_ctrls_dict = dict(cfg['controllers'])
- pool_ctrls_dict.pop('__tango__', None)
- pool_ctrls = []
- self._pool_ctrl_dict_loop = _pool_ctrl_dict_loop = {}
- for ctrl, v in pool_ctrls_dict.items():
- if ctrl.is_timerable():
- pool_ctrls.append(ctrl)
- if ElementType.CTExpChannel in ctrl.get_ctrl_types():
- _pool_ctrl_dict_loop[ctrl] = v
-
- # make sure the controller which has the master channel is the last to
- # be called
- pool_ctrls.remove(master_ctrl)
- pool_ctrls.append(master_ctrl)
-
- # Determine which channels are active
- self._channels = channels = {}
- for pool_ctrl in pool_ctrls:
- ctrl = pool_ctrl.ctrl
- pool_ctrl_data = pool_ctrls_dict[pool_ctrl]
- main_unit_data = pool_ctrl_data['units']['0']
- elements = main_unit_data['channels']
-
- for element, element_info in elements.items():
- axis = element.axis
- channel = Channel(element, info=element_info)
- channels[element] = channel
-
- #for channel in channels:
- # channel.prepare_to_acquire(self)
-
- with ActionContext(self):
-
- # PreLoadAll, PreLoadOne, LoadOne and LoadAll
- for pool_ctrl in pool_ctrls:
- ctrl = pool_ctrl.ctrl
- pool_ctrl_data = pool_ctrls_dict[pool_ctrl]
- main_unit_data = pool_ctrl_data['units']['0']
- ctrl.PreLoadAll()
- master = main_unit_data[master_key]
- axis = master.axis
- res = ctrl.PreLoadOne(axis, master_value)
- if not res:
- raise Exception("%s.PreLoadOne(%d) returns False" % (pool_ctrl.name, axis,))
- ctrl.LoadOne(axis, master_value)
- ctrl.LoadAll()
-
- # PreStartAll on all controllers
- for pool_ctrl in pool_ctrls:
- pool_ctrl.ctrl.PreStartAll()
-
- # PreStartOne & StartOne on all elements
- for pool_ctrl in pool_ctrls:
- ctrl = pool_ctrl.ctrl
- pool_ctrl_data = pool_ctrls_dict[pool_ctrl]
- main_unit_data = pool_ctrl_data['units']['0']
- elements = main_unit_data['channels']
- for element in elements:
- axis = element.axis
- channel = channels[element]
- if channel.enabled:
- ret = ctrl.PreStartOne(axis, master_value)
- if not ret:
- raise Exception("%s.PreStartOne(%d) returns False" \
- % (pool_ctrl.name, axis))
- ctrl.StartOne(axis, master_value)
-
- # set the state of all elements to and inform their listeners
- for channel in channels:
- channel.set_state(State.Moving, propagate=2)
-
- # StartAll on all controllers
- for pool_ctrl in pool_ctrls:
- pool_ctrl.ctrl.StartAll()
-
- def in_acquisition(self, states):
- """Determines if we are in acquisition or if the acquisition has ended
- based on the current unit trigger modes and states returned by the
- controller(s)
-
- :param states: a map containing state information as returned by
- read_state_info
- :type states: dict<PoolElement, State>
- :return: returns True if in acquisition or False otherwise
- :rtype: bool"""
- for elem in states:
- s = states[elem][0][0]
- if self._is_in_action(s):
- return True
-
- def action_loop(self):
- i = 0
-
- states, values = {}, {}
- for element in self._channels:
- states[element] = None
- #values[element] = None
-
- nap = self._acq_sleep_time
- nb_states_per_value = self._nb_states_per_value
-
- # read values to send a first event when starting to acquire
- with ActionContext(self):
- self.raw_read_value_loop(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value, propagate=2)
-
- while True:
- self.read_state_info(ret=states)
-
- if not self.in_acquisition(states):
- break
-
- # read value every n times
- if not i % nb_states_per_value:
- self.read_value_loop(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value)
-
- time.sleep(nap)
- i += 1
-
- for slave in self._slaves:
- try:
- slave.stop_action()
- except:
- self.warning("Unable to stop slave acquisition %s",
- slave.getLogName())
- self.debug("Details", exc_info=1)
-
- with ActionContext(self):
- self.raw_read_state_info(ret=states)
- self.raw_read_value_loop(ret=values)
-
- for acquirable, state_info in states.items():
- # first update the element state so that value calculation
- # that is done after takes the updated state into account
- acquirable.set_state_info(state_info, propagate=0)
- if acquirable in values:
- value = values[acquirable]
- acquirable.put_value(value, propagate=2)
- with acquirable:
- acquirable.clear_operation()
- state_info = acquirable._from_ctrl_state_info(state_info)
- acquirable.set_state_info(state_info, propagate=2)
-
-
-class Pool0DAcquisition(PoolAction):
-
- def __init__(self, main_element, name="0DAcquisition"):
- self._channels = None
- PoolAction.__init__(self, main_element, name)
-
- def start_action(self, *args, **kwargs):
- """Prepares everything for acquisition and starts it.
-
- :param: config"""
-
- pool = self.pool
-
- # prepare data structures
- self._aborted = False
- self._stopped = False
-
- self._acq_sleep_time = kwargs.pop("acq_sleep_time",
- pool.acq_loop_sleep_time)
- self._nb_states_per_value = \
- kwargs.pop("nb_states_per_value",
- pool.acq_loop_states_per_value)
-
- integ_time = kwargs.get("integ_time")
- mon_count = kwargs.get("monitor_count")
- if integ_time is None and mon_count is None:
- raise Exception("must give integration time or monitor counts")
- if integ_time is not None and mon_count is not None:
- raise Exception("must give either integration time or monitor counts (not both)")
-
- items = kwargs.get("items")
- if items is None:
- items = self.get_elements()
- cfg = kwargs['config']
-
- pool_ctrls_dict = dict(cfg['controllers'])
- pool_ctrls_dict.pop('__tango__', None)
- pool_ctrls = []
- for ctrl in pool_ctrls_dict:
- if ElementType.ZeroDExpChannel in ctrl.get_ctrl_types():
- pool_ctrls.append(ctrl)
-
- # Determine which channels are active
- self._channels = channels = {}
- for pool_ctrl in pool_ctrls:
- ctrl = pool_ctrl.ctrl
- pool_ctrl_data = pool_ctrls_dict[pool_ctrl]
- main_unit_data = pool_ctrl_data['units']['0']
- elements = main_unit_data['channels']
-
- for element, element_info in elements.items():
- channel = Channel(element, info=element_info)
- channels[element] = channel
-
- with ActionContext(self):
- # set the state of all elements to and inform their listeners
- for channel in channels:
- channel.clear_buffer()
- channel.set_state(State.Moving, propagate=2)
-
- def in_acquisition(self, states):
- """Determines if we are in acquisition or if the acquisition has ended
- based on the current unit trigger modes and states returned by the
- controller(s)
-
- :param states: a map containing state information as returned by
- read_state_info
- :type states: dict<PoolElement, State>
- :return: returns True if in acquisition or False otherwise
- :rtype: bool"""
- for state in states:
- s = states[state][0]
- if self._is_in_action(s):
- return True
-
- def action_loop(self):
- i = 0
-
- states, values = {}, {}
- for element in self._channels:
- states[element] = None
- values[element] = None
-
- nap = self._acq_sleep_time
- while not (self._stopped or self._aborted):
- self.read_value(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value)
-
- i += 1
- time.sleep(nap)
-
- with ActionContext(self):
- self.raw_read_state_info(ret=states)
-
- for acquirable, state_info in states.items():
- # first update the element state so that value calculation
- # that is done after takes the updated state into account
- state_info = acquirable._from_ctrl_state_info(state_info)
- acquirable.set_state_info(state_info, propagate=0)
- with acquirable:
- acquirable.clear_operation()
- acquirable.set_state_info(state_info, propagate=2)
-
- def stop_action(self, *args, **kwargs):
- """Stop procedure for this action."""
- self._stopped = True
-
- def abort_action(self, *args, **kwargs):
- """Aborts procedure for this action"""
- self._aborted = True
-
-
-class PoolIORAcquisition(PoolAction):
-
- def __init__(self, pool, name="IORAcquisition"):
- self._channels = None
- PoolAction.__init__(self, pool, name)
-
- def start_action(self, *args, **kwargs):
- pass
-
- def in_acquisition(self, states):
- return True
- pass
-
- @DebugIt()
- def action_loop(self):
- i = 0
-
- states, values = {}, {}
- for element in self._channels:
- states[element] = None
- values[element] = None
-
- # read values to send a first event when starting to acquire
- self.read_value(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value, propagate=2)
-
- while True:
- self.read_state_info(ret=states)
-
- if not self.in_acquisition(states):
- break
-
- # read value every n times
- if not i % 5:
- self.read_value(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value)
-
- i += 1
- time.sleep(0.01)
-
- self.read_state_info(ret=states)
-
- # first update the element state so that value calculation
- # that is done after takes the updated state into account
- for acquirable, state_info in states.items():
- acquirable.set_state_info(state_info, propagate=0)
-
- # Do NOT send events before we exit the OperationContext, otherwise
- # we may be asked to start another action before we leave the context
- # of the current action. Instead, send the events in the finish hook
- # which is executed outside the OperationContext
-
- def finish_hook(*args, **kwargs):
- # read values and propagate the change to all listeners
- self.read_value(ret=values)
- for acquirable, value in values.items():
- acquirable.put_value(value, propagate=2)
-
- # finally set the state and propagate to all listeners
- for acquirable, state_info in states.items():
- acquirable.set_state_info(state_info, propagate=2)
-
- self.set_finish_hook(finish_hook)