find_max_att.py 6.88 KB
Newer Older
Yoann Sallaz Damaz's avatar
bla  
Yoann Sallaz Damaz committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
"""
Procedure to find the max attenuation on a sample, while the signal from
the flourescence detector is within specified min and max integrated counts,
for a ROI between a configurable min and max energy, for a given counting time.

yml configuration example:
name: find_max_attenuation
plugin: default
diffractometer: $diffractometer
mca: $mca
transmission: $transmission
safshut: $safshut
integrated_counts: [2000, 50000]
transmission_table: [0.1, 0.2, 0.3, 0.9, 1.3, 1.9, 2.6, 4.3, 6, 8, 12, 24, 36, 50, 71]
"""
import logging
import gevent
from bliss.config import static
from bliss.common.cleanup import cleanup, error_cleanup
from bliss.setup_globals import *

class FindMaxAttenuation:
    """ Find maximum attenuation """

    def __init__(self):
        #cfg = static.get_config()
        #config = cfg.get("find_max_attenuation")
        #self.safshut = config.get("safshut")
        #self.fastshut = config.get("fastshut")
        #self.mca = config.get("mca")
        #self.mca_in_out = config.get("mca_in_out")
        #self.bstop = config.get("bstop")
        #self.transmission = config.get("transmission")
        #self.transmission_table = config.get("transmission_table", [])
        self.transmission_table = [0.1, 0.2, 0.3, 0.9, 1.3, 1.9, 2.6, 4.3, 6, 8, 12, 24, 36, 50, 71]
        self.t_table = []
        #self.integrated_counts = config.get("integrated_counts", [])
        self.integrated_counts = [2000, 50000]
        self.roi = []
        self.datafile = None
        self.initial_transmission = 0
        self.ctime = 3  # default count time [s]
        self.misc_roi_params = ["Se", 34]  # default roi element

    def init(self, **kwargs):
        """Initialise the procedure
        Kwargs:
            ctime(float): count time [s]
            integrated_counts (list): minimum and maximum mca counts value
            roi (list): mca ROI minimum and maximum energy [keV]
            datafile (string): file to keep the data - full path
            transmission_table (list): list of transmission values to check
            misc_roi_params (list): some roi parameters
        """

        if not safshut:
            logging.getLogger().debug("Safety shutter will not be handled")

        # count time in s
        self.ctime = kwargs.get("ctime", 3.0)

        # filename if saving the raw data wanted
        self.datafile = kwargs.get("datafile")

        # get the mca roi and set the values in keV
        self.roi = []
        roi = kwargs.get("roi", [2.0, 15.0])
        for i in roi:
            if i > 1000:
                i /= 1000.0
            self.roi.append(i)
        self.roi.sort()

        self.misc_roi_params = kwargs.get("misc_roi_params", ["Se", 34])

        integrated_counts = kwargs.get("integrated_counts")
        if integrated_counts:
            self.integrated_counts = integrated_counts

        if not self.integrated_counts:
            msg = "Minimum and/or maximum integrates counts value not set"
            logging.getLogger("user_level_log").exception(msg)
            raise RuntimeError(msg)
        self.integrated_counts.sort()

        self.t_table = kwargs.get("transmission_table", self.transmission_table)

    def _prepare(self, ctime=None):
        if ctime:
            self.ctime = ctime

        # set the mca
        mca.set_roi(
            self.roi[0],
            self.roi[1],
            channel=1,
            element=self.misc_roi_params[0],
            atomic_nb=self.misc_roi_params[1],
        )
        mca.set_presets(erange=1, ctime=self.ctime, fname=self.datafile)

        # open safety shutter (just in case)
        if safshut:
           safshut.open()

        # put the fluorescent detector close to the sample
        mca_in_out.insert()

    def _cleanup(self):
        fastshut.open_manual()

    def _error_cleanup(self):
        self._cleanup()
        mca_in_out.remove()
        if safshut:
            fastshut.close_manual()

    def _procedure(self, ctime=None):
        """ The procedure itself """
        if ctime:
            self.ctime = ctime

        def restore_transmission(old_transmission=transmission.get()):
            transmission.set(old_transmission)

        with cleanup(self._cleanup):
            # set the maximum attenuation
            transmission.set(0)
            logging.getLogger("user_level_log").info(
                "Choosing maximum attenuation, please wait"
            )

            # open the fast shutter
            fastshut.open_manual()

            with error_cleanup(self._error_cleanup, restore_transmission):
                # start the acquisition
                mca.start_acq()
                gevent.sleep(self.ctime)
                # save data if needed
                save_data = False
                if self.datafile:
                    save_data = True
                    logging.getLogger("user_level_log").info(
                        "Raw data in " + self.datafile
                    )

                # read the integrated counts
                i_c = sum(mca.read_roi_data(save_data)) // self.ctime
                logging.getLogger("user_level_log").debug(
                    "Integrated counts/s: %g" % i_c
                )
                if i_c > self.integrated_counts[1]:
                    fastshut.close_manual()
                    msg = "The detector is saturated, giving up."
                    logging.getLogger("user_level_log").exception(msg)
                    raise RuntimeError(msg)

                for t_m in self.t_table:
                    mca.clear_spectrum()
                    logging.getLogger("user_level_log").debug(
                        "Setting transmission to %f" % t_m
                    )
                    transmission.set(t_m)
                    mca.start_acq()
                    gevent.sleep(self.ctime)
                    i_c = sum(mca.read_roi_data()) // self.ctime
                    print("Integrated counts/s: %d" % i_c)
                    logging.getLogger("user_level_log").debug(
                        "Integrated counts/s: %g" % i_c
                    )
                    if i_c > self.integrated_counts[0]:
                        fastshut.close_manual()
                        t_m = transmission.get()
                        logging.getLogger("user_level_log").info(
                            "Transmission chosen: %.3f (%d counts/s)" % (t_m, i_c)
                        )
                        return t_m

                if i_c < self.integrated_counts[0]:
                    msg = "Could not find satisfactory attenuation (is the mca properly set up?), giving up."
                    logging.getLogger("user_level_log").exception(msg)
                    raise RuntimeError(msg)
        return False

    def find_max_attenuation(self, **kwargs):
        """ The whole sequence of finding maximum attenuation """
        self.init(**kwargs)
        self._prepare(**kwargs)
        return self._procedure(**kwargs)


find_max_attenuation = FindMaxAttenuation().find_max_attenuation