mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-20 02:40:03 +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.
|
||||
|
||||
|
||||
* Fliprows
|
||||
Added fliprows to python API
|
||||
* Added many commands to python API
|
||||
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@ set( PYTHON_FILES
|
||||
slsdet/eiger.py
|
||||
slsdet/enums.py
|
||||
slsdet/errors.py
|
||||
slsdet/gaincaps.py
|
||||
slsdet/gotthard.py
|
||||
slsdet/pattern.py
|
||||
slsdet/gotthard2.py
|
||||
|
@ -11,7 +11,7 @@ from .gotthard2 import Gotthard2
|
||||
from .gotthard import Gotthard
|
||||
from .moench import Moench
|
||||
from .pattern import Pattern, patternParameters
|
||||
|
||||
from .gaincaps import Mythen3GainCapsWrapper
|
||||
|
||||
import _slsdet
|
||||
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 Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
|
||||
from _slsdet import xy
|
||||
from .gaincaps import Mythen3GainCapsWrapper
|
||||
from . import utils as ut
|
||||
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy
|
||||
from .registers import Register, Adc_register
|
||||
@ -231,7 +232,7 @@ class Detector(CppDetectorApi):
|
||||
"""
|
||||
[Jungfrau][Gotthard2][Myhten3][Gotthard][Ctb][Moench] Hardware version of detector.
|
||||
"""
|
||||
return ut.lhex(self.getHardwareVersion())
|
||||
return self.getHardwareVersion()
|
||||
|
||||
@property
|
||||
@element
|
||||
@ -263,6 +264,12 @@ class Detector(CppDetectorApi):
|
||||
"""Receiver version """
|
||||
return self.getReceiverVersion()
|
||||
|
||||
@property
|
||||
@element
|
||||
def serialnumber(self):
|
||||
"""Jungfrau][Gotthard][Mythen3][Gotthard2][CTB][Moench] Serial number of detector """
|
||||
return ut.lhex(self.getSerialNumber())
|
||||
|
||||
@property
|
||||
@element
|
||||
def rx_threads(self):
|
||||
@ -462,6 +469,47 @@ class Detector(CppDetectorApi):
|
||||
def blockingtrigger(self):
|
||||
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
|
||||
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."""
|
||||
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):
|
||||
"""Starts receiver listener for detector data packets and create a data file (if file write enabled)."""
|
||||
self.startReceiver()
|
||||
@ -1732,6 +1784,11 @@ class Detector(CppDetectorApi):
|
||||
"""Gets the list of timing modes (timingMode) for this detector."""
|
||||
return self.getTimingModeList()
|
||||
|
||||
@property
|
||||
def readoutspeedlist(self):
|
||||
"""List of readout speed levels implemented for this detector."""
|
||||
return self.getReadoutSpeedList()
|
||||
|
||||
@property
|
||||
def templist(self):
|
||||
"""List of temperature enums (dacIndex) implemented for this detector."""
|
||||
@ -1833,23 +1890,17 @@ class Detector(CppDetectorApi):
|
||||
|
||||
@property
|
||||
def versions(self):
|
||||
if self.type == detectorType.EIGER:
|
||||
return {'type': self.type,
|
||||
version_list = {'type': self.type,
|
||||
'package': self.packageversion,
|
||||
'client': self.clientversion,
|
||||
'firmware': self.firmwareversion,
|
||||
'detectorserver': self.detectorserverversion,
|
||||
'kernel': self.kernelversion,
|
||||
'receiver': self.rx_version}
|
||||
|
||||
return {'type': self.type,
|
||||
'package': self.packageversion,
|
||||
'client': self.clientversion,
|
||||
'firmware': self.firmwareversion,
|
||||
'detectorserver': self.detectorserverversion,
|
||||
'hardware':self.hardwareversion,
|
||||
'kernel': self.kernelversion,
|
||||
'receiver': self.rx_version}
|
||||
'kernel': self.kernelversion}
|
||||
if self.type != detectorType.EIGER:
|
||||
version_list ['hardware'] = self.hardwareversion
|
||||
if self.use_receiver:
|
||||
version_list ['receiver'] = self.rx_version
|
||||
return version_list
|
||||
|
||||
@property
|
||||
def virtual(self):
|
||||
@ -3138,6 +3189,17 @@ class Detector(CppDetectorApi):
|
||||
def dbitclk(self, 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
|
||||
@element
|
||||
def dbitpipeline(self):
|
||||
@ -3748,6 +3810,23 @@ class Detector(CppDetectorApi):
|
||||
"""
|
||||
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
|
||||
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
|
||||
import _slsdet
|
||||
dacIndex = _slsdet.slsDetectorDefs.dacIndex
|
||||
gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps
|
||||
from .detector_property import DetectorProperty
|
||||
|
||||
|
||||
@ -63,3 +64,5 @@ class Mythen3(Detector):
|
||||
@property
|
||||
def dacs(self):
|
||||
return self._dacs
|
||||
|
||||
|
||||
|
@ -4,6 +4,7 @@ from .utils import element_if_equal
|
||||
from .enums import dacIndex
|
||||
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
|
||||
from _slsdet import slsDetectorDefs
|
||||
detectorType = slsDetectorDefs.detectorType
|
||||
|
||||
|
||||
def set_proxy_using_dict(func, key, value, unpack = False):
|
||||
@ -87,7 +88,10 @@ class ClkDivProxy:
|
||||
|
||||
def __repr__(self):
|
||||
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))
|
||||
if isinstance(r, list):
|
||||
rstr += ' '.join(f'{item}' for item in r)
|
||||
@ -96,10 +100,35 @@ class ClkDivProxy:
|
||||
|
||||
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:
|
||||
"""
|
||||
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):
|
||||
self.det = det
|
||||
@ -109,7 +138,9 @@ class MaxPhaseProxy:
|
||||
|
||||
def __repr__(self):
|
||||
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))
|
||||
if isinstance(r, list):
|
||||
rstr += ' '.join(f'{item}' for item in r)
|
||||
@ -120,7 +151,7 @@ class MaxPhaseProxy:
|
||||
|
||||
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):
|
||||
self.det = det
|
||||
@ -130,7 +161,9 @@ class ClkFreqProxy:
|
||||
|
||||
def __repr__(self):
|
||||
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))
|
||||
if isinstance(r, list):
|
||||
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
|
||||
modeNotImplemented("clock index (divider set)", args[0]);
|
||||
}
|
||||
|
||||
// TODO: if value between to set and num clocks, msg = "cannot set"
|
||||
enum CLKINDEX c = 0;
|
||||
int val = args[1];
|
||||
if (ret == OK) {
|
||||
|
@ -287,13 +287,12 @@ std::string CmdProxy::Versions(int action) {
|
||||
os << OutStringHex(t);
|
||||
}
|
||||
os << "\nServer : "
|
||||
<< OutString(
|
||||
det->getDetectorServerVersion(std::vector<int>{det_id}));
|
||||
<< OutString(det->getDetectorServerVersion(std::vector<int>{det_id}))
|
||||
<< "\nKernel : "
|
||||
<< OutString(det->getKernelVersion({std::vector<int>{det_id}}));
|
||||
if (!eiger)
|
||||
os << "\nHardware : "
|
||||
<< OutString(det->getHardwareVersion(std::vector<int>{det_id}));
|
||||
os << "\nKernel : "
|
||||
<< OutString(det->getKernelVersion({std::vector<int>{det_id}}));
|
||||
if (det->getUseReceiverFlag().squash(true)) {
|
||||
os << "\nReceiver : "
|
||||
<< OutString(det->getReceiverVersion(std::vector<int>{det_id}));
|
||||
|
Loading…
x
Reference in New Issue
Block a user