forked from esrf-bliss/Lima-tango
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AttrHelper.py
173 lines (151 loc) · 6.99 KB
/
AttrHelper.py
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
############################################################################
# This file is part of LImA, a Library for Image Acquisition
#
# Copyright (C) : 2009-2012
# European Synchrotron Radiation Facility
# BP 220, Grenoble 38043
# FRANCE
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This software 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
############################################################################
#============================================================================
# HELPERS
#============================================================================
#
# These helpers allows any one to map attributes with the LIMA interfaces commands without having
# to write any extra code for the read_ / write_ methods.
# It works for attributes with enumerate value and for simple value passing.
# Mapping between attributes and commands is done using a dictionnary and for each
# attribute with enum an extra dictionnary is mandatory. e.g for Andor camera we could have:
# self.__FastTrigger = {'ON':True,
# 'OFF':False}
# self.__Cooler = {'ON': True,
# 'OFF': False}
# self.__ShutterLevel = {'LOW':0,
# 'HIGH':1}
# self.__Attribute2FunctionBase = {'fast_trigger': 'FastExtTrigger',
# 'shutter_level': 'ShutterLevel',
# 'temperature': 'Temperature',
# 'temperature_sp': 'TemperatureSP',
# 'cooler': 'Cooler',
# 'cooling_status': 'CoolingStatus',
# }
# __Attribute2FunctionBase dict. maps attributes and commands (e.g. fast_trigger --> setFastExtTrigger and getFastExtTrigger)
# __FasTrigger dict. is the enum list for the attribute fast_trigger. Naming convention supposes the attribute name composed
# with words separated by "_" and the enum dictionnary name is composed with the same words titled.
#
# Finally you will need to overload your __getattr__ class method and to call the help function get_attr_4u e.g:
#
# def __getattr__(self, name):
# return get_attr_4u(self, name, _AndorCamera)
#
import PyTango
def _getDictKey(dict, value):
try:
ind = dict.values().index(value)
except ValueError:
return None
return dict.keys()[ind]
def _getDictValue(dict, key):
try:
value = dict[key.upper()]
except KeyError:
return None
return value
## @brief Class for genenic read_<attribute> with enum value
class CallableReadEnum:
def __init__(self,dictionnary,func2Call) :
self.__dict = dictionnary
self.__func2Call = func2Call
def __call__(self,attr) :
value = _getDictKey(self.__dict,self.__func2Call())
attr.set_value(value)
## @brief Class for genenic write_<attribute> with enum value
class CallableWriteEnum:
def __init__(self,attr_name,dictionnary,func2Call) :
self.__attr_name = attr_name
self.__dict = dictionnary
self.__func2Call = func2Call
def __call__(self,attr) :
data = attr.get_write_value()
value = _getDictValue(self.__dict,data.upper())
if value is None:
PyTango.Except.throw_exception('WrongData',\
'Wrong value %s: %s'%(self.__attr_name,data.upper()),\
'LimaCCD Class')
else:
self.__func2Call(value)
## @brief Class for genenic read_<attribute> with simple value
class CallableRead:
def __init__(self,func2Call) :
self.__func2Call = func2Call
def __call__(self,attr) :
value = self.__func2Call()
attr.set_value(value)
## @brief Class for genenic write_<attribute> with simple value
class CallableWrite:
def __init__(self,attr_name,func2Call) :
self.__attr_name = attr_name
self.__func2Call = func2Call
def __call__(self,attr) :
value = attr.get_write_value()
if value is None:
PyTango.Except.throw_exception('WrongData',\
'Wrong value %s: %s'%(self.__attr_name,data.upper()),\
'LimaCCD Class')
else:
self.__func2Call(value)
## @brief helper for automatic attribute to command mapping
# To be called from __getattr__
def get_attr_4u(obj,name,interface) :
if name.startswith('read_') or name.startswith('write_') :
split_name = name.split('_')[1:]
attr_name = ''.join([x.title() for x in split_name])
dict_name = '_' + obj.__class__.__name__ + '__' + attr_name
d = getattr(obj,dict_name,None)
dict_name = '_' + obj.__class__.__name__ + '__Attribute2FunctionBase'
dict_name = getattr(obj,dict_name,None)
if dict_name:
attr_name = dict_name.get('_'.join(split_name),attr_name)
if d:
if name.startswith('read_') :
functionName = 'get' + attr_name
function2Call = getattr(interface,functionName)
callable_obj = CallableReadEnum(d,function2Call)
else:
functionName = 'set' + attr_name
function2Call = getattr(interface,functionName)
callable_obj = CallableWriteEnum('_'.join(split_name),
d,function2Call)
else:
if name.startswith('read_') :
functionName = 'get' + attr_name
function2Call = getattr(interface,functionName)
callable_obj = CallableRead(function2Call)
else:
functionName = 'set' + attr_name
function2Call = getattr(interface,functionName)
callable_obj = CallableWrite('_'.join(split_name),
function2Call)
obj.__dict__[name] = callable_obj
return callable_obj
raise AttributeError('%s has no attribute %s' % (obj.__class__.__name__,name))
## @brief return list of posible value for attribute name
def get_attr_string_value_list(obj, attr_name):
valueList = []
dict_name = '_' + obj.__class__.__name__ + '__' + ''.join([x.title() for x in attr_name.split('_')])
d = getattr(obj,dict_name,None)
if d:
valueList = d.keys()
return valueList