Пример #1
0
    def run(self, *args, **kwargs):
        """Runs this action"""

        self._running = True
        synch = kwargs.pop("synch", False)

        if synch:
            try:
                with self.OperationContextClass(self) as context:
                    self.start_action(*args, **kwargs)
                    self._started = False
                    self.action_loop()
            finally:
                self._started = False
                self._running = False
        else:
            context = self.OperationContextClass(self)
            context.enter()
            try:
                self.start_action(*args, **kwargs)
            except:
                context.exit()
                self._running = False
                raise
            finally:
                self._started = False
            cb = kwargs.pop("cb", None)
            get_thread_pool().add(self._asynch_action_loop, cb, context)
Пример #2
0
    def meas_cont_acquisition(self, config, synchronization, moveable=None,
                              second_config=None):
        """Executes measurement using the measurement group.
        Checks the lengths of the acquired data.
        """
        jobs_before = get_thread_pool().qsize
        channel_names = self.prepare_meas(config)
        self.pmg.set_synchronization(synchronization)
        self.pmg.set_moveable(moveable, to_fqdn=False)
        repetitions = 0
        for group in synchronization:
            repetitions += group[SynchParam.Repeats]
        self.prepare_attribute_listener()
        self.acquire()
        self.acq_asserts(channel_names, repetitions)

        if second_config is not None:
            self.consecutive_acquisitions(
                self.pool, second_config, synchronization)

        # checking if there are no pending jobs
        jobs_after = get_thread_pool().qsize
        msg = ('there are %d jobs pending to be done after the acquisition ' +
               '(before: %d)') % (jobs_after, jobs_before)
        self.assertEqual(jobs_before, jobs_after, msg)
Пример #3
0
    def run(self, *args, **kwargs):
        """Runs this action"""

        self._running = True
        synch = kwargs.pop("synch", False)

        if synch:
            try:
                with OperationContext(self) as context:
                    self.start_action(*args, **kwargs)
                    self._started = False
                    self.action_loop()
            finally:
                self._started = False
                self._running = False
        else:
            context = OperationContext(self)
            context.enter()
            try:
                self.start_action(*args, **kwargs)
            except:
                context.exit()
                self._running = False
                raise
            finally:
                self._started = False
            get_thread_pool().add(self._asynch_action_loop, None, context)
Пример #4
0
 def event_received(self, *args, **kwargs):
     """Callback to execute software start acquisition."""
     _, type_, value = args
     name = type_.name
     if name == "start":
         get_thread_pool().add(self.acquisition.run, None, *self.acq_args,
                               **self.acq_kwargs)
 def StartOne(self, axis):
     """Start the specified trigger
     """
     self._log.debug('StartOne(%d): entering...' % axis)
     idx = axis - 1
     tg = self.tg[idx]
     tg.start()
     get_thread_pool().add(tg.run)
Пример #6
0
 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)
Пример #7
0
 def event_received(self, *args, **kwargs):
     """Callback to execute software start acquisition."""
     _, type_, value = args
     name = type_.name
     if name != "start":
         return
     args = self.acq_args
     kwargs = self.acq_kwargs
     get_thread_pool().add(self.acquisition.run, None, *args, **kwargs)
Пример #8
0
 def acquire(self, integ_time, repetitions, latency_time):
     """Acquire with a dummy C/T synchronized by a hardware start
     trigger from a dummy T/G."""
     self.ct_ctrl_1.set_ctrl_par("synchronization", AcqSynch.HardwareStart)
     conf_ct_ctrl_1 = createTimerableControllerConfiguration(
         self.ct_ctrl_1, [self.ct_1_1])
     ctrls = get_timerable_ctrls([conf_ct_ctrl_1], AcqMode.Timer)
     conf_tg_ctrl_1 = createControllerConfiguration(self.tg_ctrl_1,
                                                    [self.tg_1_1])
     synch_ctrls = get_acq_ctrls([conf_tg_ctrl_1])
     self.synchronization = self.create_action(PoolSynchronization,
                                               [self.tg_1_1])
     # add data listeners
     self.add_listeners([self.ct_1_1])
     # creating acquisition actions
     self.acquisition = self.create_action(PoolAcquisitionHardware,
                                           [self.ct_1_1])
     self.acq_args = ([conf_ct_ctrl_1], integ_time, repetitions)
     # prepare synchronization description
     total_interval = integ_time + latency_time
     group = {
         SynchParam.Delay: {SynchDomain.Time: 0},
         SynchParam.Active: {SynchDomain.Time: integ_time},
         SynchParam.Total: {SynchDomain.Time: total_interval},
         SynchParam.Repeats: repetitions
     }
     synchronization = [group]
     # get the current number of jobs
     jobs_before = get_thread_pool().qsize
     self.acquisition.run(ctrls, integ_time, repetitions, 0)
     self.synchronization.run(synch_ctrls, synchronization)
     self.wait_finish()
     self.do_asserts(repetitions, jobs_before)
