mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-07 18:40:42 +02:00
Eiger
This commit is contained in:
parent
639ed52d65
commit
c223f00511
@ -1,7 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.11)
|
cmake_minimum_required(VERSION 3.11)
|
||||||
project(slsDetectorPackage)
|
project(slsDetectorPackage)
|
||||||
set(PROJECT_VERSION 5.0.0)
|
set(PROJECT_VERSION 5.0.0)
|
||||||
|
|
||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ set( PYTHON_FILES
|
|||||||
decorators.py
|
decorators.py
|
||||||
detector_property.py
|
detector_property.py
|
||||||
# detector.py
|
# detector.py
|
||||||
# eiger.py
|
eiger.py
|
||||||
errors.py
|
errors.py
|
||||||
experimental.py
|
experimental.py
|
||||||
# jungfrau_ctb.py
|
# jungfrau_ctb.py
|
||||||
|
@ -3,8 +3,13 @@ import sys
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
sys.path.append(os.path.join(os.getcwd(), 'bin'))
|
sys.path.append(os.path.join(os.getcwd(), 'bin'))
|
||||||
# from sls_detector import Eiger, Jungfrau, Detector, defs
|
# from sls_detector import Eiger, Jungfrau, Detector, defs
|
||||||
from sls_detector import Detector
|
|
||||||
|
from sls_detector import Detector, Eiger, DetectorDacs, Dac
|
||||||
from sls_detector import dacIndex
|
from sls_detector import dacIndex
|
||||||
|
|
||||||
|
|
||||||
d = Detector()
|
d = Detector()
|
||||||
|
e = Eiger()
|
||||||
|
|
||||||
|
# from sls_detector.eiger import EigerVcmp
|
||||||
|
# v = EigerVcmp(d)
|
@ -1,5 +1,6 @@
|
|||||||
# from .detector import Detector, DetectorError, free_shared_memory
|
# from .detector import Detector, DetectorError, free_shared_memory
|
||||||
# from .eiger import Eiger
|
from .eiger import Eiger
|
||||||
|
from .dacs import DetectorDacs, Dac
|
||||||
from .experimental import Detector
|
from .experimental import Detector
|
||||||
|
|
||||||
# from .jungfrau import Jungfrau
|
# from .jungfrau import Jungfrau
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
from .detector_property import DetectorProperty
|
from .detector_property import DetectorProperty
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import _sls_detector
|
||||||
|
dacIndex = _sls_detector.slsDetectorDefs.dacIndex
|
||||||
class Dac(DetectorProperty):
|
class Dac(DetectorProperty):
|
||||||
"""
|
"""
|
||||||
This class represents a dac on the detector. One instance handles all
|
This class represents a dac on the detector. One instance handles all
|
||||||
@ -14,11 +15,11 @@ class Dac(DetectorProperty):
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, low, high, default, detector):
|
def __init__(self, name, enum, low, high, default, detector):
|
||||||
|
|
||||||
super().__init__(partial(detector._api.getDac, name),
|
super().__init__(partial(detector.getDAC, enum, False),
|
||||||
partial(detector._api.setDac, name),
|
lambda x, y : detector.setDAC(enum, x, False, y),
|
||||||
detector._api.getNumberOfDetectors,
|
detector.size,
|
||||||
name)
|
name)
|
||||||
|
|
||||||
self.min_value = low
|
self.min_value = low
|
||||||
@ -29,29 +30,28 @@ class Dac(DetectorProperty):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""String representation for a single dac in all modules"""
|
"""String representation for a single dac in all modules"""
|
||||||
r_str = ['{:10s}: '.format(self.__name__)]
|
dacstr = ''.join([f'{item:5d}' for item in self.get()])
|
||||||
r_str += ['{:5d}, '.format(self.get(i)) for i in range(self.get_nmod())]
|
return f'{self.__name__:10s}:{dacstr}'
|
||||||
return ''.join(r_str).strip(', ')
|
|
||||||
|
|
||||||
|
|
||||||
|
# a = Dac('vrf', dacIndex.VRF, 0, 4000, 2500, d )
|
||||||
class DetectorDacs:
|
class DetectorDacs:
|
||||||
_dacs = [('vsvp', 0, 4000, 0),
|
_dacs = [('vsvp', dacIndex.SVP,0, 4000, 0),
|
||||||
('vtr', 0, 4000, 2500),
|
('vtr', dacIndex.VTR,0, 4000, 2500),
|
||||||
('vrf', 0, 4000, 3300),
|
('vrf', dacIndex.VRF,0, 4000, 3300),
|
||||||
('vrs', 0, 4000, 1400),
|
('vrs', dacIndex.VRS,0, 4000, 1400),
|
||||||
('vsvn', 0, 4000, 4000),
|
('vsvn', dacIndex.SVN,0, 4000, 4000),
|
||||||
('vtgstv', 0, 4000, 2556),
|
('vtgstv', dacIndex.VTGSTV,0, 4000, 2556),
|
||||||
('vcmp_ll', 0, 4000, 1500),
|
('vcmp_ll', dacIndex.VCMP_LL,0, 4000, 1500),
|
||||||
('vcmp_lr', 0, 4000, 1500),
|
('vcmp_lr', dacIndex.VCMP_LR,0, 4000, 1500),
|
||||||
('vcall', 0, 4000, 4000),
|
('vcall', dacIndex.CAL,0, 4000, 4000),
|
||||||
('vcmp_rl', 0, 4000, 1500),
|
('vcmp_rl', dacIndex.VCMP_RL,0, 4000, 1500),
|
||||||
('rxb_rb', 0, 4000, 1100),
|
('rxb_rb', dacIndex.RXB_RB,0, 4000, 1100),
|
||||||
('rxb_lb', 0, 4000, 1100),
|
('rxb_lb', dacIndex.RXB_LB,0, 4000, 1100),
|
||||||
('vcmp_rr', 0, 4000, 1500),
|
('vcmp_rr', dacIndex.VCMP_RR,0, 4000, 1500),
|
||||||
('vcp', 0, 4000, 200),
|
('vcp', dacIndex.VCP,0, 4000, 200),
|
||||||
('vcn', 0, 4000, 2000),
|
('vcn', dacIndex.VCN,0, 4000, 2000),
|
||||||
('vis', 0, 4000, 1550),
|
('vis', dacIndex.VIS,0, 4000, 1550),
|
||||||
('iodelay', 0, 4000, 660)]
|
('iodelay', dacIndex.IO_DELAY,0, 4000, 660)]
|
||||||
_dacnames = [_d[0] for _d in _dacs]
|
_dacnames = [_d[0] for _d in _dacs]
|
||||||
|
|
||||||
def __init__(self, detector):
|
def __init__(self, detector):
|
||||||
@ -95,7 +95,7 @@ class DetectorDacs:
|
|||||||
"""
|
"""
|
||||||
Read the dacs into a numpy array with dimensions [ndacs, nmodules]
|
Read the dacs into a numpy array with dimensions [ndacs, nmodules]
|
||||||
"""
|
"""
|
||||||
dac_array = np.zeros((len(self._dacs), self._detector.n_modules))
|
dac_array = np.zeros((len(self._dacs), len(self._detector)))
|
||||||
for i, _d in enumerate(self):
|
for i, _d in enumerate(self):
|
||||||
dac_array[i,:] = _d[:]
|
dac_array[i,:] = _d[:]
|
||||||
return dac_array
|
return dac_array
|
||||||
@ -115,11 +115,3 @@ class DetectorDacs:
|
|||||||
for _d in self:
|
for _d in self:
|
||||||
_d[:] = _d.default
|
_d[:] = _d.default
|
||||||
|
|
||||||
def update_nmod(self):
|
|
||||||
"""
|
|
||||||
Update the cached value of nmod, needs to be run after adding or
|
|
||||||
removing detectors
|
|
||||||
"""
|
|
||||||
for _d in self:
|
|
||||||
_d._n_modules = self._detector.n_modules
|
|
||||||
|
|
||||||
|
@ -14,21 +14,20 @@ class DetectorProperty:
|
|||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key == slice(None, None, None):
|
if key == slice(None, None, None):
|
||||||
return [self.get(i) for i in range(self.get_nmod())]
|
return self.get()
|
||||||
elif isinstance(key, Iterable):
|
elif isinstance(key, Iterable):
|
||||||
return [self.get(k) for k in key]
|
return self.get(list(key))
|
||||||
else:
|
else:
|
||||||
return self.get(key)
|
return self.get([key])[0] #No list for single value
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
#operate on all values
|
#operate on all values
|
||||||
if key == slice(None, None, None):
|
if key == slice(None, None, None):
|
||||||
if isinstance(value, (np.integer, int)):
|
if isinstance(value, (np.integer, int)):
|
||||||
for i in range(self.get_nmod()):
|
self.set(value, [])
|
||||||
self.set(i, value)
|
|
||||||
elif isinstance(value, Iterable):
|
elif isinstance(value, Iterable):
|
||||||
for i in range(self.get_nmod()):
|
for i in range(self.get_nmod()):
|
||||||
self.set(i, value[i])
|
self.set(value[i], [i])
|
||||||
else:
|
else:
|
||||||
raise ValueError('Value should be int or np.integer not', type(value))
|
raise ValueError('Value should be int or np.integer not', type(value))
|
||||||
|
|
||||||
@ -36,15 +35,14 @@ class DetectorProperty:
|
|||||||
elif isinstance(key, Iterable):
|
elif isinstance(key, Iterable):
|
||||||
if isinstance(value, Iterable):
|
if isinstance(value, Iterable):
|
||||||
for k,v in zip(key, value):
|
for k,v in zip(key, value):
|
||||||
self.set(k,v)
|
self.set(v, [k])
|
||||||
|
|
||||||
elif isinstance(value, int):
|
elif isinstance(value, int):
|
||||||
for k in key:
|
self.set(value, list(key))
|
||||||
self.set(k, value)
|
|
||||||
|
|
||||||
#Set single value
|
#Set single value
|
||||||
elif isinstance(key, int):
|
elif isinstance(key, int):
|
||||||
self.set(key, value)
|
self.set(value, [key])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
s = ', '.join(str(v) for v in self[:])
|
s = ', '.join(str(v) for v in self[:])
|
||||||
|
@ -6,17 +6,20 @@ Created on Wed Dec 6 11:51:18 2017
|
|||||||
@author: l_frojdh
|
@author: l_frojdh
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import socket
|
|
||||||
from collections.abc import Iterable
|
|
||||||
from collections import namedtuple
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from .adcs import Adc, DetectorAdcs
|
from .experimental import Detector
|
||||||
|
# import socket
|
||||||
|
# from collections.abc import Iterable
|
||||||
|
# from collections import namedtuple
|
||||||
|
# from functools import partial
|
||||||
|
|
||||||
|
# from .adcs import Adc, DetectorAdcs
|
||||||
from .dacs import DetectorDacs
|
from .dacs import DetectorDacs
|
||||||
from .detector import Detector
|
import _sls_detector
|
||||||
|
dacIndex = _sls_detector.slsDetectorDefs.dacIndex
|
||||||
from .detector_property import DetectorProperty
|
from .detector_property import DetectorProperty
|
||||||
from .utils import element_if_equal
|
# from .utils import element_if_equal
|
||||||
from sls_detector.errors import DetectorValueError, DetectorError
|
# from sls_detector.errors import DetectorValueError, DetectorError
|
||||||
|
|
||||||
class EigerVcmp:
|
class EigerVcmp:
|
||||||
"""
|
"""
|
||||||
@ -30,20 +33,21 @@ class EigerVcmp:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, detector):
|
def __init__(self, detector):
|
||||||
_names = ['vcmp_ll',
|
_dacs = [ dacIndex.VCMP_LL,
|
||||||
'vcmp_lr',
|
dacIndex.VCMP_LR,
|
||||||
'vcmp_rl',
|
dacIndex.VCMP_RL,
|
||||||
'vcmp_rr']
|
dacIndex.VCMP_RR]
|
||||||
self.set = []
|
self.set = []
|
||||||
self.get = []
|
self.get = []
|
||||||
for i in range(detector.n_modules):
|
for i in range(detector.size()):
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
name = _names
|
dacs = _dacs
|
||||||
else:
|
else:
|
||||||
name = _names[::-1]
|
dacs = _dacs[::-1]
|
||||||
for n in name:
|
for d in dacs:
|
||||||
self.set.append(partial(detector._api.setDac, n, i))
|
print(d, i)
|
||||||
self.get.append(partial(detector._api.getDac, n, i))
|
self.set.append(lambda x, d=d, i=i : detector.setDAC(d, x, False, [i]))
|
||||||
|
self.get.append(lambda d=d, i=i : detector.getDAC(d, False, [i])[0])
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key == slice(None, None, None):
|
if key == slice(None, None, None):
|
||||||
@ -58,80 +62,84 @@ class EigerVcmp:
|
|||||||
|
|
||||||
|
|
||||||
class EigerDacs(DetectorDacs):
|
class EigerDacs(DetectorDacs):
|
||||||
_dacs = [('vsvp', 0, 4000, 0),
|
"""
|
||||||
('vtr', 0, 4000, 2500),
|
Eiger specific dacs
|
||||||
('vrf', 0, 4000, 3300),
|
"""
|
||||||
('vrs', 0, 4000, 1400),
|
_dacs = [('vsvp', dacIndex.SVP,0, 4000, 0),
|
||||||
('vsvn', 0, 4000, 4000),
|
('vtr', dacIndex.VTR,0, 4000, 2500),
|
||||||
('vtgstv', 0, 4000, 2556),
|
('vrf', dacIndex.VRF,0, 4000, 3300),
|
||||||
('vcmp_ll', 0, 4000, 1500),
|
('vrs', dacIndex.VRS,0, 4000, 1400),
|
||||||
('vcmp_lr', 0, 4000, 1500),
|
('vsvn', dacIndex.SVN,0, 4000, 4000),
|
||||||
('vcall', 0, 4000, 4000),
|
('vtgstv', dacIndex.VTGSTV,0, 4000, 2556),
|
||||||
('vcmp_rl', 0, 4000, 1500),
|
('vcmp_ll', dacIndex.VCMP_LL,0, 4000, 1500),
|
||||||
('rxb_rb', 0, 4000, 1100),
|
('vcmp_lr', dacIndex.VCMP_LR,0, 4000, 1500),
|
||||||
('rxb_lb', 0, 4000, 1100),
|
('vcall', dacIndex.CAL,0, 4000, 4000),
|
||||||
('vcmp_rr', 0, 4000, 1500),
|
('vcmp_rl', dacIndex.VCMP_RL,0, 4000, 1500),
|
||||||
('vcp', 0, 4000, 200),
|
('rxb_rb', dacIndex.RXB_RB,0, 4000, 1100),
|
||||||
('vcn', 0, 4000, 2000),
|
('rxb_lb', dacIndex.RXB_LB,0, 4000, 1100),
|
||||||
('vis', 0, 4000, 1550),
|
('vcmp_rr', dacIndex.VCMP_RR,0, 4000, 1500),
|
||||||
('iodelay', 0, 4000, 660)]
|
('vcp', dacIndex.VCP,0, 4000, 200),
|
||||||
|
('vcn', dacIndex.VCN,0, 4000, 2000),
|
||||||
|
('vis', dacIndex.VIS,0, 4000, 1550),
|
||||||
|
('iodelay', dacIndex.IO_DELAY,0, 4000, 660)]
|
||||||
_dacnames = [_d[0] for _d in _dacs]
|
_dacnames = [_d[0] for _d in _dacs]
|
||||||
|
|
||||||
|
# # noinspection PyProtectedMember
|
||||||
|
# class DetectorDelays:
|
||||||
|
# _delaynames = ['frame', 'left', 'right']
|
||||||
|
|
||||||
# noinspection PyProtectedMember
|
# def __init__(self, detector):
|
||||||
class DetectorDelays:
|
# # We need to at least initially know which detector we are connected to
|
||||||
_delaynames = ['frame', 'left', 'right']
|
# self._detector = detector
|
||||||
|
|
||||||
def __init__(self, detector):
|
# setattr(self, '_frame', DetectorProperty(detector._api.getDelayFrame,
|
||||||
# We need to at least initially know which detector we are connected to
|
# detector._api.setDelayFrame,
|
||||||
self._detector = detector
|
# detector._api.getNumberOfDetectors,
|
||||||
|
# 'frame'))
|
||||||
|
|
||||||
setattr(self, '_frame', DetectorProperty(detector._api.getDelayFrame,
|
# setattr(self, '_left', DetectorProperty(detector._api.getDelayLeft,
|
||||||
detector._api.setDelayFrame,
|
# detector._api.setDelayLeft,
|
||||||
detector._api.getNumberOfDetectors,
|
# detector._api.getNumberOfDetectors,
|
||||||
'frame'))
|
# 'left'))
|
||||||
|
|
||||||
setattr(self, '_left', DetectorProperty(detector._api.getDelayLeft,
|
# setattr(self, '_right', DetectorProperty(detector._api.getDelayRight,
|
||||||
detector._api.setDelayLeft,
|
# detector._api.setDelayRight,
|
||||||
detector._api.getNumberOfDetectors,
|
# detector._api.getNumberOfDetectors,
|
||||||
'left'))
|
# 'right'))
|
||||||
|
# # Index to support iteration
|
||||||
|
# self._current = 0
|
||||||
|
|
||||||
setattr(self, '_right', DetectorProperty(detector._api.getDelayRight,
|
# def __getattr__(self, name):
|
||||||
detector._api.setDelayRight,
|
# return self.__getattribute__('_' + name)
|
||||||
detector._api.getNumberOfDetectors,
|
|
||||||
'right'))
|
|
||||||
# Index to support iteration
|
|
||||||
self._current = 0
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
# def __setattr__(self, name, value):
|
||||||
return self.__getattribute__('_' + name)
|
# if name in self._delaynames:
|
||||||
|
# return self.__getattribute__('_' + name).__setitem__(slice(None, None, None), value)
|
||||||
|
# else:
|
||||||
|
# super().__setattr__(name, value)
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
# def __next__(self):
|
||||||
if name in self._delaynames:
|
# if self._current >= len(self._delaynames):
|
||||||
return self.__getattribute__('_' + name).__setitem__(slice(None, None, None), value)
|
# self._current = 0
|
||||||
else:
|
# raise StopIteration
|
||||||
super().__setattr__(name, value)
|
# else:
|
||||||
|
# self._current += 1
|
||||||
|
# return self.__getattr__(self._delaynames[self._current-1])
|
||||||
|
|
||||||
def __next__(self):
|
# def __iter__(self):
|
||||||
if self._current >= len(self._delaynames):
|
# return self
|
||||||
self._current = 0
|
|
||||||
raise StopIteration
|
|
||||||
else:
|
|
||||||
self._current += 1
|
|
||||||
return self.__getattr__(self._delaynames[self._current-1])
|
|
||||||
|
|
||||||
def __iter__(self):
|
# def __repr__(self):
|
||||||
return self
|
# hn = self._detector.hostname
|
||||||
|
# r_str = ['Transmission delay [ns]\n'
|
||||||
def __repr__(self):
|
# '{:11s}{:>8s}{:>8s}{:>8s}'.format('', 'left', 'right', 'frame')]
|
||||||
hn = self._detector.hostname
|
# for i in range(self._detector.n_modules):
|
||||||
r_str = ['Transmission delay [ns]\n'
|
# r_str.append('{:2d}:{:8s}{:>8d}{:>8d}{:>8d}'.format(i, hn[i], self.left[i], self.right[i], self.frame[i]))
|
||||||
'{:11s}{:>8s}{:>8s}{:>8s}'.format('', 'left', 'right', 'frame')]
|
# return '\n'.join(r_str)
|
||||||
for i in range(self._detector.n_modules):
|
|
||||||
r_str.append('{:2d}:{:8s}{:>8d}{:>8d}{:>8d}'.format(i, hn[i], self.left[i], self.right[i], self.frame[i]))
|
|
||||||
return '\n'.join(r_str)
|
|
||||||
|
|
||||||
|
from .experimental import freeze
|
||||||
|
|
||||||
|
@freeze
|
||||||
class Eiger(Detector):
|
class Eiger(Detector):
|
||||||
"""
|
"""
|
||||||
Subclassing Detector to set up correct dacs and detector specific
|
Subclassing Detector to set up correct dacs and detector specific
|
||||||
@ -145,79 +153,80 @@ class Eiger(Detector):
|
|||||||
|
|
||||||
def __init__(self, id=0):
|
def __init__(self, id=0):
|
||||||
super().__init__(id)
|
super().__init__(id)
|
||||||
|
self._frozen = False
|
||||||
self._active = DetectorProperty(self._api.getActive,
|
|
||||||
self._api.setActive,
|
|
||||||
self._api.getNumberOfDetectors,
|
|
||||||
'active')
|
|
||||||
|
|
||||||
self._vcmp = EigerVcmp(self)
|
|
||||||
self._dacs = EigerDacs(self)
|
self._dacs = EigerDacs(self)
|
||||||
self._trimbit_limits = namedtuple('trimbit_limits', ['min', 'max'])(0, 63)
|
self._vcmp = EigerVcmp(self)
|
||||||
self._delay = DetectorDelays(self)
|
|
||||||
|
|
||||||
# Eiger specific adcs
|
# self._active = DetectorProperty(self.getActive,
|
||||||
self._temp = DetectorAdcs()
|
# self.setActive,
|
||||||
self._temp.fpga = Adc('temp_fpga', self)
|
# self.size,
|
||||||
self._temp.fpgaext = Adc('temp_fpgaext', self)
|
# 'active')
|
||||||
self._temp.t10ge = Adc('temp_10ge', self)
|
|
||||||
self._temp.dcdc = Adc('temp_dcdc', self)
|
|
||||||
self._temp.sodl = Adc('temp_sodl', self)
|
|
||||||
self._temp.sodr = Adc('temp_sodr', self)
|
|
||||||
self._temp.fpgafl = Adc('temp_fpgafl', self)
|
|
||||||
self._temp.fpgafr = Adc('temp_fpgafr', self)
|
|
||||||
|
|
||||||
@property
|
# self._trimbit_limits = namedtuple('trimbit_limits', ['min', 'max'])(0, 63)
|
||||||
def active(self):
|
# self._delay = DetectorDelays(self)
|
||||||
"""
|
|
||||||
Is the detector active? Can be used to enable or disable a detector
|
|
||||||
module
|
|
||||||
|
|
||||||
Examples
|
# # Eiger specific adcs
|
||||||
----------
|
# self._temp = DetectorAdcs()
|
||||||
|
# self._temp.fpga = Adc('temp_fpga', self)
|
||||||
|
# self._temp.fpgaext = Adc('temp_fpgaext', self)
|
||||||
|
# self._temp.t10ge = Adc('temp_10ge', self)
|
||||||
|
# self._temp.dcdc = Adc('temp_dcdc', self)
|
||||||
|
# self._temp.sodl = Adc('temp_sodl', self)
|
||||||
|
# self._temp.sodr = Adc('temp_sodr', self)
|
||||||
|
# self._temp.fpgafl = Adc('temp_fpgafl', self)
|
||||||
|
# self._temp.fpgafr = Adc('temp_fpgafr', self)
|
||||||
|
|
||||||
::
|
# @property
|
||||||
|
# def active(self):
|
||||||
|
# """
|
||||||
|
# Is the detector active? Can be used to enable or disable a detector
|
||||||
|
# module
|
||||||
|
|
||||||
d.active
|
# Examples
|
||||||
>> active: [True, True]
|
# ----------
|
||||||
|
|
||||||
d.active[1] = False
|
# ::
|
||||||
>> active: [True, False]
|
|
||||||
"""
|
|
||||||
return self._active
|
|
||||||
|
|
||||||
@active.setter
|
# d.active
|
||||||
def active(self, value):
|
# >> active: [True, True]
|
||||||
self._active[:] = value
|
|
||||||
|
|
||||||
@property
|
# d.active[1] = False
|
||||||
def measured_period(self):
|
# >> active: [True, False]
|
||||||
return self._api.getMeasuredPeriod()
|
# """
|
||||||
|
# return self._active
|
||||||
|
|
||||||
@property
|
# @active.setter
|
||||||
def measured_subperiod(self):
|
# def active(self, value):
|
||||||
return self._api.getMeasuredSubPeriod()
|
# self._active[:] = value
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def add_gappixels(self):
|
# def measured_period(self):
|
||||||
"""Enable or disable the (virual) pixels between ASICs
|
# return self._api.getMeasuredPeriod()
|
||||||
|
|
||||||
Examples
|
# @property
|
||||||
----------
|
# def measured_subperiod(self):
|
||||||
|
# return self._api.getMeasuredSubPeriod()
|
||||||
|
|
||||||
::
|
# @property
|
||||||
|
# def add_gappixels(self):
|
||||||
|
# """Enable or disable the (virual) pixels between ASICs
|
||||||
|
|
||||||
d.add_gappixels = True
|
# Examples
|
||||||
|
# ----------
|
||||||
|
|
||||||
d.add_gappixels
|
# ::
|
||||||
>> True
|
|
||||||
|
|
||||||
"""
|
# d.add_gappixels = True
|
||||||
return self._api.getGapPixels()
|
|
||||||
|
|
||||||
@add_gappixels.setter
|
# d.add_gappixels
|
||||||
def add_gappixels(self, value):
|
# >> True
|
||||||
self._api.setGapPixels(value)
|
|
||||||
|
# """
|
||||||
|
# return self._api.getGapPixels()
|
||||||
|
|
||||||
|
# @add_gappixels.setter
|
||||||
|
# def add_gappixels(self, value):
|
||||||
|
# self._api.setGapPixels(value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dacs(self):
|
def dacs(self):
|
||||||
@ -280,114 +289,68 @@ class Eiger(Detector):
|
|||||||
"""
|
"""
|
||||||
return self._dacs
|
return self._dacs
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def tx_delay(self):
|
# def tx_delay(self):
|
||||||
"""
|
# """
|
||||||
Transmission delay of the modules to allow running the detector
|
# Transmission delay of the modules to allow running the detector
|
||||||
in a network not supporting the full speed of the detector.
|
# in a network not supporting the full speed of the detector.
|
||||||
|
|
||||||
|
|
||||||
::
|
# ::
|
||||||
|
|
||||||
d.tx_delay
|
# d.tx_delay
|
||||||
>>
|
# >>
|
||||||
Transmission delay [ns]
|
# Transmission delay [ns]
|
||||||
left right frame
|
# left right frame
|
||||||
0:beb048 0 15000 0
|
# 0:beb048 0 15000 0
|
||||||
1:beb049 100 190000 100
|
# 1:beb049 100 190000 100
|
||||||
|
|
||||||
d.tx_delay.left = [2000,5000]
|
# d.tx_delay.left = [2000,5000]
|
||||||
"""
|
# """
|
||||||
return self._delay
|
# return self._delay
|
||||||
|
|
||||||
def default_settings(self):
|
# def pulse_all_pixels(self, n):
|
||||||
"""
|
# """
|
||||||
reset the detector to some type of standard settings
|
# Pulse each pixel of the chip **n** times using the analog test pulses.
|
||||||
mostly used when testing
|
# The pulse height is set using d.dacs.vcall with 4000 being 0 and 0 being
|
||||||
"""
|
# the highest pulse.
|
||||||
self.n_frames = 1
|
|
||||||
self.exposure_time = 1
|
|
||||||
self.period = 0
|
|
||||||
self.n_cycles = 1
|
|
||||||
self.n_measurements = 1
|
|
||||||
self.dynamic_range = 16
|
|
||||||
|
|
||||||
@property
|
# ::
|
||||||
def eiger_matrix_reset(self):
|
|
||||||
"""
|
|
||||||
Matrix reset bit for Eiger.
|
|
||||||
|
|
||||||
:py:obj:`True` : Normal operation, the matrix is reset before each acq.
|
# #Pulse all pixels ten times
|
||||||
:py:obj:`False` : Matrix reset disabled. Used to not reset before
|
# d.pulse_all_pixels(10)
|
||||||
reading out analog test pulses.
|
|
||||||
"""
|
|
||||||
return self._api.getCounterBit()
|
|
||||||
|
|
||||||
@eiger_matrix_reset.setter
|
# #Avoid resetting before acq
|
||||||
def eiger_matrix_reset(self, value):
|
# d.eiger_matrix_reset = False
|
||||||
self._api.setCounterBit(value)
|
|
||||||
|
|
||||||
@property
|
# d.acq() #take frame
|
||||||
def flowcontrol_10g(self):
|
|
||||||
"""
|
|
||||||
:py:obj:`True` - Flow control enabled :py:obj:`False` flow control disabled.
|
|
||||||
Sets for all moduels, if for some reason access to a single module is needed
|
|
||||||
this can be done trough the C++ API.
|
|
||||||
|
|
||||||
"""
|
# #Restore normal behaviour
|
||||||
fc = self._api.getNetworkParameter('flow_control_10g')
|
# d.eiger_matrix_reset = True
|
||||||
return element_if_equal([bool(int(e)) for e in fc])
|
|
||||||
|
|
||||||
@flowcontrol_10g.setter
|
|
||||||
def flowcontrol_10g(self, value):
|
|
||||||
if value is True:
|
|
||||||
v = '1'
|
|
||||||
else:
|
|
||||||
v = '0'
|
|
||||||
self._api.setNetworkParameter('flow_control_10g', v, -1)
|
|
||||||
|
|
||||||
def pulse_all_pixels(self, n):
|
|
||||||
"""
|
|
||||||
Pulse each pixel of the chip **n** times using the analog test pulses.
|
|
||||||
The pulse height is set using d.dacs.vcall with 4000 being 0 and 0 being
|
|
||||||
the highest pulse.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
#Pulse all pixels ten times
|
|
||||||
d.pulse_all_pixels(10)
|
|
||||||
|
|
||||||
#Avoid resetting before acq
|
|
||||||
d.eiger_matrix_reset = False
|
|
||||||
|
|
||||||
d.acq() #take frame
|
|
||||||
|
|
||||||
#Restore normal behaviour
|
|
||||||
d.eiger_matrix_reset = True
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
# """
|
||||||
self._api.pulseAllPixels(n)
|
# self._api.pulseAllPixels(n)
|
||||||
|
|
||||||
|
|
||||||
def pulse_diagonal(self, n):
|
# def pulse_diagonal(self, n):
|
||||||
"""
|
# """
|
||||||
Pulse pixels in super colums in a diagonal fashion. Used for calibration
|
# Pulse pixels in super colums in a diagonal fashion. Used for calibration
|
||||||
of vcall. Saves time compared to pulsing all pixels.
|
# of vcall. Saves time compared to pulsing all pixels.
|
||||||
"""
|
# """
|
||||||
self._api.pulseDiagonal(n)
|
# self._api.pulseDiagonal(n)
|
||||||
|
|
||||||
|
|
||||||
def pulse_chip(self, n):
|
# def pulse_chip(self, n):
|
||||||
"""
|
# """
|
||||||
Advance the counter by toggling enable. Gives 2*n+2 int the counter
|
# Advance the counter by toggling enable. Gives 2*n+2 int the counter
|
||||||
|
|
||||||
"""
|
# """
|
||||||
n = int(n)
|
# n = int(n)
|
||||||
if n >= -1:
|
# if n >= -1:
|
||||||
self._api.pulseChip(n)
|
# self._api.pulseChip(n)
|
||||||
else:
|
# else:
|
||||||
raise ValueError('n must be equal or larger than -1')
|
# raise ValueError('n must be equal or larger than -1')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def vcmp(self):
|
def vcmp(self):
|
||||||
@ -420,177 +383,99 @@ class Eiger(Detector):
|
|||||||
else:
|
else:
|
||||||
raise ValueError('vcmp only compatible with setting all')
|
raise ValueError('vcmp only compatible with setting all')
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def rx_udpport(self):
|
# def rx_udpport(self):
|
||||||
"""
|
# """
|
||||||
UDP port for the receiver. Each module has two ports referred to
|
# UDP port for the receiver. Each module has two ports referred to
|
||||||
as rx_udpport and rx_udpport2 in the command line interface
|
# as rx_udpport and rx_udpport2 in the command line interface
|
||||||
here they are grouped for each detector
|
# here they are grouped for each detector
|
||||||
|
|
||||||
::
|
# ::
|
||||||
|
|
||||||
[0:rx_udpport, 0:rx_udpport2, 1:rx_udpport ...]
|
# [0:rx_udpport, 0:rx_udpport2, 1:rx_udpport ...]
|
||||||
|
|
||||||
Examples
|
# Examples
|
||||||
-----------
|
# -----------
|
||||||
|
|
||||||
::
|
# ::
|
||||||
|
|
||||||
d.rx_udpport
|
# d.rx_udpport
|
||||||
>> [50010, 50011, 50004, 50005]
|
# >> [50010, 50011, 50004, 50005]
|
||||||
|
|
||||||
d.rx_udpport = [50010, 50011, 50012, 50013]
|
# d.rx_udpport = [50010, 50011, 50012, 50013]
|
||||||
|
|
||||||
"""
|
# """
|
||||||
p0 = self._api.getReceiverUDPPort()
|
# p0 = self._api.getReceiverUDPPort()
|
||||||
p1 = self._api.getReceiverUDPPort2()
|
# p1 = self._api.getReceiverUDPPort2()
|
||||||
return [int(val) for pair in zip(p0, p1) for val in pair]
|
# return [int(val) for pair in zip(p0, p1) for val in pair]
|
||||||
|
|
||||||
@rx_udpport.setter
|
# @rx_udpport.setter
|
||||||
def rx_udpport(self, ports):
|
# def rx_udpport(self, ports):
|
||||||
"""Requires iterating over elements two and two for setting ports"""
|
# """Requires iterating over elements two and two for setting ports"""
|
||||||
a = iter(ports)
|
# a = iter(ports)
|
||||||
for i, p in enumerate(zip(a, a)):
|
# for i, p in enumerate(zip(a, a)):
|
||||||
self._api.setReceiverUDPPort(p[0], i)
|
# self._api.setReceiverUDPPort(p[0], i)
|
||||||
self._api.setReceiverUDPPort2(p[1], i)
|
# self._api.setReceiverUDPPort2(p[1], i)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rx_zmqport(self):
|
def rx_zmqport(self):
|
||||||
"""
|
"""
|
||||||
Return the receiver zmq ports. Note that Eiger has two ports per receiver!
|
Return the receiver zmq ports. Note that Eiger has two ports per receiver!
|
||||||
|
This functions therefore differ from the base class.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
detector.rx_zmqport
|
e.rx_zmqport
|
||||||
>> [30001, 30002, 30003, 30004]
|
>> [30001, 30002, 30003, 30004]
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
_s = self._api.getReceiverStreamingPort()
|
ports = self.getRxZmqPort()
|
||||||
if _s == '':
|
return [p + i for p in ports for i in range(2)]
|
||||||
return []
|
|
||||||
else:
|
|
||||||
return [int(_p) + i for _p in _s for i in range(2)]
|
|
||||||
|
|
||||||
@rx_zmqport.setter
|
|
||||||
def rx_zmqport(self, port):
|
|
||||||
if isinstance(port, Iterable):
|
|
||||||
for i, p in enumerate(port):
|
|
||||||
self._api.setReceiverStreamingPort(p, i)
|
|
||||||
else:
|
|
||||||
self._api.setReceiverStreamingPort(port, -1)
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
# @rx_zmqport.setter
|
||||||
def sub_exposure_time(self):
|
# def rx_zmqport(self, port):
|
||||||
"""
|
# if isinstance(port, Iterable):
|
||||||
Sub frame exposure time in *seconds* for Eiger in 32bit autosumming mode
|
# for i, p in enumerate(port):
|
||||||
|
# self._api.setReceiverStreamingPort(p, i)
|
||||||
|
# else:
|
||||||
|
# self._api.setReceiverStreamingPort(port, -1)
|
||||||
|
|
||||||
::
|
# @property
|
||||||
|
# def temp(self):
|
||||||
|
# """
|
||||||
|
# An instance of DetectorAdcs used to read the temperature
|
||||||
|
# of different components
|
||||||
|
|
||||||
d.sub_exposure_time
|
# Examples
|
||||||
>> 0.0023
|
# -----------
|
||||||
|
|
||||||
d.sub_exposure_time = 0.002
|
# ::
|
||||||
|
|
||||||
"""
|
# detector.temp
|
||||||
return self._api.getSubExposureTime() / 1e9
|
# >>
|
||||||
|
# temp_fpga : 36.90°C, 45.60°C
|
||||||
|
# temp_fpgaext : 31.50°C, 32.50°C
|
||||||
|
# temp_10ge : 0.00°C, 0.00°C
|
||||||
|
# temp_dcdc : 36.00°C, 36.00°C
|
||||||
|
# temp_sodl : 33.00°C, 34.50°C
|
||||||
|
# temp_sodr : 33.50°C, 34.00°C
|
||||||
|
# temp_fpgafl : 33.81°C, 30.93°C
|
||||||
|
# temp_fpgafr : 27.88°C, 29.15°C
|
||||||
|
|
||||||
|
# a = detector.temp.fpga[:]
|
||||||
|
# a
|
||||||
|
# >> [36.568, 45.542]
|
||||||
|
|
||||||
|
|
||||||
@sub_exposure_time.setter
|
# """
|
||||||
def sub_exposure_time(self, t):
|
# return self._temp
|
||||||
#TODO! checking here or in the detector?
|
|
||||||
ns_time = int(t * 1e9)
|
|
||||||
if ns_time > 0:
|
|
||||||
self._api.setSubExposureTime(ns_time)
|
|
||||||
else:
|
|
||||||
raise DetectorValueError('Sub exposure time must be larger than 0')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def sub_deadtime(self):
|
|
||||||
"""
|
|
||||||
Deadtime between subexposures. Used to mimize noise by delaying the start of the next
|
|
||||||
subexposure.
|
|
||||||
"""
|
|
||||||
return self._api.getSubExposureDeadTime() / 1e9
|
|
||||||
|
|
||||||
|
|
||||||
@sub_deadtime.setter
|
|
||||||
def sub_deadtime(self, t):
|
|
||||||
ns_time = int(t * 1e9)
|
|
||||||
if ns_time >= 0:
|
|
||||||
self._api.setSubExposureDeadTime(ns_time)
|
|
||||||
else:
|
|
||||||
raise ValueError('Sub deadtime time must be larger or equal to 0')
|
|
||||||
|
|
||||||
@property
|
# def set_delays(self, delta):
|
||||||
def temp(self):
|
# self.tx_delay.left = [delta*(i*2) for i in range(self.n_modules)]
|
||||||
"""
|
# self.tx_delay.right = [delta*(i*2+1) for i in range(self.n_modules)]
|
||||||
An instance of DetectorAdcs used to read the temperature
|
|
||||||
of different components
|
|
||||||
|
|
||||||
Examples
|
|
||||||
-----------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
detector.temp
|
|
||||||
>>
|
|
||||||
temp_fpga : 36.90°C, 45.60°C
|
|
||||||
temp_fpgaext : 31.50°C, 32.50°C
|
|
||||||
temp_10ge : 0.00°C, 0.00°C
|
|
||||||
temp_dcdc : 36.00°C, 36.00°C
|
|
||||||
temp_sodl : 33.00°C, 34.50°C
|
|
||||||
temp_sodr : 33.50°C, 34.00°C
|
|
||||||
temp_fpgafl : 33.81°C, 30.93°C
|
|
||||||
temp_fpgafr : 27.88°C, 29.15°C
|
|
||||||
|
|
||||||
a = detector.temp.fpga[:]
|
|
||||||
a
|
|
||||||
>> [36.568, 45.542]
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self._temp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tengiga(self):
|
|
||||||
"""Enable 10Gbit/s data output
|
|
||||||
|
|
||||||
Examples
|
|
||||||
----------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
d.tengiga
|
|
||||||
>> False
|
|
||||||
|
|
||||||
d.tengiga = True
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self._api.getTenGigabitEthernet()
|
|
||||||
|
|
||||||
@tengiga.setter
|
|
||||||
def tengiga(self, value):
|
|
||||||
self._api.setTenGigabitEthernet(value)
|
|
||||||
|
|
||||||
def set_delays(self, delta):
|
|
||||||
self.tx_delay.left = [delta*(i*2) for i in range(self.n_modules)]
|
|
||||||
self.tx_delay.right = [delta*(i*2+1) for i in range(self.n_modules)]
|
|
||||||
|
|
||||||
|
|
||||||
def setup500k(self, hostnames):
|
|
||||||
"""
|
|
||||||
Setup the Eiger detector to run on the local machine
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.hostname = hostnames
|
|
||||||
self.file_write = False
|
|
||||||
self.image_size = (512, 1024)
|
|
||||||
self.rx_tcpport = [1954, 1955]
|
|
||||||
self.rx_udpport = [50010, 50011, 50004, 50005]
|
|
||||||
self.rx_hostname = socket.gethostname().split('.')[0]
|
|
||||||
self.rx_datastream = False
|
|
||||||
self.file_write = False
|
|
||||||
self.online = True
|
|
||||||
self.receiver_online = True
|
|
||||||
|
@ -28,10 +28,10 @@ class Register:
|
|||||||
|
|
||||||
|
|
||||||
def freeze(cls):
|
def freeze(cls):
|
||||||
cls.__frozen = False
|
cls._frozen = False
|
||||||
|
|
||||||
def frozensetattr(self, key, value):
|
def frozensetattr(self, key, value):
|
||||||
if self.__frozen and not hasattr(self, key):
|
if self._frozen and not hasattr(self, key):
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
"Class {} is frozen. Cannot set {} = {}".format(
|
"Class {} is frozen. Cannot set {} = {}".format(
|
||||||
cls.__name__, key, value
|
cls.__name__, key, value
|
||||||
@ -44,7 +44,7 @@ def freeze(cls):
|
|||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
func(self, *args, **kwargs)
|
func(self, *args, **kwargs)
|
||||||
self.__frozen = True
|
self._frozen = True
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@ -70,6 +70,8 @@ class Detector(CppDetectorApi):
|
|||||||
super().__init__(multi_id)
|
super().__init__(multi_id)
|
||||||
self._register = Register(self)
|
self._register = Register(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self.size()
|
return self.size()
|
||||||
@ -197,6 +199,18 @@ class Detector(CppDetectorApi):
|
|||||||
else:
|
else:
|
||||||
self.setSubExptime(dt.timedelta(seconds=t))
|
self.setSubExptime(dt.timedelta(seconds=t))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def subdeadtime(self):
|
||||||
|
res = self.getSubDeadTime()
|
||||||
|
return element_if_equal([it.total_seconds() for it in res])
|
||||||
|
|
||||||
|
@subdeadtime.setter
|
||||||
|
def subdeadtime(self, t):
|
||||||
|
if isinstance(t, dt.timedelta):
|
||||||
|
self.setSubDeadTime(t)
|
||||||
|
else:
|
||||||
|
self.setSubDeadTime(dt.timedelta(seconds=t))
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def period(self):
|
def period(self):
|
||||||
@ -232,14 +246,7 @@ class Detector(CppDetectorApi):
|
|||||||
def startingfnum(self, value):
|
def startingfnum(self, value):
|
||||||
self.setStartingFrameNumber(value)
|
self.setStartingFrameNumber(value)
|
||||||
|
|
||||||
#TODO! testing switches on automatically?
|
|
||||||
@property
|
|
||||||
def flowcontrol_10g(self):
|
|
||||||
return element_if_equal(self.getTenGigaFlowControl())
|
|
||||||
|
|
||||||
@flowcontrol_10g.setter
|
|
||||||
def flowcontrol_10g(self, enable):
|
|
||||||
self.setTenGigaFlowControl(enable)
|
|
||||||
|
|
||||||
#TODO! add txdelay
|
#TODO! add txdelay
|
||||||
|
|
||||||
@ -647,3 +654,32 @@ class Detector(CppDetectorApi):
|
|||||||
@dsamples.setter
|
@dsamples.setter
|
||||||
def dsamples(self, N):
|
def dsamples(self, N):
|
||||||
self.setNumberOfDigitalSamples(N)
|
self.setNumberOfDigitalSamples(N)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Some Eiger stuff, does this have to be here or can we move it to subclass?
|
||||||
|
"""
|
||||||
|
@property
|
||||||
|
def partialreset(self):
|
||||||
|
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 flowcontrol10g(self):
|
||||||
|
return element_if_equal(self.getTenGigaFlowControl())
|
||||||
|
|
||||||
|
@flowcontrol10g.setter
|
||||||
|
def flowcontrol10g(self, enable):
|
||||||
|
self.setTenGigaFlowControl(enable)
|
Loading…
x
Reference in New Issue
Block a user