from .detector_condition import DetectorCondition
from .operating_condition import OperatingCondition
[docs]class BaseDetectorCondition(DetectorCondition):
"""
A basic operating condition valid for all semi-conductor detectors
"""
def __init__(self, memory_cells=1, bias_voltage=None,
pixels_x=None, pixels_y=None):
"""
Initialize a basic detector condition
:param memory_cells: number of memory cells of the detector. Set to
"1" for detectors without front-end memory.
:param bias_voltage: detector bias-voltage. Set to `None`
if not relevant
:param pixels_x: number of pixels in x-direction. Set to `None` if
not relevant.
:param pixels_y: number of pixels in y-direction. Set to `None` if
not relevant.
"""
super(BaseDetectorCondition, self).__init__()
self.parameters = []
if memory_cells:
self.add_operating_condition(self._memory_cells(memory_cells))
if bias_voltage:
self.add_operating_condition(self._bias_voltage(bias_voltage))
if pixels_x:
self.add_operating_condition(self._pixels_x(pixels_x))
if pixels_y:
self.add_operating_condition(self._pixels_y(pixels_y))
[docs] def add_operating_condition(self, condition):
"""
Add an operating condition to the detector condition parameter list
"""
self.parameters.append(condition)
def _bias_voltage(self, voltage):
condition = OperatingCondition()
condition.name = "Sensor Bias Voltage"
condition.description = "Sensor Bias Voltage"
condition.logarithmic = False
condition.lower_deviation = 5.0 # V
condition.upper_deviation = 5.0 # V
condition.value = voltage
return condition
def _pixels_x(self, pixels_x):
condition = OperatingCondition()
condition.name = "Pixels X"
condition.description = "Pixels X"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = pixels_x
return condition
def _pixels_y(self, pixels_y):
condition = OperatingCondition()
condition.name = "Pixels Y"
condition.description = "Pixels Y"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = pixels_y
return condition
def _memory_cells(self, cells):
condition = OperatingCondition()
condition.name = "Memory cells"
condition.description = "Memory cells"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = cells
return condition
[docs]class IlluminatedCondition(BaseDetectorCondition):
"""
A basic operating condition valid for detectors illuminated with photons.
"""
def __init__(self, photon_energy=None, beam_energy=None,
memory_cells=1, bias_voltage=None,
pixels_x=None, pixels_y=None):
"""
Same parameters as `BaseDetectorCondition` and in addition:
:param photon_energy: energy of photons in keV
:param beam_energy: total beam energy (per pulse) in μJ. Set to `None`
if not relevant.
"""
super(IlluminatedCondition, self).__init__(memory_cells=memory_cells,
bias_voltage=bias_voltage,
pixels_x=pixels_x,
pixels_y=pixels_y)
if photon_energy:
self.add_operating_condition(self._photon_energy(photon_energy))
if beam_energy:
self.add_operating_condition(self._beam_energy(beam_energy))
def _photon_energy(self, photon_energy):
condition = OperatingCondition()
condition.name = "Source Energy"
condition.description = "Source photon energy in keV"
condition.logarithmic = False
condition.lower_deviation = 1
condition.upper_deviation = 1
condition.value = photon_energy
return condition
def _beam_energy(self, beam_energy):
condition = OperatingCondition()
condition.name = "BeamEnergy"
condition.description = "Beam energy in uJ"
condition.logarithmic = False
condition.lower_deviation = 50
condition.upper_deviation = 50
condition.value = beam_energy
return condition
[docs]class LPDCondition(BaseDetectorCondition):
"""
Basic LPD detector condition.
"""
def __init__(self, memory_cells, bias_voltage,
pixels_x=256, pixels_y=256, capacitor='5pF'):
"""
Same parameters as `BaseDetectorCondition`.
Additionally, the feedback capacitor setting should be specified.
"""
super(LPDCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=memory_cells,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "LPD Def"
self.description = "The default LPD operating condition"
self.add_operating_condition(self._capacitor(capacitor))
def _capacitor(self, capacitor):
if capacitor == 5 or "5" in capacitor:
capval = 5
else:
capval = 50
condition = OperatingCondition()
condition.name = "Feedback capacitor"
condition.description = "Capacitor setting"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = capval
return condition
[docs]class LPDIlluminatedCondition(IlluminatedCondition):
"""
Illuminated LPD detector condition.
"""
def __init__(
self, memory_cells, bias_voltage,
photon_energy, pixels_x=256,
pixels_y=256, beam_energy=None,
capacitor='5pf', category=0,
):
"""
Same parameters as `IlluminatedCondition`.
Additionally, the feedback capacitor setting should be specified.
"""
super(LPDIlluminatedCondition, self).__init__(memory_cells=memory_cells,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "LPD Def Ill"
self.description = "The default LPD illuminated operating condition"
self.add_operating_condition(self._capacitor(capacitor))
if not category in (None, ""):
self.add_operating_condition(self._category(category))
def _capacitor(self, capacitor):
if capacitor == 5 or "5" in capacitor:
capval = 5
else:
capval = 50
condition = OperatingCondition()
condition.name = "Feedback capacitor"
condition.description = "Capacitor setting"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = capval
return condition
def _category(self, category):
condition = OperatingCondition()
condition.name = "Category"
condition.description = (
"Temporary condition to differentiate between "
"different Calibration constant source categories,"
" 0: European XFEL and 1: RAL"
)
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = category
return condition
[docs]class AGIPDCondition(BaseDetectorCondition):
"""Basic dark AGIPD detector condition."""
def __init__(self, memory_cells, bias_voltage,
pixels_x=512, pixels_y=128, acquisition_rate=None,
gain_setting=None, gain_mode=None):
super(AGIPDCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=memory_cells,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "AGIPD Def"
self.description = "The default AGIPD operating condition"
self._init_agipd_dark_conditions(acquisition_rate, gain_setting,
gain_mode)
def _init_agipd_dark_conditions(self, acquisition_rate,
gain_setting, gain_mode):
if acquisition_rate:
self.add_operating_condition(self._aqrate(acquisition_rate))
# gain_setting can be 0 or 1
if gain_setting not in (None, ''):
self.add_operating_condition(self._gain_setting(gain_setting))
if gain_mode:
self.add_operating_condition(self._gain_mode(bool(gain_mode)))
def _aqrate(self, rate):
condition = OperatingCondition()
condition.name = "Acquisition rate"
condition.description = "Acquisition rate"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = rate
return condition
def _gain_setting(self, setting):
condition = OperatingCondition()
condition.name = "Gain Setting"
# Correlated Double Sampling
condition.description = "0 - CDS low, 1 - CDS high"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = setting
return condition
def _gain_mode(self, rate):
"""Gain Mode is a parameter of 4 integer possibility values.
0. Adaptive Gain
1. High Gain
2. Medium Gain
3. Low Gain
For backwards compatability for the Adaptive gain,
gain_mode is not needed for AGIPD operating conditions.
While a boolean 1 is used if it is one of
the 3 fixed gain modes (gain_mode > 0).
The reason is that fixed gain constants has the same dimensions
of adaptive gain constants with the 3 fixed gains stored.
"""
condition = OperatingCondition()
condition.name = "Gain mode"
condition.description = ("Gain mode (1 for fixed gain mode"
" is a boolean of 1-High gain, "
"2-Medium gain, or 3-Low gain")
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = rate
return condition
[docs]class AGIPDIlluminatedCondition(IlluminatedCondition, AGIPDCondition):
"""Illuminated AGIPD detector condition."""
def __init__(self, memory_cells, bias_voltage, photon_energy,
pixels_x=512, pixels_y=128, beam_energy=None,
acquisition_rate=None, gain_setting=None, gain_mode=None):
super(AGIPDIlluminatedCondition, self).__init__(
memory_cells=memory_cells,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "AGIPD Def Ill"
self.description = "The default AGIPD illuminated operating condition"
self._init_agipd_dark_conditions(acquisition_rate=acquisition_rate,
gain_setting=gain_setting,
gain_mode=gain_mode)
[docs]class JungfrauMixinCondition:
def _integration_time(self, integration_time, lower_dev=50, upper_dev=50):
condition = OperatingCondition()
condition.name = "Integration Time"
condition.description = "Integration time in ms"
condition.logarithmic = False
condition.lower_deviation = lower_dev
condition.upper_deviation = upper_dev
condition.value = integration_time
return condition
def _temperature(self, temperature):
condition = OperatingCondition()
condition.name = "Sensor Temperature"
condition.description = "Sensor Temperature in K"
condition.logarithmic = False
condition.lower_deviation = 5
condition.upper_deviation = 5
condition.value = temperature
return condition
def _gain_setting(self, setting):
condition = OperatingCondition()
condition.name = "Gain Setting"
condition.description = "Feedback capacitor setting: def: 0, 1 -> HG0"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = setting
return condition
[docs]class JungfrauCondition(BaseDetectorCondition, JungfrauMixinCondition):
"""
Basic Jungfrau detector condition.
"""
def __init__(self, memory_cells, bias_voltage, integration_time,
pixels_x=1024, pixels_y=512, temperature=291,
gain_setting=0):
super(JungfrauCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=memory_cells,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "Jungfrau Def"
self.description = "The default Jungfrau operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._gain_setting(gain_setting))
[docs]class JungfrauIlluminatedCondition(IlluminatedCondition, JungfrauMixinCondition):
"""
Illuminated Jungfrau detector condition.
"""
def __init__(self, memory_cells, bias_voltage, photon_energy, integration_time,
pixels_x=1024, pixels_y=512, beam_energy=None, temperature=291,
gain_setting=0):
super(JungfrauIlluminatedCondition, self).__init__(memory_cells=memory_cells,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "Jungfrau Def Ill"
self.description = "The default Jungfrau illuminated operating condition"
self.add_operating_condition(self._integration_time(integration_time,
1000, 2000))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._gain_setting(gain_setting))
[docs]class CCDMixinCondition:
def _integration_time(self, integration_time):
condition = OperatingCondition()
condition.name = "Integration Time"
condition.description = "Integration time in ms"
condition.logarithmic = False
condition.lower_deviation = 50
condition.upper_deviation = 50
condition.value = integration_time
return condition
def _temperature(self, temperature):
condition = OperatingCondition()
condition.name = "Sensor Temperature"
condition.description = "Sensor Temperature in K"
condition.logarithmic = False
condition.lower_deviation = 5
condition.upper_deviation = 5
condition.value = temperature
return condition
def _gain_setting(self, gain):
condition = OperatingCondition()
condition.name = "Gain Setting"
condition.description = "Gain Setting"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = gain
return condition
def _freq_threshold(self, freq_threshold):
condition = OperatingCondition()
condition.name = "Frequency Threshold"
condition.description = "Frequency Threshold"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = freq_threshold
return condition
[docs]class CCDCondition(BaseDetectorCondition, CCDMixinCondition):
"""
Basic CCDs detector condition.
"""
def __init__(self, bias_voltage, integration_time, gain_setting,
pixels_x=1024, pixels_y=512, temperature=291,
freq_threshold=None):
super(CCDCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=1,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "CCD Def"
self.description = "The default CCD operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._gain_setting(gain_setting))
# karabo would give a string
if freq_threshold:
self.add_operating_condition(self._freq_threshold(freq_threshold))
[docs]class CCDIlluminatedCondition(IlluminatedCondition, CCDMixinCondition):
"""
Illuminated CCDs detector condition.
"""
def __init__(self, bias_voltage, photon_energy, integration_time,
gain_setting, pixels_x=1024, pixels_y=512, beam_energy=None,
temperature=291):
super(CCDIlluminatedCondition, self).__init__(memory_cells=1,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "CCD Def Ill"
self.description = "The default CCD illuminated operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._gain_setting(gain_setting))
[docs]class EPix100Condition(BaseDetectorCondition, JungfrauMixinCondition):
"""
Basic xPix100 detector condition.
"""
def __init__(self, bias_voltage, integration_time, in_vacuum,
pixels_x=708, pixels_y=768, temperature=288):
super(EPix100Condition, self).__init__(bias_voltage=bias_voltage,
memory_cells=1,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "ePix100 Def"
self.description = "The default ePix100 operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._in_vacuum(in_vacuum))
def _in_vacuum(self, in_vacuum):
condition = OperatingCondition()
condition.name = "In vacuum"
condition.description = "Operation in vacuum"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = in_vacuum
return condition
[docs]class EPix100IlluminatedCondition(IlluminatedCondition, JungfrauMixinCondition):
"""
Illuminated xPix100 detector condition.
"""
def __init__(self, bias_voltage, photon_energy, integration_time,
in_vacuum, pixels_x=708, pixels_y=768, beam_energy=None,
temperature=288):
super(EPix100IlluminatedCondition, self).__init__(memory_cells=1,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "ePix100 Def Ill"
self.description = "The default ePix100 illuminated operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._in_vacuum(in_vacuum))
def _in_vacuum(self, in_vacuum):
condition = OperatingCondition()
condition.name = "In vacuum"
condition.description = "Operation in vacuum"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = in_vacuum
return condition
[docs]class EPix10KCondition(BaseDetectorCondition, JungfrauMixinCondition):
"""
Basic xPix100 detector condition.
"""
def __init__(self, bias_voltage, integration_time, in_vacuum,
pixels_x=356, pixels_y=384, temperature=253, gain_setting=0):
super(EPix10KCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=1,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "ePix10K Def"
self.description = "The default ePix10K operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._in_vacuum(in_vacuum))
self.add_operating_condition(self._gain_setting(gain_setting))
def _in_vacuum(self, in_vacuum):
condition = OperatingCondition()
condition.name = "In vacuum"
condition.description = "Operation in vacuum"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = in_vacuum
return condition
[docs]class EPix10KIlluminatedCondition(IlluminatedCondition, JungfrauMixinCondition):
"""
Illuminated xPix100 detector condition.
"""
def __init__(self, bias_voltage, photon_energy, integration_time,
in_vacuum, pixels_x=356, pixels_y=384, beam_energy=None,
temperature=253, gain_setting=0):
super(EPix10KIlluminatedCondition, self).__init__(memory_cells=1,
bias_voltage=bias_voltage,
photon_energy=photon_energy,
beam_energy=beam_energy,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "ePix10K Def Ill"
self.description = "The default ePix10K illuminated operating condition"
self.add_operating_condition(self._integration_time(integration_time))
self.add_operating_condition(self._temperature(temperature))
self.add_operating_condition(self._in_vacuum(in_vacuum))
self.add_operating_condition(self._gain_setting(gain_setting))
def _in_vacuum(self, in_vacuum):
condition = OperatingCondition()
condition.name = "In vacuum"
condition.description = "Operation in vacuum"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = in_vacuum
return condition
[docs]class DSSCCondition(BaseDetectorCondition):
"""
Basic DSSC detector condition.
"""
def __init__(self, memory_cells, bias_voltage,
pixels_x=512, pixels_y=128, pulseid_checksum=None,
acquisition_rate=None, target_gain=None, encoded_gain=None):
super(DSSCCondition, self).__init__(bias_voltage=bias_voltage,
memory_cells=memory_cells,
pixels_x=pixels_x,
pixels_y=pixels_y)
self.name = "DSSC Def"
self.description = "The default DSSC operating condition"
# karabo would give a string
if pulseid_checksum:
self.add_operating_condition(
self._pulseid_checksum(pulseid_checksum))
if acquisition_rate:
self.add_operating_condition(
self._acquisition_rate(acquisition_rate))
if target_gain:
self.add_operating_condition(self._target_gain(target_gain))
if encoded_gain:
self.add_operating_condition(self._encoded_gain(encoded_gain))
def _pulseid_checksum(self, pulseid_checksum):
condition = OperatingCondition()
condition.name = "Pulse id checksum"
condition.description = "Checksum of pulse ids"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = pulseid_checksum
return condition
def _acquisition_rate(self, acquisition_rate):
condition = OperatingCondition()
condition.name = "Acquisition rate"
condition.description = "Operating frequency"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = acquisition_rate
return condition
def _target_gain(self, target_gain):
condition = OperatingCondition()
condition.name = "Target gain"
condition.description = "target gain of the detector"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = target_gain
return condition
def _encoded_gain(self, encoded_gain):
condition = OperatingCondition()
condition.name = "Encoded gain"
condition.description = "Encoded value of gain settings"
condition.logarithmic = False
condition.lower_deviation = 0
condition.upper_deviation = 0
condition.value = encoded_gain
return condition
[docs]class Conditions:
"""
Predefined detector conditions are grouped in this class.
"""
[docs] class Dark:
"""
Conditions for non-illuminated detector
"""
LPD = LPDCondition
AGIPD = AGIPDCondition
jungfrau = JungfrauCondition
CCD = CCDCondition
ePix100 = EPix100Condition
ePix10K = EPix10KCondition
DSSC = DSSCCondition
[docs] class Illuminated:
"""
Conditions for an illuminated detector, which is additionally
specified by photon energy in keV and optionally, beam energy in μJ
"""
LPD = LPDIlluminatedCondition
AGIPD = AGIPDIlluminatedCondition
jungfrau = JungfrauIlluminatedCondition
CCD = CCDIlluminatedCondition
ePix100 = EPix100IlluminatedCondition
ePix10K = EPix10KIlluminatedCondition
DSSC = DSSCCondition