Пример #9
0
    def meas_cont_stop_acquisition(self, config, synchronization,
                                   moveable=None):
        """Executes measurement using the measurement group and tests that the
        acquisition can be stopped.
        """
        self.prepare_meas(config)
        self.pmg.synchronization = synchronization
        self.pmg.set_moveable(moveable, to_fqdn=False)
        self.prepare_attribute_listener()

        self.pmg.start_acquisition()
        # retrieving the acquisition since it was cleaned when applying mg conf
        acq = self.pmg.acquisition

        # starting timer (0.05 s) which will stop the acquisiton
        threading.Timer(0.2, self.stop_acquisition).start()
        # waiting for acquisition and tggeneration to be stoped by thread
        while acq.is_running():
            time.sleep(0.05)
        msg = "acquisition shall NOT be running after stopping it"
        self.assertEqual(acq.is_running(), False, msg)

        tp = get_thread_pool()
        numBW = tp.getNumOfBusyWorkers()
        msg = "The number of busy workers is not zero; numBW = %s" % (numBW)
        self.assertEqual(numBW, 0, msg)
        # print the acquisition records
        for i, record in enumerate(zip(*self.attr_listener.data.values())):
            print i, record
Пример #10
0
 def event_received(self, *args, **kwargs):
     """Callback to execute software start acquisition."""
     _, type_, value = args
     name = type_.name
     if name == "active":
         if self.acq_busy.is_set():
             # skipping acquisition cause the previous on is ongoing
             return
         else:
             self.acq_busy.set()
             acq_args = list(self.acq_args)
             acq_kwargs = self.acq_kwargs
             index = value
             acq_args[3] = index
             get_thread_pool().add(self.acquisition.run, None, *acq_args,
                                   **acq_kwargs)
Пример #11
0
 def event_received(self, *args, **kwargs):
     """Executes a single software triggered acquisition."""
     _, type_, index = args
     name = type_.name
     if name == "active":
         if self.sw_acq_busy.is_set():
             # skipping acquisition cause the previous on is ongoing
             return
         else:
             self.sw_acq_busy.set()
             args = self.sw_acq_args
             kwargs = self.sw_acq_kwargs
             kwargs['index'] = index
             get_thread_pool().add(self.sw_acq.run,
                                   None,
                                   *args,
                                   **kwargs)
Пример #12
0
    def acquire(self, integ_time, repetitions, latency_time):
        """Acquire with a dummy C/T synchronized by a hardware start
        trigger from a dummy T/G."""
        self.prepare(integ_time, repetitions, latency_time, 1)
        conf_ct_ctrl_1 = createTimerableControllerConfiguration(
            self.channel_ctrl, [self.channel])
        ctrls = get_timerable_ctrls([conf_ct_ctrl_1], AcqMode.Timer)
        master = ctrls[0].master
        # creating synchronization action
        self.synchronization = self.create_action(PoolSynchronization,
                                                  [self.tg])
        self.synchronization.add_listener(self)
        # add_listeners
        self.add_listeners([self.channel])
        # creating acquisition actions
        self.acquisition = self.create_action(PoolAcquisitionSoftware,
                                              [self.channel])
        # Since we deposit the software acquisition action on the PoolThread's
        # queue we can not rely on the action's state - one may still wait
        # in the queue (its state has not changed to running yet) and we would
        # be depositing another one. This way we may be starting multiple
        # times the same action (with the same elements involved), what results
        # in "already involved in operation" errors.
        # Use an external Event flag to mark if we have any software
        # acquisition action pending.
        self.acq_busy = threading.Event()
        self.acquisition.add_finish_hook(self.acq_busy.clear)
        self.acq_args = (ctrls, integ_time, master, None)
        self.acq_kwargs = {}

        total_interval = integ_time + latency_time
        group = {
            SynchParam.Delay: {
                SynchDomain.Time: 0
            },
            SynchParam.Active: {
                SynchDomain.Time: integ_time
            },
            SynchParam.Total: {
                SynchDomain.Time: total_interval
            },
            SynchParam.Repeats: repetitions
        }
        synchronization = [group]
        # get the current number of jobs
        jobs_before = get_thread_pool().qsize
        self.synchronization.run([], synchronization)
        self.wait_finish()
        self.do_asserts(repetitions, jobs_before, strict=False)
