Commit fcde1fcc authored by Sebastien Petitdemange's avatar Sebastien Petitdemange

Merge branch 'wardrobe_improvements' into 'master'

Wardrobe improvements

See merge request !1340
parents 4aacf976 915c9e2c
Pipeline #11430 failed with stages
in 1 minute and 33 seconds
This diff is collapsed.
......@@ -206,7 +206,7 @@ class ScanSaving(ParametersWardrobe):
return keys + ["session", "get", "get_path", "get_parent_node", "writer"]
def __repr__(self):
d = self.to_dict()
d = self._get_instance(self.current_instance)
d["scan_name"] = "scan name"
d["scan_number"] = "scan number"
d["img_acq_device"] = "<images_* only> acquisition device name"
......@@ -198,31 +198,192 @@ The `QueueSetting` class is used to represent a list of scalar values:
## ParametersWardrobe
`ParametersWardrobe` are more advanced objects -- it is used to group
simple settings, and to be able to switch from one set of values for
the parameters to another:
`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 easly.
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 some **suit of clothes**
to choose from, for example: working suit, night suit, swimming suit.
Let's to an example with a `dress` object,
BLISS [10]: dress = ParametersWardrobe('dress') # this creates a Wardrobe with a 'default' instance
BLISS [11]: dress.current_istance
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'
So you have your default suit of dress that you can use with dotted notation inside your code:
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`.
Whe can change values and visualize them. If no value is assigned to the instance
default is taken.
Let's add *another instance* and use a method to visualize all instances in a
tabular form:
>>> from bliss.config.settings import ParametersWardrobe
>>> p = ParametersWardrobe("my_params")
>>> p.add("test", 42)
>>> p
Parameters (default)
.test = 42
>>> p.test
>>> p.test=43
>>> p.configs
>>> p.switch("another_config") - default
>>> p.add("test2", 10)
>>> p
Parameters (another_config) - default
.test2 = 10
>>> p.switch("default")
>>> p
Parameters (default)
.test = 43
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 do 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 given a list of methods and purposes of ParameterWardrobe. To understand
the details of usage just read the docstring with python `help(...)` method from Bliss shell.
#### .add
To add a new attribute to the Wardrobe
#### .switch
To switch current instance to another one and creating a new one if does not exist.
#### .remove
Allows deleting instances or attributes
#### .freeze
Freezes the current instance hardwriting values that are taken from default.
#### .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
This diff is collapsed.
......@@ -45,12 +45,11 @@ def test_scan_saving(beacon, scan_saving):
assert parent_node.parent.parent.db_name == scan_saving.session
assert parent_node.db_name == "%s:tmp:%s" % (scan_saving.session, "toto")
assert (
== """\
scan_saving_repr = """\
Parameters (default) -
.base_path = '/tmp'
.creation_date = '{creation_date}'
.data_filename = 'data'
.date = '{date}'
.date_format = '%Y%m%d'
......@@ -58,6 +57,7 @@ Parameters (default) -
.images_path_template = 'scan{{scan_number}}'
.images_prefix = '{{img_acq_device}}_'
.img_acq_device = '<images_* only> acquisition device name'
.last_accessed = '{last_accessed}'
.scan_name = 'scan name'
.scan_number = 'scan number'
.scan_number_format = '%04d'
......@@ -66,12 +66,15 @@ Parameters (default) -
.user_name = '{user_name}'
.writer = 'hdf5'
assert repr(scan_saving) == scan_saving_repr
scan_saving.template = "toto/{session}"
parent_node = scan_saving.get()["parent"]
assert == scan_saving.session
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment