mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-11 04:17:15 +02:00
3. Dev/voltage to power (#816)
* getVoltageList, getVoltage /set, getMeasuredVoltage, getVoltageNames /set, getVoltageIndex moved to 'Power' as its misleading * added cstdint and names slowadc, added division to mV * changed uV to mV in command line slow adc help. removed all python slowadcs (as it was already implemented as slowadc --------- Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
This commit is contained in:
@ -28,8 +28,7 @@ set( PYTHON_FILES
|
||||
slsdet/__init__.py
|
||||
slsdet/adcs.py
|
||||
slsdet/dacs.py
|
||||
slsdet/voltages.py
|
||||
slsdet/slowadcs.py
|
||||
slsdet/powers.py
|
||||
slsdet/decorators.py
|
||||
slsdet/detector_property.py
|
||||
slsdet/detector.py
|
||||
|
@ -4,8 +4,7 @@
|
||||
from .eiger import Eiger
|
||||
from .ctb import Ctb
|
||||
from .dacs import DetectorDacs, Dac
|
||||
from .voltages import DetectorVoltages, Voltage
|
||||
from .slowadcs import DetectorSlowAdcs, SlowAdc
|
||||
from .powers import DetectorPowers, Power
|
||||
from .detector import Detector
|
||||
from .jungfrau import Jungfrau
|
||||
from .mythen3 import Mythen3
|
||||
|
@ -3,8 +3,7 @@
|
||||
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
|
||||
from .powers import DetectorPowers, NamedPowers
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
from .detector_property import DetectorProperty
|
||||
@ -17,17 +16,12 @@ class Ctb(Detector):
|
||||
super().__init__(id)
|
||||
self._frozen = False
|
||||
self._dacs = NamedDacs(self)
|
||||
self._voltages = NamedVoltages(self)
|
||||
self._slowadcs = NamedSlowAdcs(self)
|
||||
self._powers = NamedPowers(self)
|
||||
|
||||
@property
|
||||
def dacs(self):
|
||||
return self._dacs
|
||||
|
||||
@property
|
||||
def voltages(self):
|
||||
return self._voltages
|
||||
|
||||
@property
|
||||
def slowadcs(self):
|
||||
return self._slowadcs
|
||||
def powers(self):
|
||||
return self._powers
|
@ -1839,17 +1839,17 @@ class Detector(CppDetectorApi):
|
||||
self.setSignalNames(value)
|
||||
|
||||
@property
|
||||
def voltagelist(self):
|
||||
def powerlist(self):
|
||||
"""
|
||||
List of names for every voltage for this board. 5 voltage supply
|
||||
List of names for every power for this board. 5 power supply
|
||||
:setter: Only implemented for Chiptestboard
|
||||
|
||||
"""
|
||||
return self.getVoltageNames()
|
||||
return self.getPowerNames()
|
||||
|
||||
@voltagelist.setter
|
||||
def voltagelist(self, value):
|
||||
self.setVoltageNames(value)
|
||||
@powerlist.setter
|
||||
def powerlist(self, value):
|
||||
self.setPowerNames(value)
|
||||
|
||||
@property
|
||||
def slowadclist(self):
|
||||
@ -1873,11 +1873,11 @@ class Detector(CppDetectorApi):
|
||||
}
|
||||
|
||||
@property
|
||||
def voltagevalues(self):
|
||||
"""Gets the voltage values for every voltage for this detector."""
|
||||
def powervalues(self):
|
||||
"""Gets the power values for every power for this detector."""
|
||||
return {
|
||||
voltage.name.lower(): element_if_equal(np.array(self.getVoltage(voltage)))
|
||||
for voltage in self.getVoltageList()
|
||||
power.name.lower(): element_if_equal(np.array(self.getPower(power)))
|
||||
for power in self.getPowerList()
|
||||
}
|
||||
|
||||
@property
|
||||
@ -3846,73 +3846,73 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
def v_a(self):
|
||||
"""[Ctb] Voltage supply a in mV."""
|
||||
return self.getVoltage(dacIndex.V_POWER_A)
|
||||
"""[Ctb] Power supply a in mV."""
|
||||
return self.getPower(dacIndex.V_POWER_A)
|
||||
|
||||
@v_a.setter
|
||||
def v_a(self, value):
|
||||
value = ut.merge_args(dacIndex.V_POWER_A, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def v_b(self):
|
||||
"""[Ctb] Voltage supply b in mV."""
|
||||
return self.getVoltage(dacIndex.V_POWER_B)
|
||||
"""[Ctb] Power supply b in mV."""
|
||||
return self.getPower(dacIndex.V_POWER_B)
|
||||
|
||||
@v_b.setter
|
||||
def v_b(self, value):
|
||||
value = ut.merge_args(dacIndex.V_POWER_B, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def v_c(self):
|
||||
"""[Ctb] Voltage supply c in mV."""
|
||||
return self.getVoltage(dacIndex.V_POWER_C)
|
||||
"""[Ctb] Power supply c in mV."""
|
||||
return self.getPower(dacIndex.V_POWER_C)
|
||||
|
||||
@v_c.setter
|
||||
def v_c(self, value):
|
||||
value = ut.merge_args(dacIndex.V_POWER_C, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def v_d(self):
|
||||
"""[Ctb] Voltage supply d in mV."""
|
||||
return self.getVoltage(dacIndex.V_POWER_D)
|
||||
"""[Ctb] Power supply d in mV."""
|
||||
return self.getPower(dacIndex.V_POWER_D)
|
||||
|
||||
@v_d.setter
|
||||
def v_d(self, value):
|
||||
value = ut.merge_args(dacIndex.V_POWER_D, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def v_io(self):
|
||||
"""[Ctb] Voltage supply io in mV. Minimum 1200 mV.
|
||||
"""[Ctb] Power supply io in mV. Minimum 1200 mV.
|
||||
|
||||
Note
|
||||
----
|
||||
Must be the first power regulator to be set after fpga reset (on-board detector server start up).
|
||||
"""
|
||||
return self.getVoltage(dacIndex.V_POWER_IO)
|
||||
return self.getPower(dacIndex.V_POWER_IO)
|
||||
|
||||
@v_io.setter
|
||||
def v_io(self, value):
|
||||
value = ut.merge_args(dacIndex.V_POWER_IO, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def v_limit(self):
|
||||
"""[Ctb] Soft limit for power supplies (ctb only) and DACS in mV."""
|
||||
return self.getVoltage(dacIndex.V_LIMIT)
|
||||
return self.getPower(dacIndex.V_LIMIT)
|
||||
|
||||
@v_limit.setter
|
||||
def v_limit(self, value):
|
||||
value = ut.merge_args(dacIndex.V_LIMIT, value)
|
||||
ut.set_using_dict(self.setVoltage, *value)
|
||||
ut.set_using_dict(self.setPower, *value)
|
||||
|
||||
|
||||
@property
|
||||
|
195
python/slsdet/powers.py
Executable file
195
python/slsdet/powers.py
Executable 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 Power(DetectorProperty):
|
||||
"""
|
||||
This class represents a power on the Chip Test Board. One instance handles all
|
||||
powers with the same name for a multi detector instance. (TODO: Not needed for CTB)
|
||||
|
||||
.. note ::
|
||||
|
||||
This class is used to build up DetectorPowers and is in general
|
||||
not directly accessible to the user.
|
||||
|
||||
|
||||
"""
|
||||
def __init__(self, name, enum, default, detector):
|
||||
|
||||
super().__init__(partial(detector.getPower, enum),
|
||||
lambda x, y : detector.setPower(enum, x, y),
|
||||
detector.size,
|
||||
name)
|
||||
|
||||
self.default = default
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
"""String representation for a single power in all modules"""
|
||||
powerstr = ''.join([f'{item:5d}' for item in self.get()])
|
||||
return f'{self.__name__:15s}:{powerstr}'
|
||||
|
||||
class NamedPowers:
|
||||
"""
|
||||
New implementation of the detector powers.
|
||||
"""
|
||||
_frozen = False
|
||||
_direct_access = ['_detector', '_current', '_powernames']
|
||||
def __init__(self, detector):
|
||||
self._detector = detector
|
||||
self._current = 0
|
||||
|
||||
#only get the powernames if we have modules attached
|
||||
if detector.size() == 0:
|
||||
self._powernames = ["VA", "VB", "VC", "VD", "VIO"]
|
||||
else:
|
||||
self._powernames = [n.replace(" ", "") for n in detector.getPowerNames()]
|
||||
|
||||
# Populate the powers
|
||||
for i,name in enumerate(self._powernames):
|
||||
#name, enum, low, high, default, detector
|
||||
k = dacIndex(i + int(dacIndex.V_POWER_A))
|
||||
setattr(self, name, Power(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 powers and a few fields
|
||||
if name in self._direct_access:
|
||||
super().__setattr__(name, value)
|
||||
elif name in self._powernames:
|
||||
return self.__getattribute__(name).__setitem__(slice(None, None), value)
|
||||
else:
|
||||
raise AttributeError(f'Power not found: {name}')
|
||||
|
||||
def __next__(self):
|
||||
if self._current >= len(self._powernames):
|
||||
self._current = 0
|
||||
raise StopIteration
|
||||
else:
|
||||
self._current += 1
|
||||
return self.__getattribute__(self._powernames[self._current-1])
|
||||
# return self.__getattr__(self._powernames[self._current-1])
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __repr__(self):
|
||||
r_str = ['========== POWERS =========']
|
||||
r_str += [repr(power) for power in self]
|
||||
return '\n'.join(r_str)
|
||||
def get_asarray(self):
|
||||
"""
|
||||
Read the powers into a numpy array with dimensions [npowers, nmodules]
|
||||
"""
|
||||
power_array = np.zeros((len(self._powernames), len(self._detector)))
|
||||
for i, _d in enumerate(self):
|
||||
power_array[i,:] = _d[:]
|
||||
return power_array
|
||||
|
||||
def to_array(self):
|
||||
return self.get_asarray()
|
||||
|
||||
def set_from_array(self, power_array):
|
||||
"""
|
||||
Set the power from an numpy array with power values. [npowers, nmodules]
|
||||
"""
|
||||
power_array = power_array.astype(np.int)
|
||||
for i, _d in enumerate(self):
|
||||
_d[:] = power_array[i]
|
||||
|
||||
def from_array(self, power_array):
|
||||
self.set_from_array(power_array)
|
||||
|
||||
class DetectorPowers:
|
||||
_powers = []
|
||||
_powernames = [_d[0] for _d in _powers]
|
||||
_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._powers:
|
||||
setattr(self, '_'+_d[0], Power(*_d, detector))
|
||||
|
||||
self._frozen = True
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.__getattribute__('_' + name)
|
||||
|
||||
@property
|
||||
def powernames(self):
|
||||
return [_d[0] for _d in _powers]
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name in self._powernames:
|
||||
return self.__getattribute__('_' + name).__setitem__(slice(None, None), value)
|
||||
else:
|
||||
if self._frozen == True and name not in self._allowed_attr:
|
||||
raise AttributeError(f'Power not found: {name}')
|
||||
super().__setattr__(name, value)
|
||||
|
||||
|
||||
def __next__(self):
|
||||
if self._current >= len(self._powers):
|
||||
self._current = 0
|
||||
raise StopIteration
|
||||
else:
|
||||
self._current += 1
|
||||
return self.__getattr__(self._powernames[self._current-1])
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __repr__(self):
|
||||
r_str = ['========== POWERS =========']
|
||||
r_str += [repr(power) for power in self]
|
||||
return '\n'.join(r_str)
|
||||
|
||||
def get_asarray(self):
|
||||
"""
|
||||
Read the powers into a numpy array with dimensions [npowers, nmodules]
|
||||
"""
|
||||
power_array = np.zeros((len(self._powers), len(self._detector)))
|
||||
for i, _d in enumerate(self):
|
||||
power_array[i,:] = _d[:]
|
||||
return power_array
|
||||
|
||||
def to_array(self):
|
||||
return self.get_asarray()
|
||||
|
||||
def set_from_array(self, power_array):
|
||||
"""
|
||||
Set the powers from an numpy array with power values. [npowers, nmodules]
|
||||
"""
|
||||
power_array = power_array.astype(np.int)
|
||||
for i, _d in enumerate(self):
|
||||
_d[:] = power_array[i]
|
||||
|
||||
def from_array(self, power_array):
|
||||
self.set_from_array(power_array)
|
||||
|
||||
def set_default(self):
|
||||
"""
|
||||
Set all powers to their default values
|
||||
"""
|
||||
for _d in self:
|
||||
_d[:] = _d.default
|
||||
|
@ -60,18 +60,27 @@ class SlowAdcProxy:
|
||||
|
||||
def __getitem__(self, key):
|
||||
dac_index = dacIndex(int(dacIndex.SLOW_ADC0)+key)
|
||||
return element_if_equal(self.det.getSlowADC(dac_index))
|
||||
return element_if_equal(self.det.getSlowADC(dac_index))/1000 #TODO! Multi module?
|
||||
|
||||
def __repr__(self):
|
||||
rstr = ''
|
||||
for i in range(8):
|
||||
for i,name in enumerate(self.det.getSlowADCNames()):
|
||||
r = element_if_equal(self.__getitem__(i))
|
||||
if isinstance(r, list):
|
||||
rstr += ' '.join(f'{item} uV' for item in r)
|
||||
rstr += ' '.join(f'{item/1000} mV' for item in r)
|
||||
else:
|
||||
rstr += f'{i}: {r} uV\n'
|
||||
rstr += f'[{i}] {name}: {r/1000} mV\n'
|
||||
|
||||
return rstr.strip('\n')
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self.det.getSlowADCNames():
|
||||
i = self.det.getSlowADCIndex(name)
|
||||
return element_if_equal(self.det.getSlowADC(i))
|
||||
else:
|
||||
raise ValueError(f"Could not find slow adc with name: {name}")
|
||||
|
||||
|
||||
|
||||
class ClkDivProxy:
|
||||
"""
|
||||
|
@ -1,195 +0,0 @@
|
||||
# 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
|
||||
|
@ -1,195 +0,0 @@
|
||||
# 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
|
||||
|
@ -1535,21 +1535,21 @@ void init_det(py::module &m) {
|
||||
(Result<int>(Detector::*)(sls::Positions) const) &
|
||||
Detector::getSYNCClock,
|
||||
py::arg() = Positions{});
|
||||
CppDetectorApi.def("getVoltageList",
|
||||
CppDetectorApi.def("getPowerList",
|
||||
(std::vector<defs::dacIndex>(Detector::*)() const) &
|
||||
Detector::getVoltageList);
|
||||
Detector::getPowerList);
|
||||
CppDetectorApi.def("getSlowADCList",
|
||||
(std::vector<defs::dacIndex>(Detector::*)() const) &
|
||||
Detector::getSlowADCList);
|
||||
CppDetectorApi.def(
|
||||
"getVoltage",
|
||||
"getPower",
|
||||
(Result<int>(Detector::*)(defs::dacIndex, sls::Positions) const) &
|
||||
Detector::getVoltage,
|
||||
Detector::getPower,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"setVoltage",
|
||||
"setPower",
|
||||
(void (Detector::*)(defs::dacIndex, int, sls::Positions)) &
|
||||
Detector::setVoltage,
|
||||
Detector::setPower,
|
||||
py::arg(), py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def("getADCVpp",
|
||||
(Result<int>(Detector::*)(bool, sls::Positions) const) &
|
||||
@ -1617,9 +1617,9 @@ void init_det(py::module &m) {
|
||||
Detector::setDBITClock,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"getMeasuredVoltage",
|
||||
"getMeasuredPower",
|
||||
(Result<int>(Detector::*)(defs::dacIndex, sls::Positions) const) &
|
||||
Detector::getMeasuredVoltage,
|
||||
Detector::getMeasuredPower,
|
||||
py::arg(), py::arg() = Positions{});
|
||||
CppDetectorApi.def(
|
||||
"getMeasuredCurrent",
|
||||
@ -1736,26 +1736,26 @@ void init_det(py::module &m) {
|
||||
(std::string(Detector::*)(const int) const) &
|
||||
Detector::getSignalName,
|
||||
py::arg());
|
||||
CppDetectorApi.def("setVoltageNames",
|
||||
CppDetectorApi.def("setPowerNames",
|
||||
(void (Detector::*)(const std::vector<std::string>)) &
|
||||
Detector::setVoltageNames,
|
||||
Detector::setPowerNames,
|
||||
py::arg());
|
||||
CppDetectorApi.def("getVoltageNames",
|
||||
CppDetectorApi.def("getPowerNames",
|
||||
(std::vector<std::string>(Detector::*)() const) &
|
||||
Detector::getVoltageNames);
|
||||
Detector::getPowerNames);
|
||||
CppDetectorApi.def(
|
||||
"getVoltageIndex",
|
||||
"getPowerIndex",
|
||||
(defs::dacIndex(Detector::*)(const std::string &) const) &
|
||||
Detector::getVoltageIndex,
|
||||
Detector::getPowerIndex,
|
||||
py::arg());
|
||||
CppDetectorApi.def(
|
||||
"setVoltageName",
|
||||
"setPowerName",
|
||||
(void (Detector::*)(const defs::dacIndex, const std::string &)) &
|
||||
Detector::setVoltageName,
|
||||
Detector::setPowerName,
|
||||
py::arg(), py::arg());
|
||||
CppDetectorApi.def("getVoltageName",
|
||||
CppDetectorApi.def("getPowerName",
|
||||
(std::string(Detector::*)(const defs::dacIndex) const) &
|
||||
Detector::getVoltageName,
|
||||
Detector::getPowerName,
|
||||
py::arg());
|
||||
CppDetectorApi.def("setSlowADCNames",
|
||||
(void (Detector::*)(const std::vector<std::string>)) &
|
||||
|
Reference in New Issue
Block a user