Пример #13
0
 def do_asserts(self, repetitions, jobs_before):
     # print acquisition records
     table = self.data_listener.get_table()
     header = table.dtype.names
     print header
     n_rows = table.shape[0]
     for row in xrange(n_rows):
         print row, table[row]
     # checking if all channels produced data
     for channel in self.channel_names:
         msg = 'data from channel %s were not acquired' % channel
         self.assertIn(channel, header, msg)
     # checking if all the data were acquired
     for ch_name in header:
         ch_data_len = len(table[ch_name])
         msg = 'length of data for channel %s is %d and should be %d' %\
             (ch_name, ch_data_len, repetitions)
         self.assertEqual(ch_data_len, repetitions, msg)
     # checking if there are no pending jobs
     jobs_after = get_thread_pool().qsize
     msg = ('there are %d jobs pending to be done after the acquisition ' +
            '(before: %d)') % (jobs_after, jobs_before)
     self.assertEqual(jobs_before, jobs_after, msg)
Пример #14
0
    def continuous_acquisition(self, offset, active_interval, passive_interval,
                               repetitions, integ_time):
        """Executes measurement running the TGGeneration and Acquisition actions
        according the test parameters. Checks the lengths of the acquired data.
        """
        # obtaining elements created in the BasePoolTestCase.setUp
        tg_1_1 = self.tgs['_test_tg_1_1']
        tg_ctrl_1 = tg_1_1.get_controller()
        ct_1_1 = self.cts['_test_ct_1_1']  # hw synchronized
        ct_2_1 = self.cts['_test_ct_2_1']  # sw synchronized
        ct_ctrl_1 = ct_1_1.get_controller()
        ct_ctrl_1.set_ctrl_par("synchronization", AcqSynch.HardwareTrigger)
        ct_ctrl_2 = ct_2_1.get_controller()
        self.channel_names.append('_test_ct_1_1')
        self.channel_names.append('_test_ct_2_1')

        conf_ct_ctrl_1 = createTimerableControllerConfiguration(ct_ctrl_1,
                                                                [ct_1_1])
        conf_ct_ctrl_2 = createTimerableControllerConfiguration(ct_ctrl_2,
                                                                [ct_2_1])
        hw_ctrls = get_timerable_ctrls([conf_ct_ctrl_1],
                                       acq_mode=AcqMode.Timer)
        sw_ctrls = get_timerable_ctrls([conf_ct_ctrl_2],
                                       acq_mode=AcqMode.Timer)
        sw_master = sw_ctrls[0].master
        conf_tg_ctrl_1 = createControllerConfiguration(tg_ctrl_1, [tg_1_1])
        synch_ctrls = get_acq_ctrls([conf_tg_ctrl_1])
        # creating synchronization action
        self.synchronization = self.create_action(PoolSynchronization,
                                                  [tg_1_1])
        self.synchronization.add_listener(self)
        # add_listeners
        self.add_listeners([ct_1_1, ct_2_1])
        # creating acquisition actions
        self.hw_acq = self.create_action(PoolAcquisitionHardware, [ct_1_1])
        self.sw_acq = self.create_action(PoolAcquisitionSoftware, [ct_2_1])
        # Since we deposit the software acquisition action on the PoolThread's
        # queue we can not rely on the action's state - one may still wait
        # in the queue (its state has not changed to running yet) and we would
        # be depositing another one. This way we may be starting multiple
        # times the same action (with the same elements involved), what results
        # in "already involved in operation" errors.
        # Use an external Event flag to mark if we have any software
        # acquisition action pending.
        self.sw_acq_busy = threading.Event()
        self.sw_acq.add_finish_hook(self.sw_acq_busy.clear)
        self.sw_acq_args = (sw_ctrls, integ_time, sw_master)
        self.sw_acq_kwargs = {}

        total_interval = active_interval + passive_interval
        group = {
            SynchParam.Delay: {SynchDomain.Time: offset},
            SynchParam.Active: {SynchDomain.Time: active_interval},
            SynchParam.Total: {SynchDomain.Time: total_interval},
            SynchParam.Repeats: repetitions
        }
        synchronization = [group]
        # get the current number of jobs
        jobs_before = get_thread_pool().qsize
        self.hw_acq.run(hw_ctrls, integ_time, repetitions, 0)
        self.synchronization.run(synch_ctrls, synchronization)
        # waiting for acquisition and synchronization to finish
        while (self.hw_acq.is_running()
               or self.sw_acq.is_running()
               or self.synchronization.is_running()):
            time.sleep(.1)
        self.do_asserts(repetitions, jobs_before)
