Ejemplo n.º 1
0
    def __init__(self, prefix, ad_prefix, stream,
                 enable_callbacks=0, min_cbtime=0, queuesize=5):
        """
        Parameters
        ----------
        prefix: str
            The plugin prefix that comes after the areaDetector prefix in the
            PV names.

        ad_prefix: str
            The base areaDetector control prefix. This should match a real
            areaDetector IOC's prefix.

        stream: str
            The image stream to use for the plugins. We'll be using:
                $(ad_prefix)$(stream):ArrayData    for values
                $(ad_prefix)$(stream):UniqueId_RBV for update monitoring

        enable_callbcaks: bool, optional
            If True, start the IOC with callbacks enabled. Start disabled
            otherwise.

        min_cbtime: float, optional
            The initial value for the minimum time for each callback loop.

        queuesize: int, optional
            The initial value for the array queue. The default is 5.
        """
        self.server = PypvServer(ad_prefix + prefix)
        self.ad_prefix = ad_prefix
        self.ad_directory = {}
        self.settings_lock = RLock()
        self.plugins = {}
        self.has_update = Event()
        self.enable_callbacks = int(enable_callbacks)
        self.min_cbtime = float(min_cbtime)
        self.queue = None
        queuesize = int(queuesize)

        self._ndarray_port_cb(value=str(stream))
        self._add_builtin('NDArrayPort', str(stream), cb=self._ndarray_port_cb)
        self._enable_callbacks_cb(value=self.enable_callbacks)
        self._add_builtin('EnableCallbacks', self.enable_callbacks,
                          cb=self._enable_callbacks_cb)
        self._min_cbtime_cb(value=self.min_cbtime)
        self._add_builtin('MinCallbackTime', self.min_cbtime,
                          cb=self._min_cbtime_cb)
        self._queuesize_cb(value=queuesize)
        self._add_builtin('QueueSize', queuesize, cb=self._queuesize_cb)
        self._add_builtin('QueueUse', 0)
        self._add_builtin('DroppedArrays', 0)

        arrays = CAThread(target=self._array_cb_loop, args=(), daemon=True)
        plugins = Thread(target=self._get_queue_loop, args=(), daemon=True)
        arrays.start()
        plugins.start()
Ejemplo n.º 2
0
    def setup(self):
        """Set up the server.

        Starts threads and registers for EPICS callbacks.

        """
        self._publisher_thread = CAThread(target=self._publisher,
                                          args=(self.update_addr, ),
                                          daemon=True)
        self._publisher_thread.start()
        self._request_thread = CAThread(target=self._request_handler,
                                        args=(self.request_addr, ),
                                        daemon=True)
        self._request_thread.start()
        for attr in self.robot.attrs:
            pv = getattr(self.robot, attr)
            pv.add_callback(self._pv_callback)
        self.robot.client_update.add_callback(self._on_robot_update)
        self.logger.debug('setup complete')
Ejemplo n.º 3
0
    def start_processes(self, acquire_pv, counter_pv_name, data_pv, frame_type_pv, logger, reportq, *args, **kwargs):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.

        Parameters
        ----------
        counter_pv : str
            a PV string for the area detector frame counter

        data_pv : str
            a PV string for the area detector frame data

        frame_type_pv : str
            a PV string for the area detector data type

        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger

        *args : list
            a list of arguments specific to the client process

        Returns
        -------
        None
        """
        data_thread = CAThread(target=self.deliver_data, args=(data_pv, frame_type_pv, logger,))
        data_thread.start()
        p = Process(target=handler.handle_data,
                    args=(self.process_dataq, reportq, args, kwargs,))
        p.start()

        self.counter_pv = PV(counter_pv_name)
        self.counter_pv.add_callback(self.on_ctr_change, index=1)

        self.acq_pv = PV(acquire_pv)
        self.acq_pv.add_callback(self.acq_done, index=2)

        try:
            callback_pv_name = kwargs['callback_pv']
            self.callback_pv = PV(callback_pv_name)
            self.callback_pv.add_callback(self.on_change, as_string=True, index=3)
        except KeyError:
            pass
Ejemplo n.º 4
0
def atl(softioc, caclient, tmpdir_factory):
    AbortCh.fields['ACNT'] = ':ACNT'
    AbortCh.fields['TCNT'] = ':TCNT'
    dburi = ('sqlite:///' +
             str(tmpdir_factory.mktemp('data').join('testdata.db'))
             )
    insert_current_pv_mock(dburi)
    set_initial_abort_state()
    atl = Aborttl(dburi, 'ET_dummyHost:RESETw')

    thread = CAThread(target=atl.run)
    thread.daemon = True
    thread.start()
    time.sleep(5)
    yield atl
    atl.stop()
    thread.join()
    time.sleep(1)
Ejemplo n.º 5
0
    def start_processes(self, counter_pv, data_pv, frame_type_pv, logger,
                        *args):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.
    
        Parameters
        ----------
        counter_pv : str
            a PV string for the area detector frame counter
    
        data_pv : str
            a PV string for the area detector frame data

        frame_type_pv : str
            a PV string for the area detector data type
    
        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger
    
        *args : list
            a list of arguments specific to the client process
    
        Returns
        -------
        None
        """
        data_thread = CAThread(target=self.deliver_data,
                               args=(
                                   data_pv,
                                   frame_type_pv,
                                   logger,
                               ))
        data_thread.start()

        adapter.start_process(self.process_dataq, logger, *args)
        self.cntr_pv = PV(counter_pv)
        self.cntr_pv.add_callback(self.on_change, index=1)
