mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-20 02:40:03 +02:00
2022 lines
56 KiB
Python
Executable File
2022 lines
56 KiB
Python
Executable File
from _slsdet import CppDetectorApi
|
|
from _slsdet import slsDetectorDefs
|
|
from _slsdet import IpAddr, MacAddr
|
|
|
|
runStatus = slsDetectorDefs.runStatus
|
|
timingMode = slsDetectorDefs.timingMode
|
|
speedLevel = slsDetectorDefs.speedLevel
|
|
dacIndex = slsDetectorDefs.dacIndex
|
|
detectorType = slsDetectorDefs.detectorType
|
|
|
|
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
|
|
from . import utils as ut
|
|
from .registers import Register, Adc_register
|
|
import datetime as dt
|
|
|
|
from functools import wraps
|
|
from collections import namedtuple
|
|
import socket
|
|
import numpy as np
|
|
|
|
def freeze(cls):
|
|
cls._frozen = False
|
|
|
|
def frozensetattr(self, key, value):
|
|
if self._frozen and not key in dir(self):
|
|
raise AttributeError(
|
|
"Class {} is frozen. Cannot set {} = {}".format(
|
|
cls.__name__, key, value
|
|
)
|
|
)
|
|
else:
|
|
object.__setattr__(self, key, value)
|
|
|
|
def init_decorator(func):
|
|
@wraps(func)
|
|
def wrapper(self, *args, **kwargs):
|
|
func(self, *args, **kwargs)
|
|
self._frozen = True
|
|
|
|
return wrapper
|
|
|
|
cls.__setattr__ = frozensetattr
|
|
cls.__init__ = init_decorator(cls.__init__)
|
|
return cls
|
|
|
|
|
|
@freeze
|
|
class Detector(CppDetectorApi):
|
|
"""
|
|
This class is the base for detector specific
|
|
interfaces. Most functions exists in two versions
|
|
like the getExptime() function that uses the
|
|
C++ API directly and the simplified exptime property.
|
|
"""
|
|
|
|
def __init__(self, multi_id=0):
|
|
"""
|
|
multi_id refers to the shared memory id of the
|
|
slsDetectorPackage. Default value is 0.
|
|
"""
|
|
super().__init__(multi_id)
|
|
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())
|
|
|
|
def free(self):
|
|
"""Free detector shared memory"""
|
|
self.freeSharedMemory()
|
|
|
|
@property
|
|
def config(self):
|
|
"""Load configuration file.
|
|
|
|
Note
|
|
-----
|
|
Frees shared memory before loading configuration file.
|
|
Set up once.
|
|
|
|
:getter: Not implemented
|
|
:setter: Loads config file
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.config = "/path/to/config/file.config"
|
|
|
|
"""
|
|
return NotImplementedError("config is set only")
|
|
|
|
@config.setter
|
|
def config(self, fname):
|
|
fname = ut.make_string_path(fname)
|
|
self.loadConfig(fname)
|
|
|
|
@property
|
|
def parameters(self):
|
|
"""Sets detector measurement parameters to those contained in fname. Set up per measurement.
|
|
|
|
Note
|
|
-----
|
|
Equivalent to config, but does not free shared memory.
|
|
|
|
|
|
:getter: Not implemented
|
|
:setter: loads parameters file
|
|
|
|
Example
|
|
---------
|
|
|
|
>>> d.parameters = 'path/to/file.par'
|
|
|
|
"""
|
|
return NotImplementedError("parameters is set only")
|
|
|
|
@parameters.setter
|
|
def parameters(self, value):
|
|
if isinstance(value, str):
|
|
value = ut.make_string_path(value)
|
|
self.loadParameters(value)
|
|
|
|
@property
|
|
def hostname(self):
|
|
"""Frees shared memory and sets hostname (or IP address) of all modules concatenated by + """
|
|
return self.getHostname()
|
|
|
|
@hostname.setter
|
|
def hostname(self, hostnames):
|
|
if isinstance(hostnames, str):
|
|
hostnames = [hostnames]
|
|
if isinstance(hostnames, list):
|
|
self.setHostname(hostnames)
|
|
else:
|
|
raise ValueError("hostname needs to be string or list of strings")
|
|
|
|
@property
|
|
def firmwareversion(self):
|
|
return element_if_equal(self.getFirmwareVersion())
|
|
|
|
@property
|
|
def detectorserverversion(self):
|
|
# TODO! handle hex print
|
|
return element_if_equal(self.getDetectorServerVersion())
|
|
|
|
@property
|
|
def clientversion(self):
|
|
return self.getClientVersion()
|
|
|
|
@property
|
|
def rx_version(self):
|
|
"""Receiver version in format [0xYYMMDD]."""
|
|
return element_if_equal(self.getReceiverVersion())
|
|
|
|
@property
|
|
def dr(self):
|
|
"""
|
|
Dynamic range or number of bits per pixel/channel.
|
|
|
|
Note
|
|
-----
|
|
[Eiger] Options: 4, 8, 16, 32. If set to 32, also sets clkdivider to 2 (quarter speed), else to 0 (full speed)\n
|
|
[Mythen3] Options: 8, 16, 32 \n
|
|
[Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16
|
|
"""
|
|
return element_if_equal(self.getDynamicRange())
|
|
|
|
@dr.setter
|
|
def dr(self, dr):
|
|
self.setDynamicRange(dr)
|
|
|
|
@property
|
|
def module_geometry(self):
|
|
return to_geo(self.getModuleGeometry())
|
|
|
|
@property
|
|
def module_size(self):
|
|
ms = [to_geo(item) for item in self.getModuleSize()]
|
|
return element_if_equal(ms)
|
|
|
|
@property
|
|
def detector_size(self):
|
|
return to_geo(self.getDetectorSize())
|
|
|
|
@property
|
|
def settings(self):
|
|
"""
|
|
Detector settings. Enum: detectorSettings
|
|
Notes
|
|
-----
|
|
|
|
[Eiger] Use threshold command to load settings
|
|
[Jungfrau] DYNAMICGAIN, DYNAMICHG0, FIXGAIN1, FIXGAIN2, FORCESWITCHG1, FORCESWITCHG2 \n
|
|
[Gotthard] DYNAMICGAIN, HIGHGAIN, LOWGAIN, MEDIUMGAIN, VERYHIGHGAIN \n
|
|
[Gotthard2] DYNAMICGAIN, FIXGAIN1, FIXGAIN2 \n
|
|
[Moench] G1_HIGHGAIN, G1_LOWGAIN, G2_HIGHCAP_HIGHGAIN, G2_HIGHCAP_LOWGAIN, G2_LOWCAP_HIGHGAIN, G2_LOWCAP_LOWGAIN, G4_HIGHGAIN, G4_LOWGAIN \n
|
|
[Eiger] settings loaded from file found in settingspath
|
|
"""
|
|
return element_if_equal(self.getSettings())
|
|
|
|
@settings.setter
|
|
def settings(self, value):
|
|
self.setSettings(value)
|
|
|
|
@property
|
|
def frames(self):
|
|
"""Number of frames per acquisition. In trigger mode, number of frames per trigger.
|
|
|
|
Notes
|
|
-----
|
|
Cannot be set in modular level. ????
|
|
In scan mode, number of frames is set to number of steps.
|
|
[Gotthard2] Burst mode has a maximum of 2720 frames.
|
|
"""
|
|
return element_if_equal(self.getNumberOfFrames())
|
|
|
|
@frames.setter
|
|
def frames(self, n_frames):
|
|
self.setNumberOfFrames(n_frames)
|
|
|
|
@property
|
|
def triggers(self):
|
|
return element_if_equal(self.getNumberOfTriggers())
|
|
|
|
@triggers.setter
|
|
def triggers(self, n_triggers):
|
|
self.setNumberOfTriggers(n_triggers)
|
|
|
|
@property
|
|
def exptime(self):
|
|
"""
|
|
Exposure time, accepts either a value in seconds or datetime.timedelta
|
|
|
|
Note
|
|
-----
|
|
[Mythen3] sets exposure time to all gate signals in auto and trigger mode (internal gating). To specify gateIndex, use getExptime or setExptime.
|
|
|
|
:getter: always returns in seconds. To get in datetime.delta, use getExptime
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.exptime = 1.05
|
|
>>> d.exptime = datetime.timedelta(minutes = 3, seconds = 1.23)
|
|
>>> d.exptime
|
|
181.23
|
|
>>> d.getExptime()
|
|
[datetime.timedelta(seconds=181, microseconds=230000)]
|
|
"""
|
|
if self.type == detectorType.MYTHEN3:
|
|
res = self.getExptimeForAllGates()
|
|
else:
|
|
res = self.getExptime()
|
|
return reduce_time(res)
|
|
|
|
@exptime.setter
|
|
def exptime(self, t):
|
|
if self.type == detectorType.MYTHEN3 and is_iterable(t):
|
|
for i, v in enumerate(t):
|
|
if isinstance(v, int):
|
|
v = float(v)
|
|
self.setExptime(i, v)
|
|
else:
|
|
if isinstance(t, int):
|
|
t = float(t)
|
|
self.setExptime(t)
|
|
|
|
|
|
|
|
|
|
@property
|
|
def period(self):
|
|
"""
|
|
Period between frames, accepts either a value in seconds or datetime.timedelta
|
|
|
|
Note
|
|
-----
|
|
:getter: always returns in seconds. To get in datetime.delta, use getPeriod
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.period = 1.05
|
|
>>> d.period = datetime.timedelta(minutes = 3, seconds = 1.23)
|
|
>>> d.period
|
|
181.23
|
|
>>> d.getPeriod()
|
|
[datetime.timedelta(seconds=181, microseconds=230000)]
|
|
"""
|
|
res = self.getPeriod()
|
|
return reduce_time(res)
|
|
|
|
@period.setter
|
|
def period(self, t):
|
|
self.setPeriod(t)
|
|
|
|
@property
|
|
@element
|
|
def delay(self):
|
|
"""
|
|
[Gotthard][Jungfrau][CTB][Moench][Mythen3][Gotthard2] Delay after trigger, accepts either a value in seconds or datetime.timedelta
|
|
|
|
Note
|
|
-----
|
|
:getter: always returns in seconds. To get in datetime.delta, use getDelayAfterTrigger
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.delay = 1.05
|
|
>>> d.delay = datetime.timedelta(minutes = 3, seconds = 1.23)
|
|
>>> d.delay
|
|
181.23
|
|
>>> d.getDelayAfterTrigger()
|
|
[datetime.timedelta(seconds=181, microseconds=230000)]
|
|
"""
|
|
return ut.reduce_time(self.getDelayAfterTrigger())
|
|
|
|
@delay.setter
|
|
def delay(self, t):
|
|
self.setDelayAfterTrigger(t)
|
|
|
|
@property
|
|
@element
|
|
def delayl(self):
|
|
"""
|
|
[Gotthard][Jungfrau][CTB][Moench][Mythen3][Gotthard2] Delay left after trigger during acquisition, accepts either a value in seconds or datetime.timedelta
|
|
|
|
Note
|
|
-----
|
|
[Gotthard2] only in continuous mdoe.
|
|
:getter: always returns in seconds. To get in datetime.delta, use getDelayAfterTriggerLeft
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.delay
|
|
181.23
|
|
>>> d.getDelayAfterTrigger()
|
|
[datetime.timedelta(seconds=181, microseconds=230000)]
|
|
"""
|
|
return ut.reduce_time(self.getDelayAfterTriggerLeft())
|
|
|
|
def start(self):
|
|
"""Start detector acquisition. Status changes to RUNNING or WAITING and automatically returns to idle at the end of acquisition."""
|
|
self.startDetector()
|
|
|
|
def rx_start(self):
|
|
"""Starts receiver listener for detector data packets and create a data file (if file write enabled)."""
|
|
self.startReceiver()
|
|
|
|
def rx_stop(self):
|
|
"""Stops receiver listener for detector data packets and closes current data file (if file write enabled)."""
|
|
self.stopReceiver()
|
|
|
|
def stop(self):
|
|
"""Abort detector acquisition. Status changes to IDLE or STOPPED"""
|
|
self.stopDetector()
|
|
|
|
# Time
|
|
@property
|
|
def rx_framescaught(self):
|
|
"""Number of frames caught by receiver."""
|
|
return element_if_equal(self.getFramesCaught())
|
|
|
|
@property
|
|
def startingfnum(self):
|
|
"""[Eiger][Jungfrau] Starting frame number for next acquisition. Stopping acquiistion might result in different frame numbers for different modules. """
|
|
return element_if_equal(self.getStartingFrameNumber())
|
|
|
|
@startingfnum.setter
|
|
def startingfnum(self, value):
|
|
self.setStartingFrameNumber(value)
|
|
|
|
# TODO! add txdelay
|
|
|
|
@property
|
|
def use_receiver(self):
|
|
return element_if_equal(self.getUseReceiverFlag())
|
|
|
|
@property
|
|
def rx_hostname(self):
|
|
""" Sets receiver hostname or IP address. Used for TCP control communication between client and receiver to configure receiver. Also updates receiver with detector parameters.
|
|
Notes
|
|
-----
|
|
Also resets any prior receiver property (not on detector). \n
|
|
Can concatenate receiver hostnames for every module. \n
|
|
If port included, then its the receiver tcp port for every receiver hostname.
|
|
Example
|
|
--------
|
|
>>> d.rx_hostname
|
|
'mpc1922'
|
|
>>> d.rx_hostname = 'mpc1922'
|
|
>>> d.rx_hostname = 'mpc1922:2000'
|
|
>>> d.rx_hostname = 'mpc1922:2000+mpc1922:2002'
|
|
>>> d.rx_hostname
|
|
'mpc1922'
|
|
>>> d.rx_tcpport
|
|
[2000, 2002]
|
|
"""
|
|
return element_if_equal(self.getRxHostname())
|
|
|
|
@rx_hostname.setter
|
|
def rx_hostname(self, hostname):
|
|
self.setRxHostname(hostname)
|
|
|
|
@property
|
|
def rx_tcpport(self):
|
|
"""
|
|
TCP port for client-receiver communication.
|
|
Notes
|
|
-----
|
|
Default is 1954. \n
|
|
Must be different if multiple receivers on same pc. \n
|
|
Must be first command to set a receiver parameter to be able to communicate. \n
|
|
Multi command will automatically increment port for individual modules, which must be set via setRxPort.
|
|
Example
|
|
-------
|
|
>>> d.rx_tcpport
|
|
2010
|
|
>>> d.rx_tcpport
|
|
[2000, 2002]
|
|
"""
|
|
return element_if_equal(self.getRxPort())
|
|
|
|
@rx_tcpport.setter
|
|
def rx_tcpport(self, port):
|
|
self.setRxPort(port)
|
|
|
|
@property
|
|
def rx_fifodepth(self):
|
|
"""Sets the number of frames in the receiver fifo depth (buffer between listener and writer threads)."""
|
|
return element_if_equal(self.getRxFifoDepth())
|
|
|
|
@rx_fifodepth.setter
|
|
def rx_fifodepth(self, frames):
|
|
self.setRxFifoDepth(frames)
|
|
|
|
@property
|
|
def rx_silent(self):
|
|
"""When enabled, switches off receiver text output during acquisition. """
|
|
return element_if_equal(self.getRxSilentMode())
|
|
|
|
@rx_silent.setter
|
|
def rx_silent(self, value):
|
|
self.setRxSilentMode(value)
|
|
|
|
@property
|
|
def rx_discardpolicy(self):
|
|
"""
|
|
Frame discard policy of receiver. Enum: frameDiscardPolicy
|
|
Notes
|
|
-----
|
|
Options: NO_DISCARD, DISCARD_EMPTY_FRAMES, DISCARD_PARTIAL_FRAMES \n
|
|
Default: NO_DISCARD \n
|
|
DISCARD_PARTIAL_FRAMES is the fastest.
|
|
|
|
Example
|
|
--------
|
|
>>> d.rx_discardpolicy = frameDiscardPolicy.NO_DISCARD
|
|
>>> d.rx_discardpolicy
|
|
frameDiscardPolicy.NO_DISCARD
|
|
"""
|
|
return element_if_equal(self.getRxFrameDiscardPolicy())
|
|
|
|
@rx_discardpolicy.setter
|
|
def rx_discardpolicy(self, policy):
|
|
self.setRxFrameDiscardPolicy()
|
|
|
|
@property
|
|
def rx_padding(self):
|
|
"""Partial frames padding enable in the receiver.
|
|
Notes
|
|
------
|
|
Default: enabled \n
|
|
Disabling is fastest.
|
|
"""
|
|
return element_if_equal(self.getPartialFramesPadding())
|
|
|
|
@rx_padding.setter
|
|
def rx_padding(self, policy):
|
|
self.setPartialFramesPadding(policy)
|
|
|
|
@property
|
|
def rx_lock(self):
|
|
"""Lock the receiver to a specific IP"""
|
|
return element_if_equal(self.getRxLock())
|
|
|
|
@rx_lock.setter
|
|
def rx_lock(self, value):
|
|
self.setRxLock(value)
|
|
|
|
@property
|
|
def rx_lastclient(self):
|
|
"""Client IP Address that last communicated with the receiver."""
|
|
return element_if_equal(self.getRxLastClientIP())
|
|
|
|
# FILE
|
|
|
|
@property
|
|
@element
|
|
def numinterfaces(self):
|
|
"""[Jungfrau][Gotthard2] Number of udp interfaces to stream data from detector. Default is 1.
|
|
Note
|
|
-----
|
|
Also enables second interface in receiver for listening (Writes a file per interface if writing enabled). \n
|
|
Also restarts client and receiver zmq sockets if zmq streaming enabled. \n
|
|
[Gotthard2] second interface enabled to send veto information via 10Gbps for debugging. By default, if veto enabled, it is sent via 2.5 gbps interface.
|
|
"""
|
|
return self.getNumberofUDPInterfaces()
|
|
|
|
@numinterfaces.setter
|
|
def numinterfaces(self, value):
|
|
self.setNumberofUDPInterfaces(value)
|
|
|
|
@property
|
|
def fformat(self):
|
|
""" File format of data file in receiver. Enum: fileFormat
|
|
|
|
Note
|
|
-----
|
|
Options: BINARY, HDF5
|
|
Default: BINARY
|
|
For HDF5, package must be compiled with HDF5 flags. Default is binary.
|
|
|
|
Example
|
|
--------
|
|
d.fformat = fileFormat.BINARY
|
|
|
|
"""
|
|
return element_if_equal(self.getFileFormat())
|
|
|
|
@fformat.setter
|
|
def fformat(self, format):
|
|
self.setFileFormat(format)
|
|
|
|
@property
|
|
def findex(self):
|
|
"""File or Acquisition index in receiver."""
|
|
return element_if_equal(self.getAcquisitionIndex())
|
|
|
|
@findex.setter
|
|
def findex(self, index):
|
|
self.setAcquisitionIndex(index)
|
|
|
|
@property
|
|
def fname(self):
|
|
"""File name prefix for output data file in receiver. Default is run.
|
|
|
|
Note
|
|
-----
|
|
File name: [file name prefix]_d[detector index]_f[sub file index]_[acquisition/file index].[raw/h5].
|
|
|
|
Examples
|
|
--------
|
|
d.fname = 'run'
|
|
eg. file name: run_d0_f0_5.raw
|
|
"""
|
|
return element_if_equal(self.getFileNamePrefix())
|
|
|
|
@fname.setter
|
|
def fname(self, file_name):
|
|
self.setFileNamePrefix(file_name)
|
|
|
|
@property
|
|
def fpath(self):
|
|
"""Directory where output data files are written in receiver.
|
|
|
|
Note
|
|
----
|
|
If path does not exist, it will try to create it.
|
|
|
|
Examples
|
|
--------
|
|
d.fpath = '/tmp/run_20201705'
|
|
"""
|
|
return element_if_equal(self.getFilePath())
|
|
|
|
@fpath.setter
|
|
def fpath(self, path):
|
|
path = ut.make_string_path(path)
|
|
self.setFilePath(path)
|
|
|
|
@property
|
|
def fwrite(self):
|
|
"""Enable or disable receiver file write. Default is enabled. """
|
|
return element_if_equal(self.getFileWrite())
|
|
|
|
@fwrite.setter
|
|
def fwrite(self, value):
|
|
self.setFileWrite(value)
|
|
|
|
@property
|
|
def foverwrite(self):
|
|
"""Enable or disable receiver file overwriting. Default is enabled. """
|
|
return element_if_equal(self.getFileOverWrite())
|
|
|
|
@foverwrite.setter
|
|
def foverwrite(self, value):
|
|
self.setFileOverWrite(value)
|
|
|
|
@property
|
|
def fmaster(self):
|
|
"""Enable or disable receiver master file. Default is enabled."""
|
|
return element_if_equal(self.getMasterFileWrite())
|
|
|
|
@fmaster.setter
|
|
def fmaster(self, enable):
|
|
self.setMasterFileWrite(enable)
|
|
|
|
@property
|
|
def rx_framesperfile(self):
|
|
"""Sets the number of frames per file in receiver.
|
|
|
|
Notes
|
|
-----
|
|
Default: depends on detector type. \n
|
|
0 is infinite or all frames in single file.
|
|
"""
|
|
return element_if_equal(self.getFramesPerFile())
|
|
|
|
@rx_framesperfile.setter
|
|
def rx_framesperfile(self, n_frames):
|
|
self.setFramesPerFile(n_frames)
|
|
|
|
# ZMQ Streaming Parameters (Receiver<->Client)
|
|
|
|
@property
|
|
def rx_datastream(self):
|
|
"""
|
|
Enable/ disable data streaming from receiver via zmq (eg. to GUI or to another process for further processing). \n
|
|
This creates/ destroys zmq streamer threads in receiver. \n
|
|
Switching to Gui automatically enables data streaming in receiver. \n
|
|
Switching back to command line acquire will require disabling data streaming in receiver for fast applications.
|
|
"""
|
|
return element_if_equal(self.getRxZmqDataStream())
|
|
|
|
@rx_datastream.setter
|
|
def rx_zmqdatastream(self, enable):
|
|
self.setRxZmqDataStream(enable)
|
|
|
|
@property
|
|
def rx_readfreq(self):
|
|
"""Frequency of frames streamed out from receiver via zmq.
|
|
Notes
|
|
-----
|
|
Default: 1, Means every frame is streamed out. \n
|
|
If 2, every second frame is streamed out. \n
|
|
If 0, streaming timer is the timeout, after which current frame is sent out. (default timeout is 200 ms). Usually used for gui purposes.
|
|
"""
|
|
return element_if_equal(self.getRxZmqFrequency())
|
|
|
|
@rx_readfreq.setter
|
|
def rx_readfreq(self, nth_frame):
|
|
self.setRxZmqFrequency(nth_frame)
|
|
|
|
@property
|
|
def rx_zmqport(self):
|
|
"""
|
|
Zmq port for data to be streamed out of the receiver.
|
|
Notes
|
|
-----
|
|
Also restarts receiver zmq streaming if enabled. \n
|
|
Default is 30001. \n
|
|
Modified only when using an intermediate process after receiver. \n
|
|
Must be different for every detector (and udp port). \n
|
|
Multi command will automatically increment for individual modules, use setRxZmqPort.
|
|
|
|
Examples
|
|
--------
|
|
|
|
>>> d.rx_zmqport
|
|
[30001, 30002, 30003, 300004]
|
|
>>> d.rx_zmqport = 30001
|
|
>>> d.rx_zmqport = [30001, 30005] #Set ports for the two first detectors
|
|
|
|
"""
|
|
return element_if_equal(self.getRxZmqPort())
|
|
|
|
@rx_zmqport.setter
|
|
def rx_zmqport(self, port):
|
|
if isinstance(port, int):
|
|
self.setRxZmqPort(port, -1)
|
|
elif is_iterable(port):
|
|
for i, p in enumerate(port):
|
|
self.setRxZmqPort(p, i)
|
|
else:
|
|
raise ValueError("Unknown argument type")
|
|
|
|
@property
|
|
def zmqport(self):
|
|
return element_if_equal(self.getClientZmqPort())
|
|
|
|
@zmqport.setter
|
|
def zmqport(self, port):
|
|
if isinstance(port, int):
|
|
self.setClientZmqPort(port, -1)
|
|
elif is_iterable(port):
|
|
for i, p in enumerate(port):
|
|
self.setClientZmqPort(p, i)
|
|
else:
|
|
raise ValueError("Unknown argument type")
|
|
|
|
@property
|
|
def rx_zmqip(self):
|
|
"""
|
|
Zmq Ip Address from which data is to be streamed out of the receiver.
|
|
Notes
|
|
-----
|
|
Also restarts receiver zmq streaming if enabled. \n
|
|
Default is from rx_hostname. \n
|
|
Modified only when using an intermediate process after receiver.
|
|
|
|
Example
|
|
-------
|
|
>>> d.rx_zmqip
|
|
192.168.0.101
|
|
>>> d.rx_zmqip = ?????
|
|
"""
|
|
return element_if_equal(self.getRxZmqIP())
|
|
|
|
@rx_zmqip.setter
|
|
def rx_zmqip(self, ip):
|
|
self.setRxZmqIP(IpAddr(ip))
|
|
|
|
@property
|
|
def zmqip(self):
|
|
return element_if_equal(self.getClientZmqIp())
|
|
|
|
@zmqip.setter
|
|
def zmqip(self, ip):
|
|
self.setClientZmqIp(IpAddr(ip))
|
|
|
|
@property
|
|
def udp_dstip(self):
|
|
return element_if_equal(self.getDestinationUDPIP())
|
|
|
|
@udp_dstip.setter
|
|
def udp_dstip(self, ip):
|
|
if ip == "auto":
|
|
ip = socket.gethostbyname(self.rx_hostname)
|
|
self.setDestinationUDPIP(IpAddr(ip))
|
|
|
|
@property
|
|
def udp_dstip2(self):
|
|
return element_if_equal(self.getDestinationUDPIP2())
|
|
|
|
@udp_dstip2.setter
|
|
def udp_dstip2(self, ip):
|
|
if ip == "auto":
|
|
ip = socket.gethostbyname(self.rx_hostname)
|
|
self.setDestinationUDPIP2(IpAddr(ip))
|
|
|
|
@property
|
|
def udp_dstmac(self):
|
|
return element_if_equal(self.getDestinationUDPMAC())
|
|
|
|
@udp_dstmac.setter
|
|
def udp_dstmac(self, mac):
|
|
self.setDestinationUDPMAC(MacAddr(mac))
|
|
|
|
@property
|
|
def udp_dstmac2(self):
|
|
return element_if_equal(self.getDestinationUDPMAC2())
|
|
|
|
@udp_dstmac2.setter
|
|
def udp_dstmac2(self, mac):
|
|
self.setDestinationUDPMAC2(MacAddr(mac))
|
|
|
|
@property
|
|
def udp_srcmac(self):
|
|
return element_if_equal(self.getSourceUDPMAC())
|
|
|
|
@udp_srcmac.setter
|
|
def udp_srcmac(self, mac):
|
|
if isinstance(mac, (list, tuple)):
|
|
for i, m in enumerate(mac):
|
|
self.setSourceUDPMAC(MacAddr(m), [i])
|
|
else:
|
|
self.setSourceUDPMAC(MacAddr(mac))
|
|
|
|
@property
|
|
def udp_srcmac2(self):
|
|
return element_if_equal(self.getSourceUDPMAC2())
|
|
|
|
@udp_srcmac2.setter
|
|
def udp_srcmac2(self, mac):
|
|
if isinstance(mac, (list, tuple)):
|
|
for i, m in enumerate(mac):
|
|
self.setSourceUDPMAC2(MacAddr(m), [i])
|
|
else:
|
|
self.setSourceUDPMAC2(MacAddr(mac))
|
|
|
|
@property
|
|
def udp_srcip(self):
|
|
return element_if_equal(self.getSourceUDPIP())
|
|
|
|
@udp_srcip.setter
|
|
def udp_srcip(self, ip):
|
|
self.setSourceUDPIP(IpAddr(ip))
|
|
|
|
@property
|
|
def udp_srcip2(self):
|
|
return element_if_equal(self.getSourceUDPIP2())
|
|
|
|
@udp_srcip2.setter
|
|
def udp_srcip2(self, ip):
|
|
self.setSourceUDPIP2(IpAddr(ip))
|
|
|
|
@property
|
|
def udp_dstport(self):
|
|
return element_if_equal(self.getDestinationUDPPort())
|
|
|
|
@udp_dstport.setter
|
|
def udp_dstport(self, port):
|
|
self.setDestinationUDPPort(port)
|
|
|
|
@property
|
|
def udp_dstport2(self):
|
|
return element_if_equal(self.getDestinationUDPPort2())
|
|
|
|
@udp_dstport2.setter
|
|
def udp_dstport2(self, port):
|
|
self.setDestinationUDPPort2(port)
|
|
|
|
@property
|
|
def src_udpmac(self):
|
|
return element_if_equal(self.getSourceUDPMAC())
|
|
|
|
@src_udpmac.setter
|
|
def src_udpmac(self, mac):
|
|
self.setSourceUDPMAC(MacAddr(mac))
|
|
|
|
@property
|
|
def src_udpip2(self):
|
|
return element_if_equal(self.getSourceUDPIP())
|
|
|
|
@src_udpip2.setter
|
|
def src_udpip2(self, ip):
|
|
self.setSourceUDPIP(IpAddr(ip))
|
|
|
|
@property
|
|
def src_udpip(self):
|
|
return element_if_equal(self.getSourceUDPIP())
|
|
|
|
@src_udpip.setter
|
|
def src_udpip(self, ip):
|
|
self.setSourceUDPIP(IpAddr(ip))
|
|
|
|
@property
|
|
def src_udpmac2(self):
|
|
return element_if_equal(self.getSourceUDPMAC2())
|
|
|
|
@src_udpmac2.setter
|
|
def src_udpmac2(self, mac):
|
|
self.setSourceUDPMAC2(MacAddr(mac))
|
|
|
|
@property
|
|
def highvoltage(self):
|
|
"""High voltage to the sensor in Voltage.
|
|
|
|
Note
|
|
-----
|
|
[Gotthard] 0, 90, 110, 120, 150, 180, 200 \n
|
|
[Eiger][Mythen3][Gotthard2] 0 - 200 \n
|
|
[Jungfrau][Ctb][Moench] 0, 60 - 200
|
|
"""
|
|
return element_if_equal(self.getHighVoltage())
|
|
|
|
@highvoltage.setter
|
|
def highvoltage(self, v):
|
|
self.setHighVoltage(v)
|
|
|
|
@property
|
|
def user(self):
|
|
return self.getUserDetails()
|
|
|
|
@property
|
|
def settingspath(self):
|
|
"""[Eiger] Directory where settings files are loaded from/to."""
|
|
return element_if_equal(self.getSettingsPath())
|
|
|
|
@settingspath.setter
|
|
def settingspath(self, path):
|
|
self.setSettingsPath(path)
|
|
|
|
@property
|
|
def status(self):
|
|
"""Gets detector status. Enum: runStatus
|
|
Notes
|
|
-----
|
|
Options: IDLE, ERROR, WAITING, RUN_FINISHED, TRANSMITTING, RUNNING, STOPPED
|
|
>>> d.status
|
|
runStatus.IDLE
|
|
"""
|
|
return element_if_equal(self.getDetectorStatus())
|
|
|
|
@property
|
|
def rx_status(self):
|
|
"""Gets receiver listener status. Enum: runStatus
|
|
Notes
|
|
-----
|
|
Options: IDLE, TRANSMITTING, RUNNING
|
|
>>> d.rx_status
|
|
runStatus.IDLE
|
|
"""
|
|
return element_if_equal(self.getReceiverStatus())
|
|
|
|
@property
|
|
def rx_udpsocksize(self):
|
|
"""UDP socket buffer size in receiver. Tune rmem_default and rmem_max accordingly."""
|
|
return element_if_equal(self.getRxUDPSocketBufferSize())
|
|
|
|
@rx_udpsocksize.setter
|
|
def rx_udpsocksize(self, buffer_size):
|
|
self.setRxUDPSocketBufferSize(buffer_size)
|
|
|
|
@property
|
|
def rx_realudpsocksize(self):
|
|
"""Gets actual udp socket buffer size. Double the size of rx_udpsocksize due to kernel bookkeeping."""
|
|
return element_if_equal(self.getRxRealUDPSocketBufferSize())
|
|
|
|
@property
|
|
def trimbits(self):
|
|
return NotImplementedError("trimbits are set only")
|
|
|
|
@trimbits.setter
|
|
def trimbits(self, fname):
|
|
fname = ut.make_string_path(fname)
|
|
self.loadTrimbits(fname)
|
|
|
|
@property
|
|
def lock(self):
|
|
"""Lock detector to one client IP, 1 locks, 0 unlocks. Default is unlocked."""
|
|
return element_if_equal(self.getDetectorLock())
|
|
|
|
@lock.setter
|
|
def lock(self, value):
|
|
self.setDetectorLock(value)
|
|
|
|
@property
|
|
def rx_lock(self):
|
|
"""Lock receiver to one client IP, 1 locks, 0 unlocks. Default is unlocked."""
|
|
return element_if_equal(self.getRxLock())
|
|
|
|
@rx_lock.setter
|
|
def rx_lock(self, value):
|
|
self.setRxLock(value)
|
|
|
|
@property
|
|
def lastclient(self):
|
|
"""Get Client IP Address that last communicated with the detector."""
|
|
return element_if_equal(self.getLastClientIP())
|
|
|
|
@property
|
|
def reg(self):
|
|
"""
|
|
Reads/writes to a 32 bit register.
|
|
|
|
Note
|
|
-----
|
|
Advanced user Function! \n
|
|
[Eiger] Address is +0x100 for only left, +0x200 for only right.
|
|
"""
|
|
return self._register
|
|
|
|
@property
|
|
def daclist(self):
|
|
"""Gets the list of enums for every dac for this detector."""
|
|
return self.getDacList()
|
|
|
|
@property
|
|
def dacvalues(self):
|
|
"""Gets the dac values for every dac for this detector."""
|
|
return {
|
|
dac.name.lower(): np.array(self.getDAC(dac, False))
|
|
for dac in self.getDacList()
|
|
}
|
|
|
|
@property
|
|
def timinglist(self):
|
|
return self.getTimingModeList()
|
|
|
|
@property
|
|
def templist(self):
|
|
return self.getTemperatureList()
|
|
|
|
@property
|
|
def tempvalues(self):
|
|
"""Gets the temp values for every temp for this detector."""
|
|
return {
|
|
t.name.lower(): np.array(self.getTemperature(t))
|
|
for t in self.getTemperatureList()
|
|
}
|
|
|
|
@property
|
|
def settingslist(self):
|
|
return self.getSettingsList()
|
|
|
|
@property
|
|
def adcreg(self):
|
|
"""[Jungfrau][Ctb][Moench][Gotthard] Writes to an adc register
|
|
|
|
Note
|
|
-----
|
|
Advanced user Function!
|
|
|
|
:getter: Not implemented
|
|
"""
|
|
return self._adc_register
|
|
|
|
@property
|
|
def led(self):
|
|
"""[Ctb] Switches on/off all LEDs. Default is enabled. """
|
|
return element_if_equal(self.getLEDEnable())
|
|
|
|
@led.setter
|
|
def led(self, value):
|
|
self.setLEDEnable(value)
|
|
|
|
|
|
@property
|
|
def versions(self):
|
|
return {'type': self.type,
|
|
'package': self.packageversion,
|
|
'client': self.clientversion,
|
|
'firmware': self.firmwareversion,
|
|
'detectorserver': self.detectorserverversion,
|
|
'receiver': self.rx_version}
|
|
|
|
|
|
@property
|
|
def packageversion(self):
|
|
return self.getPackageVersion()
|
|
|
|
|
|
@property
|
|
def ratecorr(self):
|
|
"""
|
|
[Eiger] Custom dead time correction constant in ns. 0 will unset rate correction.
|
|
|
|
Note
|
|
-----
|
|
To set default rate correction, use setDefaultRateCorrection
|
|
|
|
Known Issue
|
|
------------
|
|
:getter: Always give 0 due to the microseconds precision.
|
|
:setter: Use scientific notation to set custom rate correction, since timedelta resolution is 1 microseconds. \n
|
|
Or use setDefaultRateCorrection to set the default one from trimbit file
|
|
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.ratecorr = 10e-9
|
|
>>> d.setDefaultRateCorrection()
|
|
>>> d.ratecorr = 0.0
|
|
"""
|
|
return reduce_time(self.getRateCorrection())
|
|
|
|
@ratecorr.setter
|
|
def ratecorr(self, tau):
|
|
if isinstance(tau, int):
|
|
tau = float(tau)
|
|
self.setRateCorrection(tau)
|
|
|
|
@property
|
|
def speed(self):
|
|
"""
|
|
[Eiger][Jungfrau] Readout speed of chip. Enum: speedLevel
|
|
Notes
|
|
-----
|
|
Options: FULL_SPEED, HALF_SPEED, QUARTER_SPEED \n
|
|
[Jungfrau] FULL_SPEED option only available from v2.0 boards and with setting number of interfaces to 2. \n
|
|
Also overwrites adcphase to recommended default.
|
|
"""
|
|
return element_if_equal(self.getSpeed())
|
|
|
|
@speed.setter
|
|
def speed(self, value):
|
|
self.setSpeed(value)
|
|
|
|
@property
|
|
def frameindex(self):
|
|
return self.getRxCurrentFrameIndex()
|
|
|
|
@property
|
|
def threshold(self):
|
|
return element_if_equal(self.getThresholdEnergy())
|
|
|
|
@threshold.setter
|
|
def threshold(self, eV):
|
|
self.setThresholdEnergy(eV)
|
|
|
|
@property
|
|
def timing(self):
|
|
return element_if_equal(self.getTimingMode())
|
|
|
|
@timing.setter
|
|
def timing(self, mode):
|
|
self.setTimingMode(mode)
|
|
|
|
@property
|
|
def trimen(self):
|
|
return element_if_equal(self.getTrimEnergies())
|
|
|
|
@trimen.setter
|
|
def trimen(self, energies):
|
|
self.setTrimEnergies(energies)
|
|
|
|
@property
|
|
def vthreshold(self):
|
|
return element_if_equal(self.getDAC(dacIndex.VTHRESHOLD, False))
|
|
|
|
@vthreshold.setter
|
|
def vthreshold(self, value):
|
|
self.setDAC(dacIndex.VTHRESHOLD, value, False)
|
|
|
|
@property
|
|
def type(self):
|
|
return element_if_equal(self.getDetectorType())
|
|
|
|
@property
|
|
def rx_frameindex(self):
|
|
"""Current frame index received in receiver during acquisition."""
|
|
return element_if_equal(self.getRxCurrentFrameIndex())
|
|
|
|
@property
|
|
def rx_missingpackets(self):
|
|
"""Gets the number of missing packets for each port in receiver."""
|
|
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):
|
|
"""
|
|
[Eiger] Exposure time of EIGER subframes in 32 bit mode.
|
|
Note
|
|
----
|
|
Subperiod = subexptime + subdeadtime.
|
|
:getter: always returns in seconds. To get in datetime.delta, use getSubExptime
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.subexptime = 1.230203
|
|
>>> d.subexptime = datetime.timedelta(seconds = 1.23, microseconds = 203)
|
|
>>> d.subexptime
|
|
1.230203
|
|
>>> d.getSubExptime()
|
|
[datetime.timedelta(seconds = 1, microseconds = 203)]
|
|
"""
|
|
res = self.getSubExptime()
|
|
return reduce_time(res)
|
|
|
|
@subexptime.setter
|
|
def subexptime(self, t):
|
|
self.setSubExptime(t)
|
|
|
|
@property
|
|
def subdeadtime(self):
|
|
"""
|
|
[Eiger] Dead time of EIGER subframes in 32 bit mode, accepts either a value in seconds or datetime.timedelta
|
|
Note
|
|
----
|
|
Subperiod = subexptime + subdeadtime.
|
|
:getter: always returns in seconds. To get in datetime.delta, use getSubDeadTime
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.subdeadtime = 1.230203
|
|
>>> d.subdeadtime = datetime.timedelta(seconds = 1.23, microseconds = 203)
|
|
>>> d.subdeadtime
|
|
1.230203
|
|
>>> d.getSubDeadTime()
|
|
[datetime.timedelta(seconds = 1, microseconds = 203)]
|
|
"""
|
|
res = self.getSubDeadTime()
|
|
return reduce_time(res)
|
|
|
|
@subdeadtime.setter
|
|
def subdeadtime(self, t):
|
|
self.setSubDeadTime(t)
|
|
|
|
|
|
@property
|
|
@element
|
|
def parallel(self):
|
|
"""
|
|
[Eiger] Enable or disable the parallel readout mode of Eiger.
|
|
"""
|
|
return self.getParallelMode()
|
|
|
|
@parallel.setter
|
|
def parallel(self, value):
|
|
self.setParallelMode(value)
|
|
|
|
@property
|
|
def partialreset(self):
|
|
"""[Eiger] Sets up detector to do partial or complete reset at start of acquisition. 0 complete reset, 1 partial reset. Default is complete reset.
|
|
Note
|
|
-----
|
|
Advanced Function!
|
|
"""
|
|
return element_if_equal(self.getPartialReset())
|
|
|
|
@partialreset.setter
|
|
def partialreset(self, value):
|
|
self.setPartialReset(value)
|
|
|
|
@property
|
|
def tengiga(self):
|
|
return element_if_equal(self.getTenGiga())
|
|
|
|
@tengiga.setter
|
|
def tengiga(self, value):
|
|
self.setTenGiga(value)
|
|
|
|
@property
|
|
def overflow(self):
|
|
"""[Eiger] Enable or disable show overflow flag in 32 bit mode. Default is disabled. """
|
|
return element_if_equal(self.getOverFlowMode())
|
|
|
|
@overflow.setter
|
|
def overflow(self, value):
|
|
self.setOverFlowMode(value)
|
|
|
|
@property
|
|
def flowcontrol10g(self):
|
|
"""[Eiger][Jungfrau] Enable or disable 10GbE Flow Control."""
|
|
return element_if_equal(self.getTenGigaFlowControl())
|
|
|
|
@flowcontrol10g.setter
|
|
def flowcontrol10g(self, enable):
|
|
self.setTenGigaFlowControl(enable)
|
|
|
|
@property
|
|
def interruptsubframe(self):
|
|
"""[Eiger] Enable last subframe interrupt at required exposure time. Disabling will wait for last sub frame to finish exposing. Default is disabled."""
|
|
return element_if_equal(self.getInterruptSubframe())
|
|
|
|
@interruptsubframe.setter
|
|
def interruptsubframe(self, value):
|
|
self.setInterruptSubframe(value)
|
|
|
|
@property
|
|
def gappixels(self):
|
|
"""[Eiger][Jungfrau] Include Gap pixels in client data call back in Detecor api. Will not be in detector streaming, receiver file or streaming. Default is disabled. """
|
|
return element_if_equal(self.getRxAddGapPixels())
|
|
|
|
@gappixels.setter
|
|
def gappixels(self, value):
|
|
self.setRxAddGapPixels(value)
|
|
|
|
@property
|
|
def measuredperiod(self):
|
|
"""
|
|
[Eiger] Measured frame period between last frame and previous one.
|
|
|
|
Note
|
|
-----
|
|
Can be measured with minimum 2 frames in an acquisition.
|
|
:setter: Not implemented
|
|
"""
|
|
res = self.getMeasuredPeriod()
|
|
return element_if_equal([it.total_seconds() for it in res])
|
|
|
|
@property
|
|
def measuredsubperiod(self):
|
|
"""
|
|
[Eiger] Measured sub frame period between last sub frame and previous one.
|
|
Note
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
res = self.getMeasuredSubFramePeriod()
|
|
return element_if_equal([it.total_seconds() for it in res])
|
|
|
|
"""
|
|
Jungfrau specific
|
|
"""
|
|
|
|
@property
|
|
@element
|
|
def auto_comp_disable(self):
|
|
"""[Jungfrau] Enable or disable auto comparator disable mode.
|
|
|
|
Note
|
|
-----
|
|
By default, the on-chip gain switching is active during the entire exposure. This mode disables the on-chip gain switching comparator automatically after 93.75% of exposure time (only for longer than 100us).\n
|
|
Default is 0 or this mode disabled (comparator enabled throughout). 1 enables mode. 0 disables mode.
|
|
"""
|
|
return self.getAutoCompDisable()
|
|
|
|
@auto_comp_disable.setter
|
|
def auto_comp_disable(self, value):
|
|
self.setAutoCompDisable(value)
|
|
|
|
@property
|
|
@element
|
|
def storagecells(self):
|
|
"""
|
|
[Jungfrau] Number of additional storage cells.
|
|
Note
|
|
----
|
|
For advanced users only. \n
|
|
Options: 0 - 15. Default is 0.
|
|
The #images = #frames x #triggers x (#storagecells + 1)
|
|
"""
|
|
return self.getNumberOfAdditionalStorageCells()
|
|
|
|
@storagecells.setter
|
|
def storagecells(self, n_cells):
|
|
self.setNumberOfAdditionalStorageCells(n_cells)
|
|
|
|
@property
|
|
@element
|
|
def storagecell_start(self):
|
|
"""
|
|
[Jungfrau] Storage cell that stores the first acquisition of the series.
|
|
|
|
Note
|
|
----
|
|
For advanced users only.
|
|
Options 0-15. Default is 15. \n
|
|
"""
|
|
return self.getStorageCellStart()
|
|
|
|
@storagecell_start.setter
|
|
def storagecell_start(self, value):
|
|
self.setStorageCellStart(value)
|
|
|
|
@property
|
|
@element
|
|
def storagecell_delay(self):
|
|
"""
|
|
[Jungfrau] Additional time delay between 2 consecutive exposures in burst mode, accepts either a value in seconds or datetime.timedelta
|
|
Note
|
|
-----
|
|
For advanced users only \n
|
|
Value: 0-1638375 ns (resolution of 25ns) \n
|
|
:getter: always returns in seconds. To get in datetime.delta, use getStorageCellDelay
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.storagecell_delay = 0.00056
|
|
>>> d.storagecell_delay = datetime.timedelta(microseconds = 45)
|
|
>>> d.storagecell_delay
|
|
4.5e-05
|
|
>>> d.getStorageCellDelay()
|
|
[datetime.timedelta(microseconds=45)]
|
|
"""
|
|
return ut.reduce_time(self.getStorageCellDelay())
|
|
|
|
@storagecell_delay.setter
|
|
def storagecell_delay(self, t):
|
|
self.setStorageCellDelay(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):
|
|
"""[Jungfrau] The udp interface to stream data from detector.
|
|
Notes
|
|
-----
|
|
Effective only when number of interfaces is 1. Default: 0 (outer). Inner is 1.
|
|
"""
|
|
return self.getSelectedUDPInterface()
|
|
|
|
@selinterface.setter
|
|
def selinterface(self, i):
|
|
self.selectUDPInterface(i)
|
|
|
|
"""
|
|
Gotthard2
|
|
"""
|
|
|
|
@property
|
|
@element
|
|
def veto(self):
|
|
"""
|
|
[Gotthard2] Enable or disable veto data streaming from detector. Default is 0.
|
|
"""
|
|
return self.getVeto()
|
|
|
|
@veto.setter
|
|
def veto(self, value):
|
|
self.setVeto(value)
|
|
|
|
|
|
"""
|
|
Mythen3 specific
|
|
"""
|
|
|
|
@property
|
|
def gatedelay(self):
|
|
"""
|
|
[Mythen3] Gate Delay of all gate signals in auto and trigger mode (internal gating), accepts either a value in seconds or datetime.timedelta
|
|
|
|
Note
|
|
-----
|
|
To specify gateIndex, use getGateDelay or setGateDelay.
|
|
|
|
:getter: always returns in seconds. To get in datetime.delta, use getGateDelayForAllGates or getGateDelay(gateIndex)
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.gatedelay = 1.05
|
|
>>> d.gatedelay = datetime.timedelta(minutes = 3, seconds = 1.23)
|
|
>>> d.gatedelay
|
|
181.23
|
|
>>> d.setGateDelay(1, datetime.timedelta(seconds = 2))
|
|
>>> d.gatedelay
|
|
>>> [1.0, 2.0, 1.0]
|
|
>>> d.getExptimeForAllGates()
|
|
>>> [[datetime.timedelta(seconds=181, microseconds=230000), datetime.timedelta(seconds=181, microseconds=230000), datetime.timedelta(seconds=181, microseconds=230000)]]
|
|
"""
|
|
return reduce_time(self.getGateDelayForAllGates())
|
|
|
|
@gatedelay.setter
|
|
def gatedelay(self, value):
|
|
if is_iterable(value):
|
|
for i, v in enumerate(value):
|
|
if isinstance(v, int):
|
|
v = float(v)
|
|
self.setGateDelay(i, v)
|
|
else:
|
|
if isinstance(value, int):
|
|
value = float(value)
|
|
self.setGateDelay(-1, value)
|
|
|
|
@property
|
|
def counters(self):
|
|
"""
|
|
[Mythen3] List of counter indices enabled.
|
|
|
|
Note
|
|
-----
|
|
Each element in list can be 0 - 2 and must be non repetitive.
|
|
|
|
Examples
|
|
-----------
|
|
>>> d.counters = [0, 1]
|
|
|
|
"""
|
|
mask = self.getCounterMask()
|
|
mask = element_if_equal(mask)
|
|
if type(mask) == int:
|
|
return get_set_bits(mask)
|
|
else:
|
|
return [get_set_bits(m) for m in mask]
|
|
|
|
@counters.setter
|
|
def counters(self, values):
|
|
self.setCounterMask(list_to_bitmask(values))
|
|
|
|
"""
|
|
CTB stuff
|
|
"""
|
|
|
|
@property
|
|
def runclk(self):
|
|
"""[Ctb][Moench] Run clock in MHz."""
|
|
return element_if_equal(self.getRUNClock())
|
|
|
|
@runclk.setter
|
|
def runclk(self, freq):
|
|
self.setRUNClock(freq)
|
|
|
|
@property
|
|
def romode(self):
|
|
"""
|
|
[CTB] Readout mode of detector. Enum: readoutMode
|
|
|
|
Notes
|
|
------
|
|
Options: ANALOG_ONLY, DIGITAL_ONLY, ANALOG_AND_DIGITAL
|
|
Default: ANALOG_ONLY
|
|
|
|
Examples
|
|
--------
|
|
>>> d.romode = readoutMode.ANALOG_ONLY
|
|
>>> d.romode
|
|
readoutMode.ANALOG_ONLY
|
|
"""
|
|
return element_if_equal(self.getReadoutMode())
|
|
|
|
@romode.setter
|
|
def romode(self, mode):
|
|
self.setReadoutMode(mode)
|
|
|
|
@property
|
|
def asamples(self):
|
|
"""[Ctb][Moench] Number of analog samples expected. """
|
|
return element_if_equal(self.getNumberOfAnalogSamples())
|
|
|
|
@asamples.setter
|
|
def asamples(self, N):
|
|
self.setNumberOfAnalogSamples(N)
|
|
|
|
@property
|
|
def dsamples(self):
|
|
"""[CTB] Number of digital samples expected. """
|
|
return element_if_equal(self.getNumberOfDigitalSamples())
|
|
|
|
@dsamples.setter
|
|
def dsamples(self, N):
|
|
self.setNumberOfDigitalSamples(N)
|
|
|
|
@property
|
|
def dbitphase(self):
|
|
"""[Ctb][Jungfrau] Phase shift of clock to latch digital bits. Absolute phase shift.
|
|
|
|
Note
|
|
-----
|
|
[Ctb]Changing dbitclk also resets dbitphase and sets to previous values.
|
|
"""
|
|
return element_if_equal(self.getDBITPhase())
|
|
|
|
@dbitphase.setter
|
|
def dbitphase(self, value):
|
|
self.setDBITPhase(value)
|
|
|
|
@property
|
|
def dbitclk(self):
|
|
"""[Ctb] Clock for latching the digital bits in MHz."""
|
|
return element_if_equal(self.getDBITClock())
|
|
|
|
@dbitclk.setter
|
|
def dbitclk(self, value):
|
|
self.setDBITClock(value)
|
|
|
|
@property
|
|
def dbitpipeline(self):
|
|
"""[Ctb] Pipeline of the clock for latching digital bits. """
|
|
return element_if_equal(self.getDBITPipeline())
|
|
|
|
@dbitpipeline.setter
|
|
def dbitpipeline(self, value):
|
|
self.setDBITPipeline(value)
|
|
|
|
@property
|
|
def maxdbitphaseshift(self):
|
|
"""[CTB][Jungfrau] Absolute maximum Phase shift of of the clock to latch digital bits.
|
|
Note
|
|
-----
|
|
:setter: Not Implemented
|
|
"""
|
|
return element_if_equal(self.getMaxDBITPhaseShift())
|
|
|
|
@property
|
|
def rx_dbitlist(self):
|
|
"""
|
|
[Ctb] List of digital signal bits read out.
|
|
|
|
Notes
|
|
-----
|
|
Each element in list can be 0 - 63 and must be non repetitive.
|
|
|
|
Examples
|
|
---------
|
|
>>> d.rxdbitlist = [0, 1, 61, 9]
|
|
>>> d.rxdbitlist
|
|
[0, 1, 61, 9]
|
|
>>> d.rxdbitlist = []
|
|
>>> d.rxdbitlist
|
|
[]
|
|
"""
|
|
return element_if_equal(self.getRxDbitList())
|
|
|
|
@rx_dbitlist.setter
|
|
def rx_dbitlist(self, value):
|
|
self.setRxDbitList(value)
|
|
|
|
@property
|
|
def rx_dbitoffset(self):
|
|
"""[Ctb] Offset in bytes in digital data to skip in receiver."""
|
|
return element_if_equal(self.getRxDbitOffset())
|
|
|
|
@rx_dbitoffset.setter
|
|
def rx_dbitoffset(self, value):
|
|
self.setRxDbitOffset(value)
|
|
|
|
@property
|
|
def maxadcphaseshift(self):
|
|
"""[Jungfrau][CTB][Moench] Absolute maximum Phase shift of ADC clock.
|
|
Note
|
|
-----
|
|
:setter: Not Implemented
|
|
"""
|
|
return element_if_equal(self.getMaxADCPhaseShift())
|
|
|
|
@property
|
|
def adcphase(self):
|
|
"""[Gotthard][Jungfrau][CTB][Moench] Sets phase shift of ADC clock.
|
|
|
|
Note
|
|
-----
|
|
[Jungfrau] Absolute phase shift. Changing Speed also resets adcphase to recommended defaults.\n
|
|
[Ctb][Moench] Absolute phase shift. Changing adcclk also resets adcphase and sets it to previous values.\n
|
|
[Gotthard] Relative phase shift.
|
|
|
|
:getter: Not implemented for Gotthard
|
|
"""
|
|
return element_if_equal(self.getADCPhase())
|
|
|
|
@adcphase.setter
|
|
def adcphase(self, value):
|
|
self.setADCPhase(value)
|
|
|
|
@property
|
|
def adcpipeline(self):
|
|
"""[Ctb][Moench] Sets pipeline for ADC clock. """
|
|
return element_if_equal(self.getADCPipeline())
|
|
|
|
@adcpipeline.setter
|
|
def adcpipeline(self, value):
|
|
self.setADCPipeline(value)
|
|
|
|
@property
|
|
def adcclk(self):
|
|
"""[Ctb][Moench] Sets ADC clock frequency in MHz. """
|
|
return element_if_equal(self.getADCClock())
|
|
|
|
@adcclk.setter
|
|
def adcclk(self, value):
|
|
self.setADCClock(value)
|
|
|
|
@property
|
|
def syncclk(self):
|
|
return element_if_equal(self.getSYNCClock())
|
|
|
|
@property
|
|
def pattern(self):
|
|
"""[Mythen3][Moench][Ctb] Loads ASCII pattern file directly to server (instead of executing line by line).
|
|
|
|
Examples
|
|
---------
|
|
>>> d.pattern = '/tmp/pat.txt'
|
|
"""
|
|
# TODO! Clean fix
|
|
print("Set only")
|
|
return 0
|
|
|
|
@pattern.setter
|
|
def pattern(self, fname):
|
|
fname = ut.make_string_path(fname)
|
|
self.setPattern(fname)
|
|
|
|
# patioctrl
|
|
@property
|
|
def patioctrl(self):
|
|
"""[Ctb][Moench] 64 bit mask defining input (0) and output (1) signals.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patioctrl = 0x8f0effff6dbffdbf
|
|
>>> hex(d.patioctrl)
|
|
'0x8f0effff6dbffdbf'
|
|
"""
|
|
return element_if_equal(self.getPatternIOControl())
|
|
|
|
@patioctrl.setter
|
|
def patioctrl(self, mask):
|
|
self.setPatternIOControl(mask)
|
|
|
|
@property
|
|
def patlimits(self):
|
|
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of complete pattern.
|
|
|
|
Examples
|
|
---------
|
|
>>> d.patlimits = [0x0, 0x18c]
|
|
>>> d.patlimits
|
|
[0, 396]
|
|
>>> [hex(l) for l in d.patlimits]
|
|
['0x0', '0x18c']
|
|
"""
|
|
return element_if_equal(self.getPatternLoopAddresses(-1))
|
|
|
|
@patlimits.setter
|
|
def patlimits(self, lim):
|
|
self.setPatternLoopAddresses(-1, lim[0], lim[1])
|
|
|
|
@property
|
|
@element
|
|
def patsetbit(self):
|
|
"""[Ctb][Moench][Mythen3] Selects the bits that will have a pattern mask applied to the selected patmask for every pattern.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patsetbit = 0x8f0effff6dbffdbf
|
|
>>> hex(d.patsetbit)
|
|
'0x8f0effff6dbffdbf'
|
|
"""
|
|
return self.getPatternBitMask()
|
|
|
|
@patsetbit.setter
|
|
def patsetbit(self, mask):
|
|
self.setPatternBitMask(mask)
|
|
|
|
@property
|
|
def patmask(self):
|
|
"""[Ctb][Moench][Mythen3] Sets the mask applied to every pattern to the selected bits.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patmask = 0x8f0effff6dbffdbf
|
|
>>> hex(d.patmask)
|
|
'0x8f0effff6dbffdbf'
|
|
"""
|
|
return element_if_equal(self.getPatternMask())
|
|
|
|
@patmask.setter
|
|
def patmask(self, mask):
|
|
self.setPatternMask(mask)
|
|
|
|
|
|
|
|
@property
|
|
def patwait0(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 0 address.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patwait0 = 0xaa
|
|
>>> d.patwait0
|
|
170
|
|
>>> hex(d.patwait0)
|
|
'0xaa'
|
|
"""
|
|
return element_if_equal(self.getPatternWaitAddr(0))
|
|
|
|
@patwait0.setter
|
|
def patwait0(self, addr):
|
|
self.setPatternWaitAddr(0, addr)
|
|
|
|
@property
|
|
def patwait1(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 1 address.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patwait1 = 0xaa
|
|
>>> d.patwait1
|
|
170
|
|
>>> hex(d.patwait1)
|
|
'0xaa'
|
|
"""
|
|
return element_if_equal(self.getPatternWaitAddr(1))
|
|
|
|
@patwait1.setter
|
|
def patwait1(self, addr):
|
|
self.setPatternWaitAddr(1, addr)
|
|
|
|
@property
|
|
def patwait2(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 2 address.
|
|
|
|
Examples
|
|
--------
|
|
>>> d.patwait2 = 0xaa
|
|
>>> d.patwait2
|
|
170
|
|
>>> hex(d.patwait2)
|
|
'0xaa'
|
|
"""
|
|
return element_if_equal(self.getPatternWaitAddr(2))
|
|
|
|
@patwait2.setter
|
|
def patwait2(self, addr):
|
|
self.setPatternWaitAddr(2, addr)
|
|
|
|
@property
|
|
def patwaittime0(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 0 time in clock cycles."""
|
|
return element_if_equal(self.getPatternWaitTime(0))
|
|
|
|
@patwaittime0.setter
|
|
def patwaittime0(self, nclk):
|
|
self.setPatternWaitTime(0, nclk)
|
|
|
|
@property
|
|
def patwaittime1(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 1 time in clock cycles."""
|
|
return element_if_equal(self.getPatternWaitTime(1))
|
|
|
|
@patwaittime1.setter
|
|
def patwaittime1(self, nclk):
|
|
self.setPatternWaitTime(1, nclk)
|
|
|
|
@property
|
|
def patwaittime2(self):
|
|
"""[Ctb][Moench][Mythen3] Wait 2 time in clock cycles."""
|
|
return element_if_equal(self.getPatternWaitTime(2))
|
|
|
|
@patwaittime2.setter
|
|
def patwaittime2(self, nclk):
|
|
self.setPatternWaitTime(2, nclk)
|
|
|
|
@property
|
|
def patloop0(self):
|
|
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 0.
|
|
|
|
Examples
|
|
---------
|
|
>>> d.patloop0 = [0x0, 0x18c]
|
|
>>> d.patloop0
|
|
[0, 396]
|
|
>>> [hex(l) for l in d.patloop0]
|
|
['0x0', '0x18c']
|
|
"""
|
|
return element_if_equal(self.getPatternLoopAddresses(0))
|
|
|
|
@patloop0.setter
|
|
def patloop0(self, addr):
|
|
self.setPatternLoopAddresses(0, addr[0], addr[1])
|
|
|
|
@property
|
|
def patloop1(self):
|
|
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 1.
|
|
|
|
Examples
|
|
---------
|
|
>>> d.patloop1 = [0x0, 0x18c]
|
|
>>> d.patloop1
|
|
[0, 396]
|
|
>>> [hex(l) for l in d.patloop1]
|
|
['0x0', '0x18c']
|
|
|
|
"""
|
|
return element_if_equal(self.getPatternLoopAddresses(1))
|
|
|
|
@patloop1.setter
|
|
def patloop1(self, addr):
|
|
self.setPatternLoopAddresses(1, addr[0], addr[1])
|
|
|
|
@property
|
|
def patloop2(self):
|
|
"""[Ctb][Moench][Mythen3] Limits (start and stop address) of loop 2.
|
|
|
|
Examples
|
|
---------
|
|
>>> d.patloop2 = [0x0, 0x18c]
|
|
>>> d.patloop2
|
|
[0, 396]
|
|
>>> [hex(l) for l in d.patloop2]
|
|
['0x0', '0x18c']
|
|
|
|
"""
|
|
return element_if_equal(self.getPatternLoopAddresses(2))
|
|
|
|
@patloop2.setter
|
|
def patloop2(self, addr):
|
|
self.setPatternLoopAddresses(2, addr[0], addr[1])
|
|
|
|
@property
|
|
def patnloop0(self):
|
|
"""[Ctb][Moench][Mythen3] Number of cycles of loop 0."""
|
|
return element_if_equal(self.getPatternLoopCycles(0))
|
|
|
|
@patnloop0.setter
|
|
def patnloop0(self, n):
|
|
self.setPatternLoopCycles(0, n)
|
|
|
|
@property
|
|
def patnloop1(self):
|
|
"""[Ctb][Moench][Mythen3] Number of cycles of loop 1."""
|
|
return element_if_equal(self.getPatternLoopCycles(1))
|
|
|
|
@patnloop1.setter
|
|
def patnloop1(self, n):
|
|
self.setPatternLoopCycles(1, n)
|
|
|
|
@property
|
|
def patnloop2(self):
|
|
"""[Ctb][Moench][Mythen3] Number of cycles of loop 2."""
|
|
return element_if_equal(self.getPatternLoopCycles(2))
|
|
|
|
@patnloop2.setter
|
|
def patnloop2(self, n):
|
|
self.setPatternLoopCycles(2, n)
|
|
|
|
@property
|
|
@element
|
|
def v_a(self):
|
|
return self.getDAC(dacIndex.V_POWER_A, True)
|
|
|
|
@v_a.setter
|
|
def v_a(self, value):
|
|
self.setDAC(dacIndex.V_POWER_A, value, True)
|
|
|
|
@property
|
|
@element
|
|
def v_b(self):
|
|
return self.getDAC(dacIndex.V_POWER_B, True)
|
|
|
|
@v_b.setter
|
|
def v_b(self, value):
|
|
self.setDAC(dacIndex.V_POWER_B, value, True)
|
|
|
|
@property
|
|
@element
|
|
def v_c(self):
|
|
return self.getDAC(dacIndex.V_POWER_C, True)
|
|
|
|
@v_c.setter
|
|
def v_c(self, value):
|
|
self.setDAC(dacIndex.V_POWER_C, value, True)
|
|
|
|
@property
|
|
@element
|
|
def v_d(self):
|
|
return self.getDAC(dacIndex.V_POWER_D, True)
|
|
|
|
@v_d.setter
|
|
def v_d(self, value):
|
|
self.setDAC(dacIndex.V_POWER_D, value, True)
|
|
|
|
@property
|
|
@element
|
|
def v_io(self):
|
|
return self.getDAC(dacIndex.V_POWER_IO, True)
|
|
|
|
@v_io.setter
|
|
def v_io(self, value):
|
|
self.setDAC(dacIndex.V_POWER_IO, value, True)
|
|
|
|
@property
|
|
@element
|
|
def v_limit(self):
|
|
return self.getDAC(dacIndex.V_LIMIT, True)
|
|
|
|
@v_limit.setter
|
|
def v_limit(self, value):
|
|
self.setDAC(dacIndex.V_LIMIT, value, True)
|
|
|
|
@property
|
|
@element
|
|
def im_a(self):
|
|
"""[Ctb] Measured current of power supply a in mA.
|
|
|
|
Notes
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
return self.getMeasuredCurrent(dacIndex.I_POWER_A)
|
|
|
|
@property
|
|
@element
|
|
def im_b(self):
|
|
"""[Ctb] Measured current of power supply b in mA.
|
|
|
|
Notes
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
return self.getMeasuredCurrent(dacIndex.I_POWER_B)
|
|
|
|
@property
|
|
@element
|
|
def im_c(self):
|
|
"""[Ctb] Measured current of power supply c in mA.
|
|
|
|
Notes
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
return self.getMeasuredCurrent(dacIndex.I_POWER_C)
|
|
|
|
@property
|
|
@element
|
|
def im_d(self):
|
|
"""[Ctb] Measured current of power supply d in mA.
|
|
|
|
Notes
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
return self.getMeasuredCurrent(dacIndex.I_POWER_D)
|
|
|
|
@property
|
|
@element
|
|
def im_io(self):
|
|
"""[Ctb] Measured current of power supply io in mA.
|
|
|
|
Notes
|
|
-----
|
|
:setter: Not implemented
|
|
"""
|
|
return self.getMeasuredCurrent(dacIndex.I_POWER_IO)
|