From 8620be2481f8a21b0864b49228332a9dda0f2efa Mon Sep 17 00:00:00 2001 From: David Hammer <dhammer@mailbox.org> Date: Tue, 5 Oct 2021 17:02:40 +0200 Subject: [PATCH] Start adding scenes --- src/calng/agipd_gpu.py | 6 -- src/calng/base_correction.py | 39 ++++++-- src/calng/base_gpu.py | 7 +- src/calng/calcat_utils.py | 12 +-- src/calng/scenes.py | 171 +++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 24 deletions(-) create mode 100644 src/calng/scenes.py diff --git a/src/calng/agipd_gpu.py b/src/calng/agipd_gpu.py index b8fbc6c7..b2914013 100644 --- a/src/calng/agipd_gpu.py +++ b/src/calng/agipd_gpu.py @@ -202,15 +202,9 @@ class AgipdGpuRunner(base_gpu.BaseGpuRunner): if override_flags_to_use is not None: self.override_bad_pixel_flags_to_use(override_flags_to_use) - print( - f"Percentage of bad pixels now: {cupy.count_nonzero(self.bad_pixel_map_gpu) / self.bad_pixel_map_gpu.size * 100:.02f}" - ) def override_bad_pixel_flags_to_use(self, override_value): self.bad_pixel_map_gpu &= cupy.uint32(override_value) - print( - f"Percentage of bad pixels now: {cupy.count_nonzero(self.bad_pixel_map_gpu) / self.bad_pixel_map_gpu.size * 100:.02f}" - ) def set_bad_pixel_mask_value(self, mask_value): self.bad_pixel_mask_value = cupy.float32(mask_value) diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py index fc6b5005..14632431 100644 --- a/src/calng/base_correction.py +++ b/src/calng/base_correction.py @@ -27,9 +27,10 @@ from karabo.bound import ( Trainstamp, Unit, ) +from karabo.common.api import KARABO_SCHEMA_DISPLAY_TYPE_SCENES as DT_SCENES from karabo.common.states import State -from . import shmem_utils, utils +from . import scenes, shmem_utils, utils from ._version import version as deviceVersion @@ -113,6 +114,12 @@ class BaseCorrection(PythonDevice): .assignmentOptional() .defaultValue(10) .commit(), + VECTOR_STRING_ELEMENT(expected) + .key("availableScenes") + .setSpecialDisplayType(DT_SCENES) + .readOnly() + .initialValue(["overview", "constants"]) + .commit(), ) ( @@ -198,11 +205,7 @@ class BaseCorrection(PythonDevice): .commit(), ) - ( - SLOT_ELEMENT(expected) - .key("loadMostRecentConstantsWrap") - .commit() - ) + (SLOT_ELEMENT(expected).key("loadMostRecentConstantsWrap").commit()) preview_schema = Schema() ( @@ -420,6 +423,7 @@ class BaseCorrection(PythonDevice): callback=self._update_actual_rate, ) self._buffer_lock = threading.Lock() + self.KARABO_SLOT(self.requestScene) def preReconfigure(self, config): if config.has("performance.rateUpdateInterval"): @@ -474,6 +478,29 @@ class BaseCorrection(PythonDevice): self.gpu_runner.flush_buffers() self._update_correction_flags() + def requestScene(self, params): + payload = Hash() + scene_name = params.get("name", default="") + payload["name"] = scene_name + payload["success"] = True + if scene_name == "overview": + payload["data"] = scenes.correction_device_overview_scene( + device_id=self.getInstanceId() + ) + elif scene_name == "constants": + payload["data"] = scenes.correction_device_constants_scene( + device_id=self.getInstanceId(), + node_prefix="constantParameters", + schema=self.getFullSchema(), + ) + else: + payload["success"] = False + response = Hash() + response["type"] = "deviceScene" + response["origin"] = self.getInstanceId() + response["payload"] = payload + self.reply(response) + def _write_output(self, data, old_metadata): metadata = ChannelMetaData( old_metadata.get("source"), diff --git a/src/calng/base_gpu.py b/src/calng/base_gpu.py index 1ee0a49d..1b1e9bc1 100644 --- a/src/calng/base_gpu.py +++ b/src/calng/base_gpu.py @@ -1,7 +1,6 @@ import pathlib import cupy -import cupyx import jinja2 import numpy as np @@ -71,10 +70,8 @@ class BaseGpuRunner: self.processed_shape, dtype=output_data_dtype ) self.reshaped_data_gpu = cupy.empty(self.output_shape, dtype=output_data_dtype) - self.preview_raw = cupyx.empty_pinned(self.preview_shape, dtype=np.float32) - self.preview_corrected = cupyx.empty_pinned( - self.preview_shape, dtype=np.float32 - ) + self.preview_raw = np.empty(self.preview_shape, dtype=np.float32) + self.preview_corrected = np.empty(self.preview_shape, dtype=np.float32) # functions to get data from respective buffers to cell, x, y shape for preview computation # TODO: handle shape juggling programmatically, removing need for these two helpers diff --git a/src/calng/calcat_utils.py b/src/calng/calcat_utils.py index 93040855..a24fea6e 100644 --- a/src/calng/calcat_utils.py +++ b/src/calng/calcat_utils.py @@ -18,7 +18,7 @@ from calibration_client.modules import ( Parameter, PhysicalDetectorUnit, ) -from karabo.bound import DOUBLE_ELEMENT, NODE_ELEMENT, STRING_ELEMENT +from karabo.bound import DOUBLE_ELEMENT, NODE_ELEMENT, STRING_ELEMENT, UINT32_ELEMENT from . import utils @@ -102,9 +102,7 @@ class BaseCalcatFriend: AgipdCalcatFriend.dark_condition. """ - ( - NODE_ELEMENT(schema).key(prefix).commit(), - ) + (NODE_ELEMENT(schema).key(prefix).commit(),) # Parameters which any detector would probably have (extend this in subclass) # TODO: probably switch to floating point for everything, including mem cells @@ -128,18 +126,18 @@ class BaseCalcatFriend: .assignmentOptional() .defaultValue("") .commit(), - DOUBLE_ELEMENT(schema) + UINT32_ELEMENT(schema) .key(f"{prefix}.memoryCells") .assignmentOptional() .defaultValue(352) .reconfigurable() .commit(), - DOUBLE_ELEMENT(schema) + UINT32_ELEMENT(schema) .key(f"{prefix}.pixelsX") .assignmentOptional() .defaultValue(512) .commit(), - DOUBLE_ELEMENT(schema) + UINT32_ELEMENT(schema) .key(f"{prefix}.pixelsY") .assignmentOptional() .defaultValue(512) diff --git a/src/calng/scenes.py b/src/calng/scenes.py new file mode 100644 index 00000000..f12ab19e --- /dev/null +++ b/src/calng/scenes.py @@ -0,0 +1,171 @@ +from karabo.bound import Types +from karabo.common.scenemodel.api import ( + DisplayLabelModel, + DisplayStateColorModel, + DisplayTextLogModel, + DoubleLineEditModel, + IntLineEditModel, + LabelModel, + SceneModel, + write_scene, +) + +BASE_INC = 30 +PADDING = 10 +RECONFIGURABLE = 4 # TODO: look up proper enum + + +def correction_device_constants_scene(device_id, node_prefix, schema): + # TODO: are there layout models in scene model somewhere? like gridbox? + subscenes = [] + max_height = 0 + # first column: parameters + row_offset = PADDING + col_offset = PADDING + subscenes.append( + LabelModel( + text="Parameters used for CalCat queries", + width=12 * BASE_INC, + x=col_offset, + y=row_offset, + ) + ) + row_offset += BASE_INC + for key in schema.getKeys(node_prefix): + key_path = f"{node_prefix}.{key}" + subscenes.append( + LabelModel( + text=schema.getDisplayedName(key_path) + if schema.hasDisplayedName(key_path) + else key, + width=5 * BASE_INC, + height=BASE_INC, + x=col_offset, + y=row_offset, + ) + ) + subscenes.append( + DisplayLabelModel( + keys=[f"{device_id}.{node_prefix}.{key}"], + width=7 * BASE_INC, + height=BASE_INC, + x=col_offset + 5 * BASE_INC, + y=row_offset, + ) + ) + if schema.getAccessMode(key_path) == RECONFIGURABLE: + value_type = schema.getValueType(key_path) + if value_type in (Types.DOUBLE, Types.FLOAT): + subscenes.append( + DoubleLineEditModel( + keys=[f"{device_id}.{node_prefix}.{key}"], + width=7 * BASE_INC, + height=BASE_INC, + x=col_offset + 12 * BASE_INC, + y=row_offset, + ) + ) + elif value_type in (Types.INT32, Types.UINT32, Types.INT64, Types.UINT64): + subscenes.append( + IntLineEditModel( + keys=[f"{device_id}.{node_prefix}.{key}"], + width=7 * BASE_INC, + height=BASE_INC, + x=col_offset + 12 * BASE_INC, + y=row_offset, + ) + ) + else: + subscenes.append( + LabelModel( + text=f"Not yet supported: editing {key} of type {value_type}", + width=7 * BASE_INC, + height=BASE_INC, + x=col_offset + 12 * BASE_INC, + y=row_offset, + ) + ) + + row_offset += BASE_INC + max_height = max(max_height, row_offset) + + # second column: constants as currently loaded + row_offset = PADDING + col_offset += 19 * BASE_INC # width of first column + col_offset += PADDING # and padding + subscenes.append( + LabelModel( + text="Constants found and loaded", + width=10 * BASE_INC, + x=col_offset, + y=row_offset, + ) + ) + row_offset += BASE_INC + max_height = max(max_height, row_offset) + + scene = SceneModel( + height=max_height + 2 * PADDING, + width=col_offset + 10 * BASE_INC + PADDING, + children=subscenes, + ) + return write_scene(scene) + + +def correction_device_overview_scene(device_id): + subscenes = [] + row_offset = 0 + # device class and name + subscenes.append( + LabelModel( + text="Correction device", + width=5 * BASE_INC, + height=BASE_INC, + x=0, + y=row_offset, + ) + ) + subscenes.append( + DisplayLabelModel( + keys=[f"{device_id}.deviceId"], + width=10 * BASE_INC, + height=BASE_INC, + x=5 * BASE_INC, + y=row_offset, + ) + ) + row_offset += BASE_INC + # device state + subscenes.append( + DisplayStateColorModel( + keys=[f"{device_id}.state"], + width=5 * BASE_INC, + height=BASE_INC, + # parent_component="DisplayComponent", + x=0, + y=row_offset, + ) + ) + subscenes.append( + DisplayLabelModel( + keys=[f"{device_id}.state"], + width=5 * BASE_INC, + height=BASE_INC, + x=0, + y=row_offset, + ) + ) + row_offset += BASE_INC + # log of status + subscenes.append( + DisplayTextLogModel( + keys=[f"{device_id}.status"], + width=10 * BASE_INC, + height=10 * BASE_INC, + x=0, + y=row_offset, + ) + ) + row_offset += BASE_INC * 10 + scene = SceneModel(height=845.0, width=742.0, children=subscenes) + return write_scene(scene) -- GitLab