From 104d91e8c67abae7bfb4d5c4ef5b62bc3177d584 Mon Sep 17 00:00:00 2001 From: Erik Frojdh Date: Thu, 28 May 2020 11:33:52 +0200 Subject: [PATCH] more jf stuff --- python/api-tests/test_detector.py | 82 ++++++++++++ python/api-tests/test_jungfrau.py | 70 ++++++++++- python/scripts/cmd_python.py | 2 +- python/slsdet/detector.py | 199 +++++++++++++++++++----------- 4 files changed, 273 insertions(+), 80 deletions(-) create mode 100644 python/api-tests/test_detector.py diff --git a/python/api-tests/test_detector.py b/python/api-tests/test_detector.py new file mode 100644 index 000000000..1eff7d28a --- /dev/null +++ b/python/api-tests/test_detector.py @@ -0,0 +1,82 @@ +import pytest +import datetime as dt +from slsdet import Detector, timingMode, detectorType + +not_eiger = pytest.mark.skipif( + Detector().type == detectorType.EIGER, reason="Does not work for eiger" +) + + +@pytest.fixture +def det(): + from slsdet import Detector + + return Detector() + + +def test_frames(det): + for n in [1, 100, 3245, 10000]: + det.frames = n + assert det.frames == n + det.frames = 1 + + +def test_triggers(det): + for n in [1, 100, 3245, 10000]: + det.triggers = n + assert det.triggers == n + det.triggers = 1 + + +def test_exptime(det): + det.exptime = 1 + assert det.exptime == 1 + det.exptime = dt.timedelta(milliseconds=10) + assert det.exptime == 0.01 + det.exptime = 1 + + +def test_period(det): + det.period = 3.2 + assert det.period == 3.2 + + p = dt.timedelta(microseconds=1020) + det.period = p + assert det.period == 0.001020 + r = det.getPeriod() + assert r[0] == p + det.period = 0 + assert det.period == 0 + + +def test_lock(det): + for l in [True, False]: + det.lock = l + assert det.lock == l + + +def test_timing(det): + # auto and trigger is available for all det + for m in [timingMode.TRIGGER_EXPOSURE, timingMode.AUTO_TIMING]: + det.timing = m + assert det.timing == m + +@not_eiger +def test_delay(det): + det.delay = 1 + assert det.delay == 1 + + t = dt.timedelta(microseconds=1) + det.delay = t + assert det.delay == t.total_seconds() + + r = det.getDelayAfterTrigger()[0] + assert r == t + + det.delay = 0 + assert det.delay == 0 + + +@not_eiger +def test_delayl(det): + assert det.delayl == 0 \ No newline at end of file diff --git a/python/api-tests/test_jungfrau.py b/python/api-tests/test_jungfrau.py index 19d6d1138..baa57d4f0 100644 --- a/python/api-tests/test_jungfrau.py +++ b/python/api-tests/test_jungfrau.py @@ -1,5 +1,14 @@ import pytest import datetime as dt +from slsdet import Detector, detectorType + +""" +These tests are designed to work the API and catch +any changes in behavior or naming. Tests are expected +to pass with a virtual detector or a real one + +""" + @pytest.fixture def jf(): @@ -7,21 +16,74 @@ def jf(): return Jungfrau() +jungfrautest = pytest.mark.skipif( + Detector().type != detectorType.JUNGFRAU, reason="Only valid for Jungfrau" +) + + +@jungfrautest def test_storagecells(jf): for i in range(16): jf.storagecells = i assert jf.storagecells == i - jf.storagecells = 0 #default + jf.storagecells = 0 # default +@jungfrautest def test_storagecell_start(jf): for i in range(16): jf.storagecell_start = i assert jf.storagecell_start == i - jf.storagecells = 15 #default - + jf.storagecells = 15 # default +@jungfrautest def test_storagecell_delay(jf): for t in [0.001, 0.0002, 0.0013]: jf.storagecell_delay = t assert jf.storagecell_delay == t - jf.storagecell_delay = 0 #default \ No newline at end of file + jf.storagecell_delay = 0 # default + +@jungfrautest +def test_temp_event(jf): + # hard to test with virtual server + assert jf.temp_event == 0 + +@jungfrautest +def test_temp_threshold(jf): + for th in [0, 10, 43, 72]: + jf.temp_threshold = th + assert jf.temp_threshold == th + jf.temp_threshold = 0 + +@jungfrautest +def test_auto_comp_disable(jf): + for v in [True, False]: + jf.auto_comp_disable = v + assert jf.auto_comp_disable == v + +@jungfrautest +def test_numinterfaces(jf): + for n in [2, 1]: + jf.numinterfaces = n + assert jf.numinterfaces == n + +@jungfrautest +def test_dr(jf): + assert jf.dr == 16 + +@jungfrautest +def test_temp_control(jf): + for v in [True, False]: + jf.temp_control = v + assert jf.temp_control == v + +@jungfrautest +def test_startingfnum(jf): + for n in [10, 127, 43321, 1]: + jf.startingfnum = n + assert jf.startingfnum == n + +@jungfrautest +def test_selinterface(jf): + for i in [1, 0]: + jf.selinterface = i + assert jf.selinterface == i \ No newline at end of file diff --git a/python/scripts/cmd_python.py b/python/scripts/cmd_python.py index ad7395f44..4da028765 100644 --- a/python/scripts/cmd_python.py +++ b/python/scripts/cmd_python.py @@ -15,7 +15,7 @@ pycmd += ['vrf', 'vtr', 'vrs', 'vtgstv', 'vsvn', 'vtrim', 'vpreamp', 'vref_comp', 'vref_comp_fe vref_ds', 'vref_h_adc', 'vref_l_adc', 'iodelay', 'list', 'vref_ds', 'vis', 'vpl', 'vref_comp_fe', 'vph', 'vout_cm', 'vcp', 'vcn', 'vcmp_ll', 'vcmp_lr' -, 'vcmp_rl', 'vcmp_rr'] +, 'vcmp_rl', 'vcmp_rr', 'daclist', 'dacvalues', 'vcal', 'vcas'] missing = [] for c in cmd: diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 8da6c2de9..e657ea250 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -3,6 +3,7 @@ from _slsdet import slsDetectorDefs from _slsdet import IpAddr, MacAddr runStatus = slsDetectorDefs.runStatus +timingMode = slsDetectorDefs.timingMode speedLevel = slsDetectorDefs.speedLevel dacIndex = slsDetectorDefs.dacIndex detectorType = slsDetectorDefs.detectorType @@ -17,6 +18,7 @@ from functools import wraps from collections import namedtuple import socket + def freeze(cls): cls._frozen = False @@ -61,15 +63,12 @@ class Detector(CppDetectorApi): self._register = Register(self) self._adc_register = Adc_register(self) - # CONFIGURATION def __len__(self): return self.size() def __repr__(self): - return '{}(id = {})'.format(self.__class__.__name__, - self.getShmId()) - + return "{}(id = {})".format(self.__class__.__name__, self.getShmId()) def free(self): self.freeSharedMemory() @@ -92,7 +91,6 @@ class Detector(CppDetectorApi): @property def hostname(self): - print('getting host!') return self.getHostname() @hostname.setter @@ -110,7 +108,7 @@ class Detector(CppDetectorApi): @property def server_version(self): - #TODO! handle hex print + # TODO! handle hex print return element_if_equal(self.getDetectorServerVersion()) @property @@ -131,7 +129,7 @@ class Detector(CppDetectorApi): @dr.setter def dr(self, dr): - self.setDynamicRange(dr) + self.setDynamicRange(dr) @property def module_geometry(self): @@ -178,56 +176,38 @@ class Detector(CppDetectorApi): res = self.getExptime() return reduce_time(res) - @exptime.setter def exptime(self, t): self.setExptime(ut.make_timedelta(t)) - @property - def gatedelay(self): - return reduce_time(self.getGateDelayForAllGates()) - - @gatedelay.setter - def gatedelay(self, value): - if is_iterable(value): - if len(value) == 3: - for i,v in enumerate(value): - self.setGateDelay(i, ut.make_timedelta(v)) - else: - self.setGateDelay(-1, ut.make_timedelta(value)) - - @property - def subexptime(self): - res = self.getSubExptime() - return reduce_time(res) - - @subexptime.setter - def subexptime(self, t): - self.setSubExptime(ut.make_timedelta(t)) - - @property - def subdeadtime(self): - res = self.getSubDeadTime() - reduce_time(res) - - @subdeadtime.setter - def subdeadtime(self, t): - self.setSubDeadTime(ut.make_timedelta(t)) - @property def period(self): res = self.getPeriod() - reduce_time(res) + return reduce_time(res) @period.setter def period(self, t): self.setPeriod(ut.make_timedelta(t)) - + + @property + @element + def delay(self): + return ut.reduce_time(self.getDelayAfterTrigger()) + + @delay.setter + def delay(self, t): + self.setDelayAfterTrigger(ut.make_timedelta(t)) + + @property + @element + def delayl(self): + return ut.reduce_time(self.getDelayAfterTriggerLeft()) + + # Time @property def rx_framescaught(self): return element_if_equal(self.getFramesCaught()) - @property def startingfnum(self): @@ -236,10 +216,7 @@ class Detector(CppDetectorApi): @startingfnum.setter def startingfnum(self, value): self.setStartingFrameNumber(value) - - - - #TODO! add txdelay + # TODO! add txdelay @property def use_receiver(self): @@ -305,14 +282,21 @@ class Detector(CppDetectorApi): @property def rx_lastclient(self): return element_if_equal(self.getRxLastClientIP()) + # FILE + @property + @element + def numinterfaces(self): + return self.getNumberofUDPInterfaces() - #FILE + @numinterfaces.setter + def numinterfaces(self, value): + self.setNumberofUDPInterfaces(value) @property def fformat(self): return element_if_equal(self.getFileFormat()) - + @fformat.setter def fformat(self, format): self.setFileFormat(format) @@ -423,14 +407,13 @@ class Detector(CppDetectorApi): def zmqip(self, ip): self.setClientZmqIp(ip) - @property def udp_dstip(self): return element_if_equal(self.getDestinationUDPIP()) @udp_dstip.setter def udp_dstip(self, ip): - if ip == 'auto': + if ip == "auto": ip = socket.gethostbyname(self.rx_hostname) self.setDestinationUDPIP(IpAddr(ip)) @@ -440,7 +423,7 @@ class Detector(CppDetectorApi): @udp_dstip2.setter def udp_dstip2(self, ip): - if ip == 'auto': + if ip == "auto": ip = socket.gethostbyname(self.rx_hostname) self.setDestinationUDPIP2(IpAddr(ip)) @@ -460,7 +443,6 @@ class Detector(CppDetectorApi): def udp_dstmac2(self, mac): self.setDestinationUDPMAC2(MacAddr(mac)) - @property def udp_srcip(self): return element_if_equal(self.getSourceUDPIP()) @@ -517,7 +499,6 @@ class Detector(CppDetectorApi): def src_udpip(self, ip): self.setSourceUDPIP(IpAddr(ip)) - @property def src_udpmac2(self): return element_if_equal(self.getSourceUDPMAC2()) @@ -554,8 +535,6 @@ class Detector(CppDetectorApi): def rx_status(self): return element_if_equal(self.getReceiverStatus()) - - @property def rx_udpsocksize(self): return element_if_equal(self.getRxUDPSocketBufferSize()) @@ -570,7 +549,7 @@ class Detector(CppDetectorApi): @property def trimbits(self): - return NotImplementedError('trimbits are set only') + return NotImplementedError("trimbits are set only") @trimbits.setter def trimbits(self, fname): @@ -604,7 +583,6 @@ class Detector(CppDetectorApi): def adcreg(self): return self._adc_register - @property def led(self): return element_if_equal(self.getLEDEnable()) @@ -645,11 +623,11 @@ class Detector(CppDetectorApi): @property def timing(self): - return element_if_equal(self.getTimingMode()) + return element_if_equal(self.getTimingMode()) @timing.setter def timing(self, mode): - self.setTimingMode(mode) + self.setTimingMode(mode) @property def trimen(self): @@ -663,8 +641,6 @@ class Detector(CppDetectorApi): def vthreshold(self): return element_if_equal(self.getDAC(dacIndex.THRESHOLD)) - - @property def type(self): return element_if_equal(self.getDetectorType()) @@ -677,10 +653,27 @@ class Detector(CppDetectorApi): def rx_missingpackets(self): return element_if_equal(self.getNumMissingPackets()) - """ Some Eiger stuff, does this have to be here or can we move it to subclass? """ + @property + def subexptime(self): + res = self.getSubExptime() + return reduce_time(res) + + @subexptime.setter + def subexptime(self, t): + self.setSubExptime(ut.make_timedelta(t)) + + @property + def subdeadtime(self): + res = self.getSubDeadTime() + reduce_time(res) + + @subdeadtime.setter + def subdeadtime(self, t): + self.setSubDeadTime(ut.make_timedelta(t)) + @property def partialreset(self): return element_if_equal(self.getPartialReset()) @@ -692,7 +685,7 @@ class Detector(CppDetectorApi): @property def tengiga(self): return element_if_equal(self.getTenGiga()) - + @tengiga.setter def tengiga(self, value): self.setTenGiga(value) @@ -739,7 +732,6 @@ class Detector(CppDetectorApi): res = self.getMeasuredSubFramePeriod() return element_if_equal([it.total_seconds() for it in res]) - @property def storeinram(self): return element_if_equal(self.getStoreInRamMode()) @@ -748,11 +740,19 @@ class Detector(CppDetectorApi): def storeinram(self, value): self.setStoreInRamMode(value) - """ Jungfrau specific """ + @property + @element + def auto_comp_disable(self): + return self.getAutoCompDisable() + + @auto_comp_disable.setter + def auto_comp_disable(self, value): + self.setAutoCompDisable(value) + @property @element def storagecells(self): @@ -780,9 +780,49 @@ class Detector(CppDetectorApi): def storagecell_delay(self, t): self.setStorageCellDelay(ut.make_timedelta(t)) + @property + @element + def temp_threshold(self): + return self.getThresholdTemperature() + + @temp_threshold.setter + def temp_threshold(self, value): + self.setThresholdTemperature(value) + + @property + @element + def temp_event(self): + return self.getTemperatureEvent() + + @temp_event.setter + def temp_event(self, value): + if value != 0: + raise ValueError("Value needs to be 0 for reset. Setting not allowed") + self.resetTemperatureEvent() + + @property + @element + def temp_control(self): + return self.getTemperatureControl() + + @temp_control.setter + def temp_control(self, value): + self.setTemperatureControl(value) + + + @property + @element + def selinterface(self): + return self.getSelectedUDPInterface() + + @selinterface.setter + def selinterface(self, i): + self.selectUDPInterface(i) + """ Gotthard2 """ + @property @element def veto(self): @@ -793,11 +833,23 @@ class Detector(CppDetectorApi): self.setVeto(value) - """ Mythen3 specific """ + @property + def gatedelay(self): + return reduce_time(self.getGateDelayForAllGates()) + + @gatedelay.setter + def gatedelay(self, value): + if is_iterable(value): + if len(value) == 3: + for i, v in enumerate(value): + self.setGateDelay(i, ut.make_timedelta(v)) + else: + self.setGateDelay(-1, ut.make_timedelta(value)) + @property def counters(self): mask = self.getCounterMask() @@ -807,11 +859,10 @@ class Detector(CppDetectorApi): else: return [get_set_bits(m) for m in mask] - @counters.setter def counters(self, values): self.setCounterMask(list_to_bitmask(values)) - + """ CTB stuff """ @@ -859,7 +910,7 @@ class Detector(CppDetectorApi): @property def dbitclk(self): return element_if_equal(self.getDBITClock()) - + @dbitclk.setter def dbitclk(self, value): self.setDBITClock(value) @@ -899,7 +950,7 @@ class Detector(CppDetectorApi): @property def adcphase(self): return element_if_equal(self.getADCPhase()) - + @adcphase.setter def adcphase(self, value): self.setADCPhase(value) @@ -923,10 +974,10 @@ class Detector(CppDetectorApi): @property def syncclk(self): return element_if_equal(self.getSYNCClock()) - + @property def pattern(self): - #TODO! Clean fix + # TODO! Clean fix print("Set only") return 0 @@ -1015,7 +1066,6 @@ class Detector(CppDetectorApi): def patwaittime2(self, nclk): self.setPatternWaitTime(2, nclk) - @property def patloop0(self): return element_if_equal(self.getPatternLoopAddresses(0)) @@ -1064,7 +1114,6 @@ class Detector(CppDetectorApi): def patnloop2(self, n): self.setPatternLoopCycles(2, n) - @property @element def v_a(self): @@ -1142,4 +1191,4 @@ class Detector(CppDetectorApi): @property @element def im_io(self): - return self.getMeasuredCurrent(dacIndex.I_POWER_IO) \ No newline at end of file + return self.getMeasuredCurrent(dacIndex.I_POWER_IO)