Voltage and slow adc naming (#772)

* voltages in python 

* added voltage values in cmd line, added voltagelist in detector class

* voltage values in python

* slow adc list
This commit is contained in:
2023-07-10 16:10:23 +02:00
committed by GitHub
parent fe4db54eb6
commit 054e733cd5
17 changed files with 842 additions and 353 deletions

View File

@ -27,6 +27,8 @@ set( PYTHON_FILES
slsdet/__init__.py
slsdet/adcs.py
slsdet/dacs.py
slsdet/voltages.py
slsdet/slowadcs.py
slsdet/decorators.py
slsdet/detector_property.py
slsdet/detector.py

View File

@ -4,6 +4,8 @@
from .eiger import Eiger
from .ctb import Ctb
from .dacs import DetectorDacs, Dac
from .voltages import DetectorVoltages, Voltage
from .slowadcs import DetectorSlowAdcs, SlowAdc
from .detector import Detector
from .jungfrau import Jungfrau
from .mythen3 import Mythen3

View File

@ -3,6 +3,8 @@
from .detector import Detector, freeze
from .utils import element_if_equal
from .dacs import DetectorDacs, NamedDacs
from .voltages import DetectorVoltages, NamedVoltages
from .slowadcs import DetectorSlowAdcs, NamedSlowAdcs
import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty
@ -15,8 +17,17 @@ class Ctb(Detector):
super().__init__(id)
self._frozen = False
self._dacs = NamedDacs(self)
self._voltages = NamedVoltages(self)
self._slowadcs = NamedSlowAdcs(self)
@property
def dacs(self):
return self._dacs
@property
def voltages(self):
return self._voltages
@property
def slowadcs(self):
return self._slowadcs

View File

@ -1837,6 +1837,22 @@ class Detector(CppDetectorApi):
for dac in self.getDacList()
}
@property
def voltagevalues(self):
"""Gets the voltage values for every voltage for this detector."""
return {
voltage.name.lower(): element_if_equal(np.array(self.getVoltage(voltage)))
for voltage in self.getVoltageList()
}
@property
def slowadcvalues(self):
"""Gets the slow adc values for every slow adc for this detector."""
return {
slowadc.name.lower(): element_if_equal(np.array(self.getSlowADC(slowadc)))
for slowadc in self.getSlowADCList()
}
@property
def timinglist(self):
"""Gets the list of timing modes (timingMode) for this detector."""
@ -3755,45 +3771,45 @@ class Detector(CppDetectorApi):
@element
def v_a(self):
"""[Ctb] Voltage supply a in mV."""
return self.getDAC(dacIndex.V_POWER_A, True)
return self.getVoltage(dacIndex.V_POWER_A)
@v_a.setter
def v_a(self, value):
value = ut.merge_args(dacIndex.V_POWER_A, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_POWER_A, value)
ut.set_using_dict(self.setVoltage, *value)
@property
@element
def v_b(self):
"""[Ctb] Voltage supply b in mV."""
return self.getDAC(dacIndex.V_POWER_B, True)
return self.getVoltage(dacIndex.V_POWER_B)
@v_b.setter
def v_b(self, value):
value = ut.merge_args(dacIndex.V_POWER_B, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_POWER_B, value)
ut.set_using_dict(self.setVoltage, *value)
@property
@element
def v_c(self):
"""[Ctb] Voltage supply c in mV."""
return self.getDAC(dacIndex.V_POWER_C, True)
return self.getVoltage(dacIndex.V_POWER_C)
@v_c.setter
def v_c(self, value):
value = ut.merge_args(dacIndex.V_POWER_C, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_POWER_C, value)
ut.set_using_dict(self.setVoltage, *value)
@property
@element
def v_d(self):
"""[Ctb] Voltage supply d in mV."""
return self.getDAC(dacIndex.V_POWER_D, True)
return self.getVoltage(dacIndex.V_POWER_D)
@v_d.setter
def v_d(self, value):
value = ut.merge_args(dacIndex.V_POWER_D, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_POWER_D, value)
ut.set_using_dict(self.setVoltage, *value)
@property
@element
@ -3804,23 +3820,23 @@ class Detector(CppDetectorApi):
----
Must be the first power regulator to be set after fpga reset (on-board detector server start up).
"""
return self.getDAC(dacIndex.V_POWER_IO, True)
return self.getVoltage(dacIndex.V_POWER_IO)
@v_io.setter
def v_io(self, value):
value = ut.merge_args(dacIndex.V_POWER_IO, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_POWER_IO, value)
ut.set_using_dict(self.setVoltage, *value)
@property
@element
def v_limit(self):
"""[Ctb] Soft limit for power supplies (ctb only) and DACS in mV."""
return self.getDAC(dacIndex.V_LIMIT, True)
return self.getVoltage(dacIndex.V_LIMIT)
@v_limit.setter
def v_limit(self, value):
value = ut.merge_args(dacIndex.V_LIMIT, value, True)
ut.set_using_dict(self.setDAC, *value)
value = ut.merge_args(dacIndex.V_LIMIT, value)
ut.set_using_dict(self.setVoltage, *value)
@property

195
python/slsdet/slowadcs.py Executable file
View File

@ -0,0 +1,195 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
from .detector_property import DetectorProperty
from functools import partial
import numpy as np
import _slsdet
from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex
class SlowAdc(DetectorProperty):
"""
This class represents a slowadc on the Chip Test Board. One instance handles all
slowadcs with the same name for a multi detector instance. (TODO: Not needed for CTB)
.. note ::
This class is used to build up DetectorSlowAdcs and is in general
not directly accessible to the user.
"""
def __init__(self, name, enum, default, detector):
super().__init__(partial(detector.getVoltage, enum),
lambda x, y : detector.setVoltage(enum, x, y),
detector.size,
name)
self.default = default
def __repr__(self):
"""String representation for a single slowadc in all modules"""
slowadcstr = ''.join([f'{item:5d}' for item in self.get()])
return f'{self.__name__:15s}:{slowadcstr}'
class NamedSlowAdcs:
"""
New implementation of the detector slowadcs.
"""
_frozen = False
_direct_access = ['_detector', '_current', '_voltagenames']
def __init__(self, detector):
self._detector = detector
self._current = 0
#only get the voltagenames if we have modules attached
if detector.size() == 0:
self._voltagenames = ["VA", "VB", "VC", "VD", "VIO"]
else:
self._voltagenames = [n.replace(" ", "") for n in detector.getVoltageNames()]
# Populate the slowadcs
for i,name in enumerate(self._voltagenames):
#name, enum, low, high, default, detector
k = dacIndex(i + int(dacIndex.V_POWER_A))
setattr(self, name, SlowAdc(name, k, 0, detector))
self._frozen = True
# def __getattr__(self, name):
# return self.__getattribute__('_' + name)
def __setattr__(self, name, value):
if not self._frozen:
#durning init we need to be able to set up the class
super().__setattr__(name, value)
else:
#Later we restrict us to manipulate slowadcs and a few fields
if name in self._direct_access:
super().__setattr__(name, value)
elif name in self._voltagenames:
return self.__getattribute__(name).__setitem__(slice(None, None), value)
else:
raise AttributeError(f'SlowAdc not found: {name}')
def __next__(self):
if self._current >= len(self._voltagenames):
self._current = 0
raise StopIteration
else:
self._current += 1
return self.__getattribute__(self._voltagenames[self._current-1])
# return self.__getattr__(self._voltagenames[self._current-1])
def __iter__(self):
return self
def __repr__(self):
r_str = ['========== SLOW ADCS =========']
r_str += [repr(slowadc) for slowadc in self]
return '\n'.join(r_str)
def get_asarray(self):
"""
Read the slowadcs into a numpy array with dimensions [nslowadcs, nmodules]
"""
voltage_array = np.zeros((len(self._voltagenames), len(self._detector)))
for i, _d in enumerate(self):
voltage_array[i,:] = _d[:]
return voltage_array
def to_array(self):
return self.get_asarray()
def set_from_array(self, voltage_array):
"""
Set the slowadc from an numpy array with slowadc values. [nslowadcs, nmodules]
"""
voltage_array = voltage_array.astype(np.int)
for i, _d in enumerate(self):
_d[:] = voltage_array[i]
def from_array(self, voltage_array):
self.set_from_array(voltage_array)
class DetectorSlowAdcs:
_slowadcs = []
_voltagenames = [_d[0] for _d in _slowadcs]
_allowed_attr = ['_detector', '_current']
_frozen = False
def __init__(self, detector):
# We need to at least initially know which detector we are connected to
self._detector = detector
# Index to support iteration
self._current = 0
# Name the attributes?
for _d in self._slowadcs:
setattr(self, '_'+_d[0], SlowAdc(*_d, detector))
self._frozen = True
def __getattr__(self, name):
return self.__getattribute__('_' + name)
@property
def voltagenames(self):
return [_d[0] for _d in _slowadcs]
def __setattr__(self, name, value):
if name in self._voltagenames:
return self.__getattribute__('_' + name).__setitem__(slice(None, None), value)
else:
if self._frozen == True and name not in self._allowed_attr:
raise AttributeError(f'SlowAdc not found: {name}')
super().__setattr__(name, value)
def __next__(self):
if self._current >= len(self._slowadcs):
self._current = 0
raise StopIteration
else:
self._current += 1
return self.__getattr__(self._voltagenames[self._current-1])
def __iter__(self):
return self
def __repr__(self):
r_str = ['========== SLOW ADCS =========']
r_str += [repr(slowadc) for slowadc in self]
return '\n'.join(r_str)
def get_asarray(self):
"""
Read the slowadcs into a numpy array with dimensions [nslowadcs, nmodules]
"""
voltage_array = np.zeros((len(self._slowadcs), len(self._detector)))
for i, _d in enumerate(self):
voltage_array[i,:] = _d[:]
return voltage_array
def to_array(self):
return self.get_asarray()
def set_from_array(self, voltage_array):
"""
Set the slowadcs from an numpy array with slowadc values. [nslowadcs, nmodules]
"""
voltage_array = voltage_array.astype(np.int)
for i, _d in enumerate(self):
_d[:] = voltage_array[i]
def from_array(self, voltage_array):
self.set_from_array(voltage_array)
def set_default(self):
"""
Set all slowadcs to their default values
"""
for _d in self:
_d[:] = _d.default

195
python/slsdet/voltages.py Executable file
View File

@ -0,0 +1,195 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
from .detector_property import DetectorProperty
from functools import partial
import numpy as np
import _slsdet
from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex
class Voltage(DetectorProperty):
"""
This class represents a voltage on the Chip Test Board. One instance handles all
voltages with the same name for a multi detector instance. (TODO: Not needed for CTB)
.. note ::
This class is used to build up DetectorVoltages and is in general
not directly accessible to the user.
"""
def __init__(self, name, enum, default, detector):
super().__init__(partial(detector.getVoltage, enum),
lambda x, y : detector.setVoltage(enum, x, y),
detector.size,
name)
self.default = default
def __repr__(self):
"""String representation for a single voltage in all modules"""
voltagestr = ''.join([f'{item:5d}' for item in self.get()])
return f'{self.__name__:15s}:{voltagestr}'
class NamedVoltages:
"""
New implementation of the detector voltages.
"""
_frozen = False
_direct_access = ['_detector', '_current', '_voltagenames']
def __init__(self, detector):
self._detector = detector
self._current = 0
#only get the voltagenames if we have modules attached
if detector.size() == 0:
self._voltagenames = ["VA", "VB", "VC", "VD", "VIO"]
else:
self._voltagenames = [n.replace(" ", "") for n in detector.getVoltageNames()]
# Populate the voltages
for i,name in enumerate(self._voltagenames):
#name, enum, low, high, default, detector
k = dacIndex(i + int(dacIndex.V_POWER_A))
setattr(self, name, Voltage(name, k, 0, detector))
self._frozen = True
# def __getattr__(self, name):
# return self.__getattribute__('_' + name)
def __setattr__(self, name, value):
if not self._frozen:
#durning init we need to be able to set up the class
super().__setattr__(name, value)
else:
#Later we restrict us to manipulate voltages and a few fields
if name in self._direct_access:
super().__setattr__(name, value)
elif name in self._voltagenames:
return self.__getattribute__(name).__setitem__(slice(None, None), value)
else:
raise AttributeError(f'Voltage not found: {name}')
def __next__(self):
if self._current >= len(self._voltagenames):
self._current = 0
raise StopIteration
else:
self._current += 1
return self.__getattribute__(self._voltagenames[self._current-1])
# return self.__getattr__(self._voltagenames[self._current-1])
def __iter__(self):
return self
def __repr__(self):
r_str = ['========== VOLTAGES =========']
r_str += [repr(voltage) for voltage in self]
return '\n'.join(r_str)
def get_asarray(self):
"""
Read the voltages into a numpy array with dimensions [nvoltages, nmodules]
"""
voltage_array = np.zeros((len(self._voltagenames), len(self._detector)))
for i, _d in enumerate(self):
voltage_array[i,:] = _d[:]
return voltage_array
def to_array(self):
return self.get_asarray()
def set_from_array(self, voltage_array):
"""
Set the voltage from an numpy array with voltage values. [nvoltages, nmodules]
"""
voltage_array = voltage_array.astype(np.int)
for i, _d in enumerate(self):
_d[:] = voltage_array[i]
def from_array(self, voltage_array):
self.set_from_array(voltage_array)
class DetectorVoltages:
_voltages = []
_voltagenames = [_d[0] for _d in _voltages]
_allowed_attr = ['_detector', '_current']
_frozen = False
def __init__(self, detector):
# We need to at least initially know which detector we are connected to
self._detector = detector
# Index to support iteration
self._current = 0
# Name the attributes?
for _d in self._voltages:
setattr(self, '_'+_d[0], Voltage(*_d, detector))
self._frozen = True
def __getattr__(self, name):
return self.__getattribute__('_' + name)
@property
def voltagenames(self):
return [_d[0] for _d in _voltages]
def __setattr__(self, name, value):
if name in self._voltagenames:
return self.__getattribute__('_' + name).__setitem__(slice(None, None), value)
else:
if self._frozen == True and name not in self._allowed_attr:
raise AttributeError(f'Voltage not found: {name}')
super().__setattr__(name, value)
def __next__(self):
if self._current >= len(self._voltages):
self._current = 0
raise StopIteration
else:
self._current += 1
return self.__getattr__(self._voltagenames[self._current-1])
def __iter__(self):
return self
def __repr__(self):
r_str = ['========== VOLTAGES =========']
r_str += [repr(voltage) for voltage in self]
return '\n'.join(r_str)
def get_asarray(self):
"""
Read the voltages into a numpy array with dimensions [nvoltages, nmodules]
"""
voltage_array = np.zeros((len(self._voltages), len(self._detector)))
for i, _d in enumerate(self):
voltage_array[i,:] = _d[:]
return voltage_array
def to_array(self):
return self.get_asarray()
def set_from_array(self, voltage_array):
"""
Set the voltages from an numpy array with voltage values. [nvoltages, nmodules]
"""
voltage_array = voltage_array.astype(np.int)
for i, _d in enumerate(self):
_d[:] = voltage_array[i]
def from_array(self, voltage_array):
self.set_from_array(voltage_array)
def set_default(self):
"""
Set all voltages to their default values
"""
for _d in self:
_d[:] = _d.default

View File

@ -1516,6 +1516,12 @@ void init_det(py::module &m) {
(void (Detector::*)(int, sls::Positions)) &
Detector::setADCPipeline,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getVoltageList",
(std::vector<defs::dacIndex>(Detector::*)() const) &
Detector::getVoltageList);
CppDetectorApi.def("getSlowADCList",
(std::vector<defs::dacIndex>(Detector::*)() const) &
Detector::getSlowADCList);
CppDetectorApi.def(
"getVoltage",
(Result<int>(Detector::*)(defs::dacIndex, sls::Positions) const) &
@ -1716,26 +1722,26 @@ void init_det(py::module &m) {
(std::string(Detector::*)(const defs::dacIndex) const) &
Detector::getVoltageName,
py::arg());
CppDetectorApi.def("setSlowAdcNames",
CppDetectorApi.def("setSlowADCNames",
(void (Detector::*)(const std::vector<std::string>)) &
Detector::setSlowAdcNames,
Detector::setSlowADCNames,
py::arg());
CppDetectorApi.def("getSlowAdcNames",
CppDetectorApi.def("getSlowADCNames",
(std::vector<std::string>(Detector::*)() const) &
Detector::getSlowAdcNames);
Detector::getSlowADCNames);
CppDetectorApi.def(
"getSlowAdcIndex",
"getSlowADCIndex",
(defs::dacIndex(Detector::*)(const std::string &) const) &
Detector::getSlowAdcIndex,
Detector::getSlowADCIndex,
py::arg());
CppDetectorApi.def(
"setSlowAdcName",
"setSlowADCName",
(void (Detector::*)(const defs::dacIndex, const std::string &)) &
Detector::setSlowAdcName,
Detector::setSlowADCName,
py::arg(), py::arg());
CppDetectorApi.def("getSlowAdcName",
CppDetectorApi.def("getSlowADCName",
(std::string(Detector::*)(const defs::dacIndex) const) &
Detector::getSlowAdcName,
Detector::getSlowADCName,
py::arg());
CppDetectorApi.def(
"getPatterFileName",