Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • calibration/calng
1 result
Show changes
Commits on Source (11)
...@@ -348,6 +348,11 @@ class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend): ...@@ -348,6 +348,11 @@ class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend):
OVERWRITE_ELEMENT(schema) OVERWRITE_ELEMENT(schema)
.key(f"{param_prefix}.memoryCells") .key(f"{param_prefix}.memoryCells")
.setNewDefaultValue(352) .setNewDefaultValue(352)
.commit(),
OVERWRITE_ELEMENT(schema)
.key(f"{param_prefix}.biasVoltage")
.setNewDefaultValue(300)
.commit() .commit()
) )
...@@ -377,7 +382,7 @@ class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend): ...@@ -377,7 +382,7 @@ class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend):
.key(f"{param_prefix}.gainMode") .key(f"{param_prefix}.gainMode")
.assignmentOptional() .assignmentOptional()
.defaultValue("ADAPTIVE_GAIN") .defaultValue("ADAPTIVE_GAIN")
.options("ADAPTIVE_GAIN,FIXED_HIGH_GAIN,FIXED_MEDIUM_GAIN,FIXED_LOW_GAIN") .options(",".join(gain_mode.name for gain_mode in AgipdGainMode))
.commit(), .commit(),
DOUBLE_ELEMENT(schema) DOUBLE_ELEMENT(schema)
...@@ -437,6 +442,7 @@ class AgipdCorrection(BaseCorrection): ...@@ -437,6 +442,7 @@ class AgipdCorrection(BaseCorrection):
_kernel_runner_class = AgipdGpuRunner _kernel_runner_class = AgipdGpuRunner
_calcat_friend_class = AgipdCalcatFriend _calcat_friend_class = AgipdCalcatFriend
_constant_enum_class = AgipdConstants _constant_enum_class = AgipdConstants
_managed_keys = BaseCorrection._managed_keys.copy()
@staticmethod @staticmethod
def expectedParameters(expected): def expectedParameters(expected):
......
...@@ -123,6 +123,11 @@ class DsscCalcatFriend(calcat_utils.BaseCalcatFriend): ...@@ -123,6 +123,11 @@ class DsscCalcatFriend(calcat_utils.BaseCalcatFriend):
OVERWRITE_ELEMENT(schema) OVERWRITE_ELEMENT(schema)
.key(f"{param_prefix}.memoryCells") .key(f"{param_prefix}.memoryCells")
.setNewDefaultValue(400) .setNewDefaultValue(400)
.commit(),
OVERWRITE_ELEMENT(schema)
.key(f"{param_prefix}.biasVoltage")
.setNewDefaultValue(100) # TODO: proper
.commit() .commit()
) )
( (
......
import enum
import pathlib import pathlib
import threading import threading
from timeit import default_timer from timeit import default_timer
...@@ -14,6 +15,7 @@ from karabo.bound import ( ...@@ -14,6 +15,7 @@ from karabo.bound import (
NDARRAY_ELEMENT, NDARRAY_ELEMENT,
NODE_ELEMENT, NODE_ELEMENT,
OUTPUT_CHANNEL, OUTPUT_CHANNEL,
OVERWRITE_ELEMENT,
SLOT_ELEMENT, SLOT_ELEMENT,
STRING_ELEMENT, STRING_ELEMENT,
UINT32_ELEMENT, UINT32_ELEMENT,
...@@ -40,6 +42,13 @@ from ._version import version as deviceVersion ...@@ -40,6 +42,13 @@ from ._version import version as deviceVersion
PROCESSING_STATE_TIMEOUT = 10 PROCESSING_STATE_TIMEOUT = 10
class FramefilterSpecType(enum.Enum):
NONE = "none"
RANGE = "range"
COMMASEPARATED = "commaseparated"
preview_schema = Schema() preview_schema = Schema()
( (
NODE_ELEMENT(preview_schema).key("image").commit(), NODE_ELEMENT(preview_schema).key("image").commit(),
...@@ -241,13 +250,18 @@ class BaseCorrection(PythonDevice): ...@@ -241,13 +250,18 @@ class BaseCorrection(PythonDevice):
do_generate_preview, do_generate_preview,
): ):
"""Subclass must define data processing (presumably using the kernel runner). """Subclass must define data processing (presumably using the kernel runner).
Will be called by input_handler, which will take care of some common checks " Will be called by input_handler, which will take care of some common checks and
"and extracting the parameters given to process_data.""" extracting the parameters given to process_data."""
raise NotImplementedError() raise NotImplementedError()
@staticmethod @staticmethod
def expectedParameters(expected): def expectedParameters(expected):
( (
OVERWRITE_ELEMENT(expected)
.key("state")
.setNewDefaultValue(State.INIT)
.commit(),
INPUT_CHANNEL(expected).key("dataInput").commit(), INPUT_CHANNEL(expected).key("dataInput").commit(),
OUTPUT_CHANNEL(expected) OUTPUT_CHANNEL(expected)
...@@ -291,7 +305,7 @@ class BaseCorrection(PythonDevice): ...@@ -291,7 +305,7 @@ class BaseCorrection(PythonDevice):
"are parsed and passed directly to numpy.arange. 'commaseparated' " "are parsed and passed directly to numpy.arange. 'commaseparated' "
"reads a list of integers separated by commas." "reads a list of integers separated by commas."
) )
.options("none,arange,commaseparated") .options(",".join(spectype.value for spectype in FramefilterSpecType))
.assignmentOptional() .assignmentOptional()
.defaultValue("none") .defaultValue("none")
.reconfigurable() .reconfigurable()
...@@ -404,7 +418,7 @@ class BaseCorrection(PythonDevice): ...@@ -404,7 +418,7 @@ class BaseCorrection(PythonDevice):
.displayedName("Memory cells") .displayedName("Memory cells")
.description("Full number of memory cells in incoming data") .description("Full number of memory cells in incoming data")
.assignmentOptional() .assignmentOptional()
.noDefaultValue() # subclass will want to set a default value .defaultValue(1) # subclass will want to set a default value
.commit(), .commit(),
UINT32_ELEMENT(expected) UINT32_ELEMENT(expected)
...@@ -424,6 +438,7 @@ class BaseCorrection(PythonDevice): ...@@ -424,6 +438,7 @@ class BaseCorrection(PythonDevice):
"the latter indicating the memory cell axis. The default value of " "the latter indicating the memory cell axis. The default value of "
"'cxy' puts pixels on the fast axes." "'cxy' puts pixels on the fast axes."
) )
.options("cxy,cyx,xcy,xyc,ycx,yxc")
.assignmentOptional() .assignmentOptional()
.defaultValue("cxy") .defaultValue("cxy")
.commit(), .commit(),
...@@ -483,7 +498,7 @@ class BaseCorrection(PythonDevice): ...@@ -483,7 +498,7 @@ class BaseCorrection(PythonDevice):
BOOL_ELEMENT(expected) BOOL_ELEMENT(expected)
.key("preview.enable") .key("preview.enable")
.displayedName("Enable preview data generation") .displayedName("Enable preview")
.assignmentOptional() .assignmentOptional()
.defaultValue(True) .defaultValue(True)
.reconfigurable() .reconfigurable()
...@@ -494,12 +509,13 @@ class BaseCorrection(PythonDevice): ...@@ -494,12 +509,13 @@ class BaseCorrection(PythonDevice):
.displayedName("Index (or stat) for preview") .displayedName("Index (or stat) for preview")
.description( .description(
"If this value is ≥ 0, the corresponding index (frame, cell, or pulse) " "If this value is ≥ 0, the corresponding index (frame, cell, or pulse) "
"will be sliced for the preview output. If this value is 0, preview " "will be sliced for the preview output. If this value is < 0, preview "
"will be one of the following stats: -1: max, -2: mean, -3: sum, -4: " "will be one of the following stats: -1: max, -2: mean, -3: sum, -4: "
"stdev. These stats are computed across memory cells." "stdev. These stats are computed across memory cells."
) )
.assignmentOptional() .assignmentOptional()
.defaultValue(0) .defaultValue(0)
.minInc(-4)
.reconfigurable() .reconfigurable()
.commit(), .commit(),
...@@ -525,8 +541,8 @@ class BaseCorrection(PythonDevice): ...@@ -525,8 +541,8 @@ class BaseCorrection(PythonDevice):
.description( .description(
"Preview will only be generated for trains whose ID modulo this " "Preview will only be generated for trains whose ID modulo this "
"number is zero. Higher values means less frequent preview updates. " "number is zero. Higher values means less frequent preview updates. "
"Keep in mind that the GUI has limited refresh rate of 2 Hz. Should " "Keep in mind that the GUI has limited refresh rate. Extra care must "
"take extra care if DAQ train stride is >1." "be taken if DAQ train stride is >1."
) )
.assignmentOptional() .assignmentOptional()
.defaultValue(6) .defaultValue(6)
...@@ -557,7 +573,7 @@ class BaseCorrection(PythonDevice): ...@@ -557,7 +573,7 @@ class BaseCorrection(PythonDevice):
.readOnly() .readOnly()
.initialValue(0) .initialValue(0)
.warnHigh(100) .warnHigh(100)
.info("Processing not fast enough for full speed") .info("Processing too slow to reach 10 Hz")
.needsAcknowledging(False) .needsAcknowledging(False)
.commit(), .commit(),
...@@ -584,17 +600,12 @@ class BaseCorrection(PythonDevice): ...@@ -584,17 +600,12 @@ class BaseCorrection(PythonDevice):
def __init__(self, config): def __init__(self, config):
self._schema_cache = { self._schema_cache = {
k: config.get(k) for k in self._schema_cache_fields if config.has(k) k: config[k] for k in self._schema_cache_fields if config.has(k)
} }
super().__init__(config) super().__init__(config)
if not sorted(config.get("dataFormat.outputAxisOrder")) == ["c", "x", "y"]: self.input_data_dtype = np.dtype(config["dataFormat.inputImageDtype"])
# TODO: figure out how to get this information to operator self.output_data_dtype = np.dtype(config["dataFormat.outputImageDtype"])
self.log_status_error("Invalid output axis order string")
return
self.input_data_dtype = np.dtype(config.get("dataFormat.inputImageDtype"))
self.output_data_dtype = np.dtype(config.get("dataFormat.outputImageDtype"))
self.sources = set(config.get("fastSources")) self.sources = set(config.get("fastSources"))
...@@ -606,15 +617,36 @@ class BaseCorrection(PythonDevice): ...@@ -606,15 +617,36 @@ class BaseCorrection(PythonDevice):
self._buffer_lock = threading.Lock() self._buffer_lock = threading.Lock()
self._last_processing_started = 0 # used for processing time and timeout self._last_processing_started = 0 # used for processing time and timeout
# register slots
if parse_version(karaboVersion) >= parse_version("2.11"):
# TODO: the CalCatFriend could add these for us
# note: overly complicated for closure to work
def make_wrapper_capturing_constant(constant):
def aux():
self.calcat_friend.get_specific_constant_version_and_call_me_back(
constant, self._load_constant_to_runner
)
return aux
for constant in self._constant_enum_class:
slot_name = f"foundConstants.{constant.name}.overrideConstantVersion"
meth_name = slot_name.replace(".", "_")
self.KARABO_SLOT(
make_wrapper_capturing_constant(constant),
slotName=meth_name,
)
self.KARABO_SLOT(self.loadMostRecentConstants)
self.KARABO_SLOT(self.requestScene)
self.registerInitialFunction(self._initialization) self.registerInitialFunction(self._initialization)
def _initialization(self): def _initialization(self):
self.updateState(State.INIT)
self.calcat_friend = self._calcat_friend_class( self.calcat_friend = self._calcat_friend_class(
self, pathlib.Path.cwd() / "calibration-client-secrets.json" self, pathlib.Path.cwd() / "calibration-client-secrets.json"
) )
self._update_frame_filter() self._update_frame_filter()
self._update_buffers()
self._buffered_status_update = Hash( self._buffered_status_update = Hash(
"trainId", "trainId",
...@@ -634,31 +666,11 @@ class BaseCorrection(PythonDevice): ...@@ -634,31 +666,11 @@ class BaseCorrection(PythonDevice):
self.KARABO_ON_INPUT("dataInput", self.input_handler) self.KARABO_ON_INPUT("dataInput", self.input_handler)
self.KARABO_ON_EOS("dataInput", self.handle_eos) self.KARABO_ON_EOS("dataInput", self.handle_eos)
if parse_version(karaboVersion) >= parse_version("2.11"):
# TODO: the CalCatFriend could add these for us
# note: overly complicated for closure to work
def make_wrapper_capturing_constant(constant):
def aux():
self.calcat_friend.get_specific_constant_version_and_call_me_back(
constant, self._load_constant_to_runner
)
return aux
for constant in self._constant_enum_class:
slot_name = f"foundConstants.{constant.name}.overrideConstantVersion"
meth_name = slot_name.replace(".", "_")
self.KARABO_SLOT(
make_wrapper_capturing_constant(constant),
slotName=meth_name,
)
self.KARABO_SLOT(self.loadMostRecentConstants)
self.KARABO_SLOT(self.requestScene)
self.updateState(State.ON) self.updateState(State.ON)
def __del__(self): def __del__(self):
del self._shmem_buffer del self._shmem_buffer
super().__del__()
def preReconfigure(self, config): def preReconfigure(self, config):
for ts_path in ( for ts_path in (
...@@ -820,18 +832,18 @@ class BaseCorrection(PythonDevice): ...@@ -820,18 +832,18 @@ class BaseCorrection(PythonDevice):
self.log.DEBUG(f"Corrections for dataOutput: {str(enabled)}") self.log.DEBUG(f"Corrections for dataOutput: {str(enabled)}")
self.log.DEBUG(f"Corrections for preview: {str(preview)}") self.log.DEBUG(f"Corrections for preview: {str(preview)}")
def _update_frame_filter(self): def _update_frame_filter(self, update_buffers=True):
"""Parse frameFilter string (if set) and update cached filter array. May update """Parse frameFilter string (if set) and update cached filter array. May update
dataFormat.filteredFrames, so one will typically want to call _update_buffers dataFormat.filteredFrames - will therefore by default call _update_buffers
afterwards.""" afterwards."""
# TODO: add some validation to preReconfigure # TODO: add some validation to preReconfigure
self.log.DEBUG("Updating frame filter") self.log.DEBUG("Updating frame filter")
filter_type = self.get("frameFilter.type") filter_type = FramefilterSpecType(self.get("frameFilter.type"))
filter_string = self.get("frameFilter.spec") filter_string = self.get("frameFilter.spec")
if filter_type == "none" or filter_string.strip() == "": if filter_type is FramefilterSpecType.NONE or filter_string.strip() == "":
self._frame_filter = None self._frame_filter = None
elif filter_type == "arange": elif filter_type is Framefilterspectype.RANGE:
try: try:
numbers = tuple(int(part) for part in filter_string.split(",")) numbers = tuple(int(part) for part in filter_string.split(","))
except (ValueError, TypeError): except (ValueError, TypeError):
...@@ -840,7 +852,7 @@ class BaseCorrection(PythonDevice): ...@@ -840,7 +852,7 @@ class BaseCorrection(PythonDevice):
) )
else: else:
self._frame_filter = np.arange(*numbers, dtype=np.uint16) self._frame_filter = np.arange(*numbers, dtype=np.uint16)
elif filter_type == "commaseparated": elif filter_type is Framefilterspectype.COMMASEPARATED:
try: try:
self._frame_filter = np.fromstring( self._frame_filter = np.fromstring(
filter_string, sep=",", dtype=np.uint16 filter_string, sep=",", dtype=np.uint16
...@@ -866,6 +878,9 @@ class BaseCorrection(PythonDevice): ...@@ -866,6 +878,9 @@ class BaseCorrection(PythonDevice):
): ):
self.log_status_warn("Invalid frame filter set, expect exceptions!") self.log_status_warn("Invalid frame filter set, expect exceptions!")
if update_buffers:
self._update_buffers()
def _update_buffers(self): def _update_buffers(self):
"""(Re)initialize buffers / kernel runner according to expected data shapes""" """(Re)initialize buffers / kernel runner according to expected data shapes"""
self.log.INFO("Updating buffers according to data shapes") self.log.INFO("Updating buffers according to data shapes")
...@@ -968,7 +983,6 @@ class BaseCorrection(PythonDevice): ...@@ -968,7 +983,6 @@ class BaseCorrection(PythonDevice):
self.set("dataFormat.memoryCells", image_data.shape[0]) self.set("dataFormat.memoryCells", image_data.shape[0])
with self._buffer_lock: with self._buffer_lock:
self._update_frame_filter() self._update_frame_filter()
self._update_buffers()
# DataAggregator typically tells us the wrong axis order # DataAggregator typically tells us the wrong axis order
if self._schema_cache["dataFormat.overrideInputAxisOrder"]: if self._schema_cache["dataFormat.overrideInputAxisOrder"]:
......
...@@ -248,25 +248,33 @@ class BaseCalcatFriend: ...@@ -248,25 +248,33 @@ class BaseCalcatFriend:
UINT32_ELEMENT(schema) UINT32_ELEMENT(schema)
.key(f"{param_prefix}.memoryCells") .key(f"{param_prefix}.memoryCells")
.displayedName("Memory cells")
.description(
"Number of memory cells / frames per train. Relevant for burst mode."
)
.assignmentOptional() .assignmentOptional()
.noDefaultValue() .defaultValue(1)
.reconfigurable() .reconfigurable()
.commit(), .commit(),
UINT32_ELEMENT(schema) UINT32_ELEMENT(schema)
.key(f"{param_prefix}.pixelsX") .key(f"{param_prefix}.pixelsX")
.displayedName("Pixels X")
.assignmentOptional() .assignmentOptional()
.defaultValue(512) .defaultValue(512)
.commit(), .commit(),
UINT32_ELEMENT(schema) UINT32_ELEMENT(schema)
.key(f"{param_prefix}.pixelsY") .key(f"{param_prefix}.pixelsY")
.displayedName("Pixels Y")
.assignmentOptional() .assignmentOptional()
.defaultValue(128) .defaultValue(128)
.commit(), .commit(),
DOUBLE_ELEMENT(schema) DOUBLE_ELEMENT(schema)
.key(f"{param_prefix}.biasVoltage") .key(f"{param_prefix}.biasVoltage")
.displayedName("Bias voltage")
.description("Sensor bias voltage")
.assignmentOptional() .assignmentOptional()
.defaultValue(300) .defaultValue(300)
.reconfigurable() .reconfigurable()
......