Ejemplo n.º 6
0
 def _process_request(self, message):
     """Parse requests from the clients and take the appropriate action."""
     self.logger.debug('client request: %r', message)
     operation = message.get('operation')
     parameters = message.get('parameters', {})
     try:
         target = getattr(self, operation)
     except (AttributeError, TypeError):
         self.logger.error('operation does not exist: %r', operation)
         return {'error': 'invalid request: operation does not exist'}
     try:
         operation_type = target._operation_type
     except AttributeError:
         self.logger.error('%r must be declared an operation', operation)
         return {
             'error': 'invalid request: %r not an operation' % operation
         }
     try:
         sig = inspect.signature(target)
         if operation_type == 'query':
             sig.bind(**parameters)
         else:
             sig.bind(None, **parameters)  # Must accept a handle argument
     except (ValueError, TypeError):
         self.logger.error('invalid arguments for operation %r: %r',
                           operation, parameters)
         return {'error': 'invalid request: incorrect arguments'}
     self.logger.debug('calling: %r with %r', operation, parameters)
     if operation_type == 'query':
         return target(**parameters)
     elif operation_type in {'foreground', 'background'}:
         handle = self._next_handle()
         thread = CAThread(target=target,
                           args=(handle, ),
                           kwargs=parameters,
                           daemon=True)
         thread.start()
         return {'error': None, 'handle': handle}
     else:
         return {'error': 'invalid request: unknown operation type'}
Ejemplo n.º 7
0
    def start_processes(self):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.

        Parameters
        ----------
        none

        Returns
        -------
        nothing
        """
        data_thread = CAThread(target=self.handle_event, args=())
        data_thread.start()

        self.counter_pv = PV(self.get_counter_pv_name())
        self.counter_pv.add_callback(self.on_change, index=1)

        self.acq_pv = PV(self.get_acquire_pv_name())
        self.acq_pv.add_callback(self.acq_done, index=2)
Ejemplo n.º 8
0
def test_cathread():
    write( 'Test use CAThread\n')
    th1 = CAThread(target=run_CAThread, args=(names_a, 3, 'A'))
    th2 = CAThread(target=run_CAThread, args=(names_b, 5, 'B'))
    run_threads((th1, th2))
Ejemplo n.º 9
0
        stdout.flush()

    # epics.ca.use_initial_context()   #  epics.ca.create_context()
    start_time = time.time()
    pvs = [epics.PV(pvn, callback=onChanges) for pvn in pvnames]

    while time.time() - start_time < runtime:
        time.sleep(0.001)

    [p.clear_callbacks() for p in pvs]
    stdout.write('Completed Thread  %s\n' % (run_name))


stdout.write("First, create a PV in the main thread:\n")
for pvname in pvlist_a + pvlist_b:
    p = epics.PV(pvname)
    p.connect()
    p.get()
    print(p.info)

stdout.write("Run 2 Background Threads simultaneously:\n")
th1 = CAThread(target=run_test, args=(30, pvlist_a, 'A'))
th1.start()

th2 = CAThread(target=run_test, args=(60, pvlist_b, 'B'))
th2.start()

th2.join()
th1.join()
stdout.write('Done\n')
Ejemplo n.º 10
0
    # pvs_b.append(pvname)
    names_b.append(pvname)

names_a = names_b[1:]
pvs_a = pvs_b[1:]

epics.ca.create_context()

styles = ('decorator', 'init', 'cathread')
style = styles[2]

if style == 'init':
    write(
        'Test use plain threading.Thread, force use of initial CA Context \n')
    th1 = Thread(target=test_initcontext, args=(names_a, 2, 'A'))
    th2 = Thread(target=test_initcontext, args=(names_b, 3, 'B'))
    run_threads((th1, th2))

elif style == 'decorator':
    write('Test use plain threading.Thread, withInitialContext decorator\n')
    th1 = Thread(target=test_decorator, args=(names_a, 3, 'A'))
    th2 = Thread(target=test_decorator, args=(names_b, 5, 'B'))
    run_threads((th1, th2))
elif style == 'cathread':
    write('Test use CAThread\n')
    th1 = CAThread(target=test_CAThread, args=(names_a, 3, 'A'))
    th2 = CAThread(target=test_CAThread, args=(names_b, 5, 'B'))
    run_threads((th1, th2))

write('Test Done\n---------------------\n')