mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-06 10:00:40 +02:00
python additions (#686)
* python: fixed versions when no receiver, added clearbusy, serialnumber and readoutspeedlist. commandline: modified versions to look like python versions * python: added clkphase, fixed clkdiv, maxphase * python added adcvpp * gaincaps for python --------- Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
This commit is contained in:
parent
a74c9498e2
commit
ed2894dafd
@ -142,8 +142,7 @@ This document describes the differences between v7.0.0 and v6.1.2
|
|||||||
Hostnames concatenated using '+' was not split up in Python API. Fixed.
|
Hostnames concatenated using '+' was not split up in Python API. Fixed.
|
||||||
|
|
||||||
|
|
||||||
* Fliprows
|
* Added many commands to python API
|
||||||
Added fliprows to python API
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ set( PYTHON_FILES
|
|||||||
slsdet/eiger.py
|
slsdet/eiger.py
|
||||||
slsdet/enums.py
|
slsdet/enums.py
|
||||||
slsdet/errors.py
|
slsdet/errors.py
|
||||||
|
slsdet/gaincaps.py
|
||||||
slsdet/gotthard.py
|
slsdet/gotthard.py
|
||||||
slsdet/pattern.py
|
slsdet/pattern.py
|
||||||
slsdet/gotthard2.py
|
slsdet/gotthard2.py
|
||||||
|
@ -11,7 +11,7 @@ from .gotthard2 import Gotthard2
|
|||||||
from .gotthard import Gotthard
|
from .gotthard import Gotthard
|
||||||
from .moench import Moench
|
from .moench import Moench
|
||||||
from .pattern import Pattern, patternParameters
|
from .pattern import Pattern, patternParameters
|
||||||
|
from .gaincaps import Mythen3GainCapsWrapper
|
||||||
|
|
||||||
import _slsdet
|
import _slsdet
|
||||||
xy = _slsdet.xy
|
xy = _slsdet.xy
|
||||||
|
@ -16,6 +16,7 @@ defs = slsDetectorDefs
|
|||||||
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
|
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
|
||||||
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
|
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
|
||||||
from _slsdet import xy
|
from _slsdet import xy
|
||||||
|
from .gaincaps import Mythen3GainCapsWrapper
|
||||||
from . import utils as ut
|
from . import utils as ut
|
||||||
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
|
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
|
||||||
from .registers import Register, Adc_register
|
from .registers import Register, Adc_register
|
||||||
@ -231,7 +232,7 @@ class Detector(CppDetectorApi):
|
|||||||
"""
|
"""
|
||||||
[Jungfrau][Gotthard2][Myhten3][Gotthard][Ctb][Moench] Hardware version of detector.
|
[Jungfrau][Gotthard2][Myhten3][Gotthard][Ctb][Moench] Hardware version of detector.
|
||||||
"""
|
"""
|
||||||
return ut.lhex(self.getHardwareVersion())
|
return self.getHardwareVersion()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
@ -263,6 +264,12 @@ class Detector(CppDetectorApi):
|
|||||||
"""Receiver version """
|
"""Receiver version """
|
||||||
return self.getReceiverVersion()
|
return self.getReceiverVersion()
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def serialnumber(self):
|
||||||
|
"""Jungfrau][Gotthard][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
||||||
|
return ut.lhex(self.getSerialNumber())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def rx_threads(self):
|
def rx_threads(self):
|
||||||
@ -462,6 +469,47 @@ class Detector(CppDetectorApi):
|
|||||||
def blockingtrigger(self):
|
def blockingtrigger(self):
|
||||||
self.sendSoftwareTrigger(True)
|
self.sendSoftwareTrigger(True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def gaincaps(self):
|
||||||
|
"""
|
||||||
|
[Mythen3] Gain caps. Enum: M3_GainCaps \n
|
||||||
|
|
||||||
|
Note
|
||||||
|
----
|
||||||
|
Options: M3_GainCaps, M3_C15sh, M3_C30sh, M3_C50sh, M3_C225ACsh, M3_C15pre
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
>>> d.gaincaps
|
||||||
|
C15pre, C30sh
|
||||||
|
>>> d.gaincaps = M3_GainCaps.M3_C30sh
|
||||||
|
>>> d.gaincaps
|
||||||
|
C30sh
|
||||||
|
>>> d.gaincaps = M3_GainCaps.M3_C30sh | M3_GainCaps.M3_C15sh
|
||||||
|
>>> d.gaincaps
|
||||||
|
C15sh, C30sh
|
||||||
|
"""
|
||||||
|
res = [Mythen3GainCapsWrapper(it) for it in self.getGainCaps()]
|
||||||
|
return res
|
||||||
|
|
||||||
|
@gaincaps.setter
|
||||||
|
def gaincaps(self, caps):
|
||||||
|
#convert to int if called with Wrapper
|
||||||
|
if isinstance(caps, Mythen3GainCapsWrapper):
|
||||||
|
self.setGainCaps(caps.value)
|
||||||
|
elif isinstance(caps, dict):
|
||||||
|
corr = {}
|
||||||
|
for key, value in caps.items():
|
||||||
|
if isinstance(value, Mythen3GainCapsWrapper):
|
||||||
|
corr[key] = value.value
|
||||||
|
else:
|
||||||
|
corr[key] = value
|
||||||
|
ut.set_using_dict(self.setGainCaps, corr)
|
||||||
|
else:
|
||||||
|
self.setGainCaps(caps)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def exptime(self):
|
def exptime(self):
|
||||||
"""
|
"""
|
||||||
@ -656,6 +704,10 @@ class Detector(CppDetectorApi):
|
|||||||
"""Start detector acquisition. Status changes to RUNNING or WAITING and automatically returns to idle at the end of acquisition."""
|
"""Start detector acquisition. Status changes to RUNNING or WAITING and automatically returns to idle at the end of acquisition."""
|
||||||
self.startDetector()
|
self.startDetector()
|
||||||
|
|
||||||
|
def clearbusy(self):
|
||||||
|
"""If acquisition aborted during acquire command, use this to clear acquiring flag in shared memory before starting next acquisition"""
|
||||||
|
self.clearAcquiringFlag()
|
||||||
|
|
||||||
def rx_start(self):
|
def rx_start(self):
|
||||||
"""Starts receiver listener for detector data packets and create a data file (if file write enabled)."""
|
"""Starts receiver listener for detector data packets and create a data file (if file write enabled)."""
|
||||||
self.startReceiver()
|
self.startReceiver()
|
||||||
@ -1732,6 +1784,11 @@ class Detector(CppDetectorApi):
|
|||||||
"""Gets the list of timing modes (timingMode) for this detector."""
|
"""Gets the list of timing modes (timingMode) for this detector."""
|
||||||
return self.getTimingModeList()
|
return self.getTimingModeList()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def readoutspeedlist(self):
|
||||||
|
"""List of readout speed levels implemented for this detector."""
|
||||||
|
return self.getReadoutSpeedList()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def templist(self):
|
def templist(self):
|
||||||
"""List of temperature enums (dacIndex) implemented for this detector."""
|
"""List of temperature enums (dacIndex) implemented for this detector."""
|
||||||
@ -1833,23 +1890,17 @@ class Detector(CppDetectorApi):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def versions(self):
|
def versions(self):
|
||||||
if self.type == detectorType.EIGER:
|
version_list = {'type': self.type,
|
||||||
return {'type': self.type,
|
|
||||||
'package': self.packageversion,
|
'package': self.packageversion,
|
||||||
'client': self.clientversion,
|
'client': self.clientversion,
|
||||||
'firmware': self.firmwareversion,
|
'firmware': self.firmwareversion,
|
||||||
'detectorserver': self.detectorserverversion,
|
'detectorserver': self.detectorserverversion,
|
||||||
'kernel': self.kernelversion,
|
'kernel': self.kernelversion}
|
||||||
'receiver': self.rx_version}
|
if self.type != detectorType.EIGER:
|
||||||
|
version_list ['hardware'] = self.hardwareversion
|
||||||
return {'type': self.type,
|
if self.use_receiver:
|
||||||
'package': self.packageversion,
|
version_list ['receiver'] = self.rx_version
|
||||||
'client': self.clientversion,
|
return version_list
|
||||||
'firmware': self.firmwareversion,
|
|
||||||
'detectorserver': self.detectorserverversion,
|
|
||||||
'hardware':self.hardwareversion,
|
|
||||||
'kernel': self.kernelversion,
|
|
||||||
'receiver': self.rx_version}
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def virtual(self):
|
def virtual(self):
|
||||||
@ -3138,6 +3189,17 @@ class Detector(CppDetectorApi):
|
|||||||
def dbitclk(self, value):
|
def dbitclk(self, value):
|
||||||
ut.set_using_dict(self.setDBITClock, value)
|
ut.set_using_dict(self.setDBITClock, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def adcvpp(self):
|
||||||
|
"""[Ctb][Moench] Vpp of ADC. [0 -> 1V | 1 -> 1.14V | 2 -> 1.33V | 3 -> 1.6V | 4 -> 2V] \n
|
||||||
|
Advanced User function!"""
|
||||||
|
return self.getADCVpp(False)
|
||||||
|
|
||||||
|
@adcvpp.setter
|
||||||
|
def adcvpp(self, value):
|
||||||
|
ut.set_using_dict(self.setADCVpp, value, False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@element
|
@element
|
||||||
def dbitpipeline(self):
|
def dbitpipeline(self):
|
||||||
@ -3748,6 +3810,23 @@ class Detector(CppDetectorApi):
|
|||||||
"""
|
"""
|
||||||
return self.getMeasuredCurrent(dacIndex.I_POWER_IO)
|
return self.getMeasuredCurrent(dacIndex.I_POWER_IO)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def clkphase(self):
|
||||||
|
"""
|
||||||
|
[Gotthard2][Mythen3] Phase shift of all clocks.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
>>> d.clkphase[0] = 20
|
||||||
|
>>> d.clkphase
|
||||||
|
0: 20
|
||||||
|
1: 10
|
||||||
|
2: 20
|
||||||
|
3: 10
|
||||||
|
4: 10
|
||||||
|
5: 5
|
||||||
|
"""
|
||||||
|
return ClkPhaseProxy(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clkdiv(self):
|
def clkdiv(self):
|
||||||
|
42
python/slsdet/gaincaps.py
Normal file
42
python/slsdet/gaincaps.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import _slsdet
|
||||||
|
gc = _slsdet.slsDetectorDefs.M3_GainCaps
|
||||||
|
|
||||||
|
|
||||||
|
class Mythen3GainCapsWrapper:
|
||||||
|
"""Holds M3_GainCaps enums and facilitates printing"""
|
||||||
|
# 'M3_C10pre', 'M3_C15pre', 'M3_C15sh', 'M3_C225ACsh', 'M3_C30sh', 'M3_C50sh'
|
||||||
|
all_bits = gc.M3_C10pre | gc.M3_C15pre | gc.M3_C15sh | gc.M3_C225ACsh | gc.M3_C30sh | gc.M3_C50sh
|
||||||
|
all_caps = (gc.M3_C10pre, gc.M3_C15pre, gc.M3_C15sh, gc.M3_C225ACsh, gc.M3_C30sh, gc.M3_C50sh)
|
||||||
|
def __init__(self, value = 0):
|
||||||
|
self._validate(value)
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
|
||||||
|
def __eq__(self, other) -> bool:
|
||||||
|
if isinstance(other, Mythen3GainCapsWrapper):
|
||||||
|
return self.value == other.value
|
||||||
|
else:
|
||||||
|
return self.value == other
|
||||||
|
|
||||||
|
|
||||||
|
def __ne__(self, other) -> bool:
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
s = ', '.join(str(c).rsplit('_', 1)[1] for c in self.all_caps if self.value & c)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
def _validate(self, value):
|
||||||
|
"""Check that only bits representing real capacitors are set"""
|
||||||
|
if isinstance(value, gc):
|
||||||
|
return True
|
||||||
|
elif isinstance(value, int):
|
||||||
|
if value & (~self.all_bits):
|
||||||
|
raise ValueError(f"The value: {value} is not allowed for Mythen3GainCapsWrapper")
|
||||||
|
else:
|
||||||
|
raise ValueError("GainCaps can only be initialized from int or M3_GainCaps enum")
|
@ -13,6 +13,7 @@ from .detector import Detector, freeze
|
|||||||
from .dacs import DetectorDacs
|
from .dacs import DetectorDacs
|
||||||
import _slsdet
|
import _slsdet
|
||||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||||
|
gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps
|
||||||
from .detector_property import DetectorProperty
|
from .detector_property import DetectorProperty
|
||||||
|
|
||||||
|
|
||||||
@ -62,4 +63,6 @@ class Mythen3(Detector):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def dacs(self):
|
def dacs(self):
|
||||||
return self._dacs
|
return self._dacs
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ from .utils import element_if_equal
|
|||||||
from .enums import dacIndex
|
from .enums import dacIndex
|
||||||
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
|
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
|
||||||
from _slsdet import slsDetectorDefs
|
from _slsdet import slsDetectorDefs
|
||||||
|
detectorType = slsDetectorDefs.detectorType
|
||||||
|
|
||||||
|
|
||||||
def set_proxy_using_dict(func, key, value, unpack = False):
|
def set_proxy_using_dict(func, key, value, unpack = False):
|
||||||
@ -87,7 +88,10 @@ class ClkDivProxy:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
rstr = ''
|
rstr = ''
|
||||||
for i in range(6):
|
num_clocks = 6
|
||||||
|
if self.det.type == detectorType.MYTHEN3:
|
||||||
|
num_clocks = 5
|
||||||
|
for i in range(num_clocks):
|
||||||
r = element_if_equal(self.__getitem__(i))
|
r = element_if_equal(self.__getitem__(i))
|
||||||
if isinstance(r, list):
|
if isinstance(r, list):
|
||||||
rstr += ' '.join(f'{item}' for item in r)
|
rstr += ' '.join(f'{item}' for item in r)
|
||||||
@ -96,10 +100,35 @@ class ClkDivProxy:
|
|||||||
|
|
||||||
return rstr.strip('\n')
|
return rstr.strip('\n')
|
||||||
|
|
||||||
|
class ClkPhaseProxy:
|
||||||
|
"""
|
||||||
|
Proxy class to allow for more intuitive reading clock phase
|
||||||
|
"""
|
||||||
|
def __init__(self, det):
|
||||||
|
self.det = det
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return element_if_equal(self.det.getClockPhase(key))
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
set_proxy_using_dict(self.det.setClockPhase, key, value)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
rstr = ''
|
||||||
|
if self.det.type == detectorType.MYTHEN3:
|
||||||
|
num_clocks = 5
|
||||||
|
for i in range(num_clocks):
|
||||||
|
r = element_if_equal(self.__getitem__(i))
|
||||||
|
if isinstance(r, list):
|
||||||
|
rstr += ' '.join(f'{item}' for item in r)
|
||||||
|
else:
|
||||||
|
rstr += f'{i}: {r}\n'
|
||||||
|
|
||||||
|
return rstr.strip('\n')
|
||||||
|
|
||||||
class MaxPhaseProxy:
|
class MaxPhaseProxy:
|
||||||
"""
|
"""
|
||||||
Proxy class to allow for more intuitive reading clockdivider
|
Proxy class to allow for more intuitive reading max clock phase shift
|
||||||
"""
|
"""
|
||||||
def __init__(self, det):
|
def __init__(self, det):
|
||||||
self.det = det
|
self.det = det
|
||||||
@ -109,7 +138,9 @@ class MaxPhaseProxy:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
rstr = ''
|
rstr = ''
|
||||||
for i in range(5):
|
if self.det.type == detectorType.MYTHEN3:
|
||||||
|
num_clocks = 5
|
||||||
|
for i in range(num_clocks):
|
||||||
r = element_if_equal(self.__getitem__(i))
|
r = element_if_equal(self.__getitem__(i))
|
||||||
if isinstance(r, list):
|
if isinstance(r, list):
|
||||||
rstr += ' '.join(f'{item}' for item in r)
|
rstr += ' '.join(f'{item}' for item in r)
|
||||||
@ -120,7 +151,7 @@ class MaxPhaseProxy:
|
|||||||
|
|
||||||
class ClkFreqProxy:
|
class ClkFreqProxy:
|
||||||
"""
|
"""
|
||||||
Proxy class to allow for more intuitive reading clockdivider
|
Proxy class to allow for more intuitive reading clock frequency
|
||||||
"""
|
"""
|
||||||
def __init__(self, det):
|
def __init__(self, det):
|
||||||
self.det = det
|
self.det = det
|
||||||
@ -130,7 +161,9 @@ class ClkFreqProxy:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
rstr = ''
|
rstr = ''
|
||||||
for i in range(5):
|
if self.det.type == detectorType.MYTHEN3:
|
||||||
|
num_clocks = 5
|
||||||
|
for i in range(num_clocks):
|
||||||
r = element_if_equal(self.__getitem__(i))
|
r = element_if_equal(self.__getitem__(i))
|
||||||
if isinstance(r, list):
|
if isinstance(r, list):
|
||||||
rstr += ' '.join(f'{item}' for item in r)
|
rstr += ' '.join(f'{item}' for item in r)
|
||||||
|
24
python/tests/test_m3gaincaps.py
Normal file
24
python/tests/test_m3gaincaps.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from slsdet import Mythen3GainCapsWrapper
|
||||||
|
from slsdet.enums import M3_GainCaps #this is the c++ enum
|
||||||
|
|
||||||
|
|
||||||
|
def test_comapre_with_int():
|
||||||
|
c = Mythen3GainCapsWrapper(128) #C10pre
|
||||||
|
assert c == 128
|
||||||
|
assert c != 5
|
||||||
|
assert c != 1280
|
||||||
|
|
||||||
|
def test_compare_with_other():
|
||||||
|
a = Mythen3GainCapsWrapper(128)
|
||||||
|
b = Mythen3GainCapsWrapper(1<<10)
|
||||||
|
c = Mythen3GainCapsWrapper(128)
|
||||||
|
assert a!=b
|
||||||
|
assert (a==b) == False
|
||||||
|
assert a==c
|
||||||
|
|
||||||
|
def test_can_be_default_constructed():
|
||||||
|
c = Mythen3GainCapsWrapper()
|
||||||
|
assert c == 0
|
||||||
|
|
@ -6013,7 +6013,7 @@ int set_clock_divider(int file_des) {
|
|||||||
#endif
|
#endif
|
||||||
modeNotImplemented("clock index (divider set)", args[0]);
|
modeNotImplemented("clock index (divider set)", args[0]);
|
||||||
}
|
}
|
||||||
|
// TODO: if value between to set and num clocks, msg = "cannot set"
|
||||||
enum CLKINDEX c = 0;
|
enum CLKINDEX c = 0;
|
||||||
int val = args[1];
|
int val = args[1];
|
||||||
if (ret == OK) {
|
if (ret == OK) {
|
||||||
|
@ -287,13 +287,12 @@ std::string CmdProxy::Versions(int action) {
|
|||||||
os << OutStringHex(t);
|
os << OutStringHex(t);
|
||||||
}
|
}
|
||||||
os << "\nServer : "
|
os << "\nServer : "
|
||||||
<< OutString(
|
<< OutString(det->getDetectorServerVersion(std::vector<int>{det_id}))
|
||||||
det->getDetectorServerVersion(std::vector<int>{det_id}));
|
<< "\nKernel : "
|
||||||
|
<< OutString(det->getKernelVersion({std::vector<int>{det_id}}));
|
||||||
if (!eiger)
|
if (!eiger)
|
||||||
os << "\nHardware : "
|
os << "\nHardware : "
|
||||||
<< OutString(det->getHardwareVersion(std::vector<int>{det_id}));
|
<< OutString(det->getHardwareVersion(std::vector<int>{det_id}));
|
||||||
os << "\nKernel : "
|
|
||||||
<< OutString(det->getKernelVersion({std::vector<int>{det_id}}));
|
|
||||||
if (det->getUseReceiverFlag().squash(true)) {
|
if (det->getUseReceiverFlag().squash(true)) {
|
||||||
os << "\nReceiver : "
|
os << "\nReceiver : "
|
||||||
<< OutString(det->getReceiverVersion(std::vector<int>{det_id}));
|
<< OutString(det->getReceiverVersion(std::vector<int>{det_id}));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user