counter.py 3.84 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
# -*- coding: utf-8 -*-
#
# This file is part of the bliss project
#
# Copyright (c) 2017 Beamline Control Unit, ESRF
# Distributed under the GNU LGPLv3. See LICENSE for more info.

import numpy
import time
from gevent import event,sleep
from bliss.common.event import dispatcher
12
from ..chain import AcquisitionDevice,AcquisitionChannel
13
from bliss.common.measurement import CounterBase
14
15
16

class CounterAcqDevice(AcquisitionDevice):
    def __init__(self,counter,
17
                 count_time=None,npoints=1,**keys):
18
19
20
21
22
23
24
25
26
        prepare_once = keys.pop('prepare_once',npoints > 1 and True or False)
        start_once = keys.pop('start_once',npoints > 1 and True or False)
        npoints = max(1,npoints)
        AcquisitionDevice.__init__(self, counter, counter.name, "zerod",
                                   npoints=npoints,
                                   trigger_type=AcquisitionDevice.SOFTWARE,
                                   prepare_once=prepare_once,
                                   start_once=start_once,
                                   **keys)
27
        self._count_time = count_time
28
29
        if not isinstance(counter,CounterBase.ReadAllHandler):
            self.channels.append(AcquisitionChannel(counter.name,numpy.double, (1,)))
30
31
32
33
34
35
        self._nb_acq_points = 0
        self._event = event.Event()
        self._stop_flag = False
        self._ready_event = event.Event()
        self._ready_flag = True

36
37
38
    def add_counter_to_read(self,counter):
        self.channels.append(AcquisitionChannel(counter.name,numpy.double, (1,)))

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    def prepare(self):
        self._nb_acq_points = 0
        self._stop_flag = False
        self._ready_flag = True
        self._event.clear()

    def start(self):
        pass

    def stop(self):
        self._stop_flag = True
        self._trig_time = None
        self._event.set()

    def trigger(self):
        self._trig_time = time.time()
        self._event.set()

    def wait_ready(self):
        """
        will wait until the last triggered point is read
        """
        while not self._ready_flag:
            self._ready_event.wait()
            self._ready_event.clear()

    def reading(self):
66
67
68
69
70
71
72
73
74
        counter_name = [x.name for x in self.channels]
        if isinstance(self.device,CounterBase.ReadAllHandler):
            def read():
                return numpy.array(self.device.read_all(*counter_name),
                                   dtype=numpy.double)
        else:                   # read_all
            def read():
                return numpy.array(self.device.read(),
                                   dtype=numpy.double)
75
76
77
78
79
80
81
82
83
84
85
        while self._nb_acq_points < self.npoints:
            #trigger wait
            self._event.wait()
            self._event.clear()
            self._ready_flag = False
            trig_time = self._trig_time
            if trig_time is None: continue
            if self._stop_flag: break

            nb_read = 0
            acc_read_time = 0
86
            acc_value = numpy.zeros((len(counter_name),),dtype=numpy.double)
87
            stop_time = trig_time + self._count_time or 0
88
89
90
            #Counter integration loop
            while not self._stop_flag:
                start_read = time.time()
91
                acc_value += read()
92
93
94
95
96
97
98
99
100
101
                end_read = time.time()
                nb_read += 1
                acc_read_time += end_read - start_read

                current_time = time.time()
                if (current_time + (acc_read_time / nb_read)) > stop_time:
                    break
                sleep(0) # Be able to kill the task

            self._nb_acq_points += 1
102
103
            data = acc_value / nb_read
            channel_data = {name:data[index] for index,name in enumerate(counter_name)}
104
            dispatcher.send("new_data",self,
105
                            {"channel_data": channel_data})
106
107
            self._ready_flag = True
            self._ready_event.set()
108