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