Пример #15
0
 def _raw_read_value_concurrent_loop(self, ret):
     """Internal method. Read value in a concurrent mode"""
     th_pool = get_thread_pool()
     for pool_ctrl in self.get_read_value_loop_ctrls():
         th_pool.add(self._raw_read_ctrl_value, None, ret, pool_ctrl)
     return ret
Пример #16
0
 def _raw_read_state_info_concurrent(self, ret):
     """Internal method. Read state in a concurrent mode"""
     th_pool = get_thread_pool()
     for pool_ctrl in self._pool_ctrl_dict:
         th_pool.add(self._raw_read_ctrl_state_info, None, ret, pool_ctrl)
     return ret
Пример #17
0
    def start_action(self, ctrls, synch_description, moveable=None,
                     sw_synch_initial_domain=None, *args, **kwargs):
        """Start synchronization action.

        :param ctrls: list of enabled trigger/gate controllers
        :type ctrls: list
        :param synch_description: synchronization description
        :type synch_description:
         :class:`~sardana.pool.poolsynchronization.SynchDescription`
        :param moveable: (optional) moveable object used as the
         synchronization source in the Position domain
        :type moveable: :class:`~sardna.pool.poolmotor.PoolMotor` or
         :class:`~sardana.pool.poolpseudomotor.PoolPseudoMotor`
        :param sw_synch_initial_domain: (optional) - initial domain for
         software synchronizer, can be either
         :obj:`~sardana.pool.pooldefs.SynchDomain.Time` or
         :obj:`~sardana.pool.pooldefs.SynchDomain.Position`
        """
        with ActionContext(self):

            # loads synchronization description
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.PreSynchAll()
                for channel in ctrl.get_channels(enabled=True):
                    axis = channel.axis
                    ret = pool_ctrl.ctrl.PreSynchOne(axis, synch_description)
                    if not ret:
                        msg = ("%s.PreSynchOne(%d) returns False" %
                               (ctrl.name, axis))
                        raise Exception(msg)
                    pool_ctrl.ctrl.SynchOne(axis, synch_description)
                pool_ctrl.ctrl.SynchAll()

            # attaching listener (usually acquisition action)
            # to the software trigger gate generator
            if self._listener is not None:
                if sw_synch_initial_domain is not None:
                    self._synch_soft.initial_domain = sw_synch_initial_domain
                self._synch_soft.set_configuration(synch_description)
                self._synch_soft.add_listener(self._listener)
                remove_acq_listener = partial(self._synch_soft.remove_listener,
                                              self._listener)
                self.add_finish_hook(remove_acq_listener, False)
                self._synch_soft.add_listener(
                    self.main_element.on_element_changed)
                remove_mg_listener = partial(self._synch_soft.remove_listener,
                                             self.main_element)
                self.add_finish_hook(remove_mg_listener, False)
            # subscribing to the position change events to generate events
            # in position domain
            if moveable is not None:
                position = moveable.get_position_attribute()
                position.add_listener(self._synch_soft)
                remove_pos_listener = partial(position.remove_listener,
                                              self._synch_soft)
                self.add_finish_hook(remove_pos_listener, False)

            # start software synchronizer
            if self._listener is not None:
                self._synch_soft.start()
                get_thread_pool().add(self._synch_soft.run)

            # PreStartAll on all controllers
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.PreStartAll()

            # PreStartOne & StartOne on all elements
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                for channel in ctrl.get_channels(enabled=True):
                    axis = channel.axis
                    ret = pool_ctrl.ctrl.PreStartOne(axis)
                    if not ret:
                        raise Exception("%s.PreStartOne(%d) returns False"
                                        % (pool_ctrl.name, axis))
                    pool_ctrl.ctrl.StartOne(axis)

            # set the state of all elements to inform their listeners
            self._channels = []
            for ctrl in ctrls:
                for channel in ctrl.get_channels(enabled=True):
                    channel.set_state(State.Moving, propagate=2)
                    self._channels.append(channel)

            # StartAll on all controllers
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.StartAll()
Пример #18
0
 def add_job(self, job, callback=None, *args, **kw):
     th_pool = get_thread_pool()
     th_pool.add(job, callback, *args, **kw)
