Beacon settings¶
Settings¶
Beacon settings are helper classes to store data in the Redis database at runtime from Python code, using BLISS.
Use cases for settings:
-
on top of static configuration parameters
- motor velocity, acceleration, limits
- auto-gain on a Keithley
-
to persistently keep (or share) information across executions (or across processes)
- selected counter for plot
- enabled loggers, log level
- scan saving path, file template…
Direct access to the Redis database
redis-cli
is a command-line tool to directly access to the Redis database.
redis-cli -s /tmp/redis.sock -n 0
WARNING: redis-cli
must be used with care, alteration of the database integrity
can lead to very strange behaviour.
Never forget: “With great power comes great responsibility”
BLISS provides different classes for different kinds of settings.
SimpleSetting¶
The SimpleSetting
class is used to store a scalar value:
- int
- float
- string
- bool
Main usages are:
-
to create the setting with a default value:
sss = SimpleSetting(<key>, default_value=<value>)
-
to set a value to store:
sss.set()
- to read the stored value:
sss.get()
- to reset the value to the default one:
sss.clear()
SimpleSetting Example¶
from blissdata import settings
magicNumber = 63825363
sss = settings.SimpleSetting('myIntkey', default_value=magicNumber)
print(sss)
# <SimpleSetting name=myIntkey value=None>
print(sss.get())
# 63825363 # this is the default value.
sss.set(42)
print(sss)
# <SimpleSetting name=myIntkey value=b'42'>
print(sss.get())
# 42
sss.clear()
print(sss.get())
# 63825363
sss.set(3.14)
redis-cli
can be used to inspect the redis database:
% redis-cli -s /tmp/redis.sock -n 0
redis /tmp/redis.sock> keys my*
1) "myHkey"
2) "myIntkey"
redis /tmp/redis.sock> get myIntkey
"3.14"
After a restart of the session (or from another session):
from blissdata import settings
sss = settings.SimpleSetting('myIntkey')
print(sss.get())
# 3.14
After a .clear()
, the key is removed from Redis database:
sss.clear()
redis /tmp/redis.sock> keys myIntkey
(empty list or set)
SimpleSetting behaviour¶
After instanciation (sss = SimpleSetting('aKey', default_value=42)
), the
SimpleSetting
object returns the default_value
. This default value is NOT
saved in Redis database.
After a value has been set to the SimpleSetting
object (sss.set(3.14)
):
- this value is stored in the Redis database
SimpleSetting
object returns this value (sss.get()
)
After a clear()
(sss.clear()
), the key is removed from Redis database and
the SimpleSetting
object returns again the default_value
.
Note
default_value
can be None
, but a SimpleSetting
cannot be set to None
.
BaseHashSetting and HashSetting¶
The BaseHashSetting
class is used to represent a dictionary of
scalar values. HashSetting
simply adds a kwarg (keyword argument)
default_values
that is a dictionary containing values taken as a fallback.
from blissdata import settings
myDict = {"key1":"value1", "key2":"value2"}
hs = settings.HashSetting('myHkey', default_values=myDict)
# note the 's' in default_values
# 'hs' acts now as a dictionary.
print(hs["key1"])
# value1
print(hs["key2"])
# value2
hs["key1"]=3333
print(hs["key1"])
# 3333
Redis stores only key/value pairs that have changed:
% redis-cli -s /tmp/redis.sock -n 0
redis /tmp/redis.sock> hgetall myHkey
1) "key1"
2) "3333"
After a .clear()
, the key is removed from Redis database.
A key can be added and removed:
bliss session:
hs["newKey"]=45
redis:
hgetall myHkey
1) "key1"
2) "3333"
3) "newKey"
4) "45"
bliss session:
hs.remove("newKey")
redis:
redis /tmp/redis.sock> hgetall myHkey
1) "key1"
2) "3333"
QueueSetting¶
The QueueSetting
class is used to represent a list of scalar values:
>>> myList = ["a", "b", "c", "d"]
>>> sqs = settings.QueueSetting('myQkey')
>>> sqs.set(myList)
ParametersWardrobe¶
ParametersWardrobe
is a more advanced object used to group
simple settings and to be able to switch from one set of values to another set easily.
We call the different sets with the name of instances
.
Every instance has a name
and share the same attributes with other instances.
You can imagine and visualize a ParameterWardrobe as a table where rows are the attributes and column are the instances. In fact we can use the values from one column/instance at a time.
The name of ParameterWardrobe comes from the idea of having some parts of the body to dress and suits of clothes to choose from, for example: working suit, night suit, swimming suit.
Let’s try an example with a dress
object,
BLISS [10]: dress = settings.ParametersWardrobe('dress') # this creates a Wardrobe with a 'default' instance
BLISS [11]: dress.current_instance
BLISS [11]: 'default'
BLISS [12]: dress.add('body','shirt') # adding some slots default dressing
BLISS [13]: dress.add('head','nothing')
BLISS [14]: dress.add('feet','tennis shoes')
BLISS [15]: dress.add('legs','jeans')
BLISS [16]: dress
Out [17]: Parameters (default) -
.body = 'shirt'
.creation_date = '2019-06-05-12:38'
.feet = 'tennis shoes'
.head = 'nothing'
.last_accessed = '2019-06-05-12:38'
.legs = 'jeans'
BLISS [25]: dress.body
Out [25]: 'shirt'
BLISS [26]: dress.body = "T shirt"
BLISS [27]: dress.body
Out [27]: 'T shirt'
Values can be accessed and changed using dot notation.
At this point you would like to add another suit of clothes:
BLISS [28]: dress.switch("Night dress")
BLISS [29]: dress
Out [29]: Parameters (Night dress) - default
.body = 'T shirt'
.creation_date = '2019-06-05-14:30'
.feet = 'tennis shoes'
.head = 'nothing'
.last_accessed = '2019-06-05-14:30'
.legs = 'jeans'
BLISS [30]: dress.body = 'Jacket'
BLISS [31]: dress.feet = "Nice shoes"
BLISS [32]: dress.legs = "Black trousers"
BLISS [33]: dress
Out [33]: Parameters (Night dress) - default
.body = 'Jacket'
.creation_date = '2019-06-05-14:30'
.feet = 'Nice shoes'
.head = 'nothing'
.last_accessed = '2019-06-05-14:30'
.legs = 'Black trousers'
Now we have two instances of dress and we are currently using Night dress
.
We can change values and visualize them. If no value is assigned to the instance, the default is taken.
Let’s add another instance and use a method to visualize all instances in a tabular form:
BLISS [34]: dress.switch('swim')
BLISS [35]: dress.feet = "nothing"
BLISS [36]: dress.head = "swim glasses"
BLISS [37]: dress.body = "nothing"
BLISS [38]: dress.legs = "swimsuit"
BLISS [39]: dress.instances
Out [39]: ['swim', 'Night dress', 'default']
BLISS [40]: dress.show_table()
* asterisks means value not stored in database (default is taken)
# hash means a computed attribute (property)
swim (SELECTED) Night dress default
------------- ------------------ ------------------ ------------------
body nothing Jacket T shirt
creation_date # 2019-06-05-14:37 # 2019-06-05-14:30 # 2019-06-05-12:38
feet nothing Nice shoes tennis shoes
head swim glasses * nothing nothing
last_accessed # 2019-06-05-14:37 # 2019-06-05-14:30 # 2019-06-05-12:38
legs swimsuit Black trousers jeans
With .show_table()
we have a complete vision of what is contained in all instances
.
ParametersWardrobe can handle all basic types of data like:
- string
- bool
- list (including numpy array)
- tuple
- dict
- set
Let’s have another example:
BLISS [40]: all = ParametersWardrobe('all')
BLISS [41]: all.add('bool',True)
BLISS [42]: all.add('dict', {'index':'value'})
BLISS [43]: all.add('list') # without passing a default value (will be None)
BLISS [44]: all.list = [1,2,3] # assigning a value later
BLISS [45]: import numpy
BLISS [46]: numpy.ndarray((1,2,3))
Out [46]: array([[[ 6.91528554e-310, 4.64581452e-310, 5.86245261e-160],
[ 6.91528554e-310, 4.64581452e-310, -1.39151878e+147]]])
BLISS [47]: all.list = numpy.ndarray((1,2,3))
BLISS [48]: all.list
Out [48]: array([[[6.91528554e-310, 4.64581452e-310, 5.86245261e-160],
[6.91528554e-310, 4.64581452e-310, 1.39151878e+147]]])
BLISS [49]: all
Out [49]: Parameters (default) -
.bool = True
.creation_date = '2019-06-05-14:43'
.dict = {'index': 'value'}
.last_accessed = '2019-06-05-14:43'
.list = array([[[6.91528554e-310, 4.64581452e-310, 5.86245261e-160],
[6.91528554e-310, 4.64581452e-310, 1.39151878e+147]]])
Useful methods of ParameterWardrobe are:¶
Here is a list of methods and purposes of ParameterWardrobe. To understand
the usage details, just read the docstring with python’s help(...)
method from the Bliss shell.
.add¶
To add a new attribute to the Wardrobe
.switch¶
To switch the current instance to another one and creating it if needed.
.remove or purge¶
remove
allows deleting instances or attributes.
purge
completely removes a ParametersWardrobe from redis.
.freeze¶
Freezes the current instance copying values the default instance.
.to_dict and .from_dict¶
Allows to easily import/export instances, the main purpose is to have data in a form that can be used inside shell or scripts to do computation.
.to_file and .from_file¶
Saves and imports data using yml format to and from a file.
The purpose is to dump
instances and keep a copy for backup reasons.
Not created for manipulation purposes.
Keep in mind that exporting to file in fact freezes
the data in the file,
This means that if you are using an instance that takes some values from
‘default’ instance the act of writing to the file will hardcode these values
to file.
You should be aware that an instance
imported from_file will have her
own values for every attribute and will not use default ones.
.to_beacon and .from_beacon¶
The same purpose and behaviour than to_file and from_file, but the files are saved in Beacon on a subfolder called wardrobe as .dat files.
.instances¶
Gives the list of all instance names.
.creation_date and .last_accessed¶
Read only values (properties) that gives some information for ParameterWardrobe maintenance.