Commit 17d22e18 authored by Cyril Guilloud's avatar Cyril Guilloud
Browse files

add __info__ for counters:

* SamplingCounter
* IntegratingCounter
* SoftCounter
parent 62a5ef6a
Pipeline #18555 failed with stages
in 31 minutes and 1 second
......@@ -16,6 +16,7 @@ import numpy
from bliss import global_map
from bliss.common.utils import autocomplete_property
from bliss.common.logtools import log_error
def add_conversion_function(obj, method_name, function):
......@@ -42,7 +43,7 @@ class SamplingMode(enum.IntEnum):
* STATS: in addition to MEAN, use iterative algorithms to emit std,min,max,N etc.
* SAMPLES: in addition to MEAN, emit also individual samples as 1D array
* SINGLE: emit the first value (if possible: call read only once)
* LAST: emit the last value
* LAST: emit the last value
* INTEGRATE: emit MEAN multiplied by counting time
"""
......@@ -112,6 +113,18 @@ class Counter:
def get_metadata(self):
return {}
def __info__(self):
info_str = "Counter info:\n"
info_str += f" name = {self.name} \n"
info_str += f" unit = {self.unit} \n"
info_str += f" shape = {self.shape} \n"
info_str += f" dtype = {self.dtype} \n"
info_str += f" fullname = {self.fullname} \n"
info_str += f" conversion_function = {self.conversion_function} \n"
info_str += f" _counter_controller = {self._counter_controller} \n"
return info_str
class SamplingCounter(Counter):
def __init__(
......@@ -169,6 +182,15 @@ class SamplingCounter(Counter):
def statistics(self):
return self._statistics
def __info__(self):
"""Standard method called by BLISS Shell info helper."""
info_str = "------ SamplingCounter ------\n"
info_str = super().info()
info_str += f"\nSamplingCounter info:\n"
info_str += f" mode = {SamplingMode(self.mrrode).name} ({self.mode})\n"
return info_str
class IntegratingCounter(Counter):
def __init__(self, name, controller, conversion_function=None, unit=None):
......@@ -177,6 +199,13 @@ class IntegratingCounter(Counter):
name, controller, conversion_function=conversion_function, unit=unit
)
def __info__(self):
"""Standard method called by BLISS Shell info helper."""
info_str = "------ IntegratingCounter ------\n"
info_str += super().info()
return info_str
class SoftCounter(SamplingCounter):
"""
......@@ -243,11 +272,11 @@ class SoftCounter(SamplingCounter):
name = value_name if name is None else name
obj_has_name = hasattr(obj, "name") and isinstance(obj.name, str)
if obj_has_name:
ctrl_name = obj.name
self.ctrl_name = obj.name
elif obj is None:
ctrl_name = name
self.ctrl_name = name
else:
ctrl_name = type(obj).__name__
self.ctrl_name = type(obj).__name__
if apply is None:
apply = lambda x: x
self.apply = apply
......@@ -256,7 +285,7 @@ class SoftCounter(SamplingCounter):
super().__init__(
name,
SoftCounterController(ctrl_name),
SoftCounterController(self.ctrl_name),
mode=mode,
unit=unit,
conversion_function=conversion_function,
......@@ -284,6 +313,15 @@ class SoftCounter(SamplingCounter):
value_func.__name__ = value_name
return value_func, value_name
def __info__(self):
"""Standard method called by BLISS Shell info helper."""
info_str = "------ SoftCounter ------\n"
info_str = super().info()
info_str += f"\nSoftCounter info:\n"
info_str += f" ctrl_name = {self.ctrl_name}\n"
return info_str
class CalcCounter(Counter):
pass
......@@ -50,7 +50,7 @@ BLISS [1]: lima_simulator.counters. ↹
should have an `__info__()` function implemented!
- The return type of `__info__()` must be `str`, otherwhise it fails and
`__repr__()` is used as fallback!
- As a rule of thumb: the retrun value of a custom `__repr__()` implementation
- As a rule of thumb: the return value of a custom `__repr__()` implementation
should not contain `\n` and should be inspired by the standard
implementation of `__repr__()` in python.
......@@ -147,27 +147,16 @@ BLISS [4]: [a]
before returning.
Example of a typical implementation of `.__info__()` method:
Example of a typical implementation of `.__info__()` method (no more need of
exception management like previously):
```python
def info(self):
def __info__(self):
"""Standard method called by BLISS Shell info helper."""
info_str = ""
info_str += " bla bla\n"
return info_str
def __info__(self):
"""Standard method called by BLISS Shell info helper."""
try:
info_string = self.info(menu=False)
except Exception:
log_error(
self,
"An error happend during execution of __info__(), "\
"use .info() to get it.",
)
return info_string
```
The equivalent of `repr(obj)` or `str(obj)` is also availabe in
......
......@@ -42,11 +42,15 @@ A `SoftCounter` object can be defined to use an encoder as a BLISS counter in a
scan by putting in the setup of a BLISS session:
```python
from bliss.common.counter import SoftCounter
<counter> = SoftCounter(<encoder>, <function used to read>, name=<counter_name>)`
```
example:
```python
from bliss.common.counter import SoftCounter
hpz_enc = SoftCounter(hpzrotid16_enc, 'read', name='hpz_enc')
```
......
......@@ -30,7 +30,7 @@ your object with a bliss `SoftCounter`:
```python
from bliss.common.standard import loopscan
from bliss.common.measurement import SoftCounter
from bliss.common.counter import SoftCounter
# counter from an object property
pot_counter = SoftCounter(pot, 'potential')
......@@ -48,8 +48,9 @@ loopscan(10, 0.1, pot_counter, milivol_counter)
Functions can also be made counters. Here is how:
```python
from bliss.common.counter import SoftCounter
import random
random_counter = SoftCounter(value=random.random, name='aleat')
```
......@@ -57,7 +58,7 @@ random_counter = SoftCounter(value=random.random, name='aleat')
Particularly useful might be tango attributes or commands as counters:
```python
from bliss.common.counter import SoftCounter
from bliss.common.tango import DeviceProxy
fe = DeviceProxy('orion:10000/fe/id/00')
......@@ -67,4 +68,4 @@ sr_curr_counter = SoftCounter(fe, value='sr_current')
!!! note
On the fly counters are not necessarily associated with bliss objects. As
so, they don't have a reserved name in the bliss namespace and therefore
they cannot be added to a measurement group.
\ No newline at end of file
they cannot be added to a measurement group.
......@@ -518,3 +518,23 @@ def test_tango_attr_counter(beacon, dummy_tango_server, session):
# Test missing uri
with pytest.raises(KeyError):
no_uri_counter = beacon.get("no_uri_counter")
def test_info_counters(beacon):
"""
execute .__info__() method of 3 types of counters.
"""
mot_robz = beacon.get("robz")
# SamplingCounter
diode1 = beacon.get("diode")
# IntegratingCounter
diode2 = beacon.get("integ_diode")
# SoftCounter
soft_cnt = SoftCounter(mot_robz, "position")
diode1.__info__()
diode2.__info__()
soft_cnt.__info__()
Supports Markdown
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