Пример #19
0
 def set_max_parallel_macros(self, nb):
     assert nb > 0, "max parallel macros number must be > 0"
     th_pool = get_thread_pool()
     if th_pool.size + 5 < nb:
         th_pool.size = nb
     self._max_parallel_macros = nb
Пример #20
0
    def start_action(self, ctrls, synchronization, moveable=None,
                     sw_synch_initial_domain=None, *args, **kwargs):
        """Start synchronization action.

        :param ctrls: list of enabled trigger/gate controllers
        :type ctrls: list
        :param synchronization: synchronization description
        :type synchronization:
         :class:`~sardana.pool.poolsynchronization.SynchronizationDescription`
        :param moveable: (optional) moveable object used as the
         synchronization source in the Position domain
        :type moveable: :class:`~sardna.pool.poolmotor.PoolMotor` or
         :class:`~sardana.pool.poolpseudomotor.PoolPseudoMotor`
        :param sw_synch_initial_domain: (optional) - initial domain for
         software synchronizer, can be either
         :obj:`~sardana.pool.pooldefs.SynchDomain.Time` or
         :obj:`~sardana.pool.pooldefs.SynchDomain.Position`
        """
        with ActionContext(self):

            # loads synchronization description
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.PreSynchAll()
                for channel in ctrl.get_channels(enabled=True):
                    axis = channel.axis
                    ret = pool_ctrl.ctrl.PreSynchOne(axis, synchronization)
                    if not ret:
                        msg = ("%s.PreSynchOne(%d) returns False" %
                               (ctrl.name, axis))
                        raise Exception(msg)
                    pool_ctrl.ctrl.SynchOne(axis, synchronization)
                pool_ctrl.ctrl.SynchAll()

            # attaching listener (usually acquisition action)
            # to the software trigger gate generator
            if self._listener is not None:
                if sw_synch_initial_domain is not None:
                    self._synch_soft.initial_domain = sw_synch_initial_domain
                self._synch_soft.set_configuration(synchronization)
                self._synch_soft.add_listener(self._listener)
                remove_acq_listener = partial(self._synch_soft.remove_listener,
                                              self._listener)
                self.add_finish_hook(remove_acq_listener, False)
                self._synch_soft.add_listener(
                    self.main_element.on_element_changed)
                remove_mg_listener = partial(self._synch_soft.remove_listener,
                                             self.main_element)
                self.add_finish_hook(remove_mg_listener, False)
            # subscribing to the position change events to generate events
            # in position domain
            if moveable is not None:
                position = moveable.get_position_attribute()
                position.add_listener(self._synch_soft)
                remove_pos_listener = partial(position.remove_listener,
                                              self._synch_soft)
                self.add_finish_hook(remove_pos_listener, False)

            # start software synchronizer
            if self._listener is not None:
                self._synch_soft.start()
                get_thread_pool().add(self._synch_soft.run)

            # PreStartAll on all controllers
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.PreStartAll()

            # PreStartOne & StartOne on all elements
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                for channel in ctrl.get_channels(enabled=True):
                    axis = channel.axis
                    ret = pool_ctrl.ctrl.PreStartOne(axis)
                    if not ret:
                        raise Exception("%s.PreStartOne(%d) returns False"
                                        % (pool_ctrl.name, axis))
                    pool_ctrl.ctrl.StartOne(axis)

            # set the state of all elements to inform their listeners
            self._channels = []
            for ctrl in ctrls:
                for channel in ctrl.get_channels(enabled=True):
                    channel.set_state(State.Moving, propagate=2)
                    self._channels.append(channel)

            # StartAll on all controllers
            for ctrl in ctrls:
                pool_ctrl = ctrl.element
                pool_ctrl.ctrl.StartAll()