mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 19:21:50 +02:00
refactor: add support to plot against x_data
This commit is contained in:
@ -1144,13 +1144,13 @@ class Waveform(PlotBase):
|
||||
to reduce the number of copies in between cycles. Be careful when refactoring
|
||||
this part as it will affect the performance of the async readback.
|
||||
|
||||
Async curves support plotting against 'index' or other 'device_signal'. No 'auto' or 'timestamp'.
|
||||
The fallback mechanism for 'auto' and 'timestamp' is to use the 'index'.
|
||||
|
||||
Note:
|
||||
We create data_plot_x and data_plot_y and modify them within this function
|
||||
to avoid creating new arrays. This is important for performance.
|
||||
We adjust the variables based on instruction type.
|
||||
- add: Add the new data to the existing data.
|
||||
- add_slice: Add the new data to the existing data and set the slice index.
|
||||
- replace: Replace the existing data with the new data.
|
||||
Support update instructions are 'add', 'add_slice', and 'replace'.
|
||||
|
||||
Args:
|
||||
msg(dict): Message with the async data.
|
||||
@ -1196,14 +1196,31 @@ class Waveform(PlotBase):
|
||||
|
||||
# Replace is trivial, no need to modify data_plot_y
|
||||
|
||||
# Get the x data if 'timestamp' is selected, otherwise compute it
|
||||
data_plot_x = async_data["timestamp"]
|
||||
if plot_mode == "timestamp" and instruction != "add_slice":
|
||||
if data_plot_x is not None and x_data is not None:
|
||||
data_plot_x = np.hstack((x_data, data_plot_x))
|
||||
else:
|
||||
# Get x data for plotting
|
||||
if plot_mode in ["index", "auto", "timestamp"]:
|
||||
data_plot_x = np.linspace(0, len(data_plot_y) - 1, len(data_plot_y))
|
||||
# Set the x data
|
||||
self._auto_adjust_async_curve_settings(curve, len(data_plot_y))
|
||||
curve.setData(data_plot_x, data_plot_y)
|
||||
# Move on in the loop
|
||||
continue
|
||||
# Only consider device signals that are async for now, fallback is index
|
||||
x_device_entry = self.x_axis_mode["entry"]
|
||||
async_data = msg["signals"].get(x_device_entry, None)
|
||||
# Make sure the signal exists, otherwise fall back to index
|
||||
if async_data is None:
|
||||
# Try to grab the data from device signals
|
||||
data_plot_x = self._get_x_data(plot_mode, x_device_entry)
|
||||
if len(data_plot_x) != len(data_plot_y):
|
||||
# If the data is not the same length, fall back to index
|
||||
logger.warning(
|
||||
f"Async data for curve {curve.name()} is None. Falling back to index."
|
||||
)
|
||||
data_plot_x = np.linspace(0, len(data_plot_y) - 1, len(data_plot_y))
|
||||
elif x_data is not None:
|
||||
data_plot_x = np.hstack((x_data, async_data["value"]))
|
||||
else:
|
||||
data_plot_x = async_data["value"]
|
||||
# Plot the data
|
||||
self._auto_adjust_async_curve_settings(curve, len(data_plot_y))
|
||||
curve.setData(data_plot_x, data_plot_y)
|
||||
|
||||
|
@ -135,13 +135,13 @@ def test_async_plotting(qtbot, bec_client_lib, connected_client_gui_obj):
|
||||
|
||||
# Wait for the scan to finish and the data to be available in history
|
||||
# Wait until scan_id is in history
|
||||
def _wait_for_scan_in_hisotry():
|
||||
def _wait_for_scan_in_history():
|
||||
if len(client.history) == 0:
|
||||
return False
|
||||
# Once items appear in storage, the last one hast to be the one we just scanned
|
||||
return client.history[-1].metadata.bec["scan_id"] == status.scan.scan_id
|
||||
|
||||
qtbot.waitUntil(_wait_for_scan_in_hisotry, timeout=10000)
|
||||
qtbot.waitUntil(_wait_for_scan_in_history, timeout=10000)
|
||||
last_scan_data = client.history[-1]
|
||||
# check plotted data
|
||||
x_data, y_data = curve.get_data()
|
||||
|
@ -353,7 +353,7 @@ def test_update_async_curves(monkeypatch, qtbot, mocked_client):
|
||||
wf = create_widget(qtbot, Waveform, client=mocked_client)
|
||||
c = wf.plot(arg1="async_device", label="async_device-async_device")
|
||||
wf._async_curves = [c]
|
||||
wf.x_mode = "timestamp"
|
||||
wf.x_mode = "timestamp" # Timestamp is not supported, fallback to index.
|
||||
dummy_scan = create_dummy_scan_item()
|
||||
wf.scan_item = dummy_scan
|
||||
|
||||
@ -366,7 +366,7 @@ def test_update_async_curves(monkeypatch, qtbot, mocked_client):
|
||||
monkeypatch.setattr(c, "setData", fake_setData)
|
||||
|
||||
wf.update_async_curves()
|
||||
np.testing.assert_array_equal(recorded.get("x"), [11, 21, 31])
|
||||
np.testing.assert_array_equal(recorded.get("x"), [0, 1, 2])
|
||||
np.testing.assert_array_equal(recorded.get("y"), [1, 2, 3])
|
||||
|
||||
|
||||
@ -528,12 +528,10 @@ def test_setup_async_curve(qtbot, mocked_client, monkeypatch):
|
||||
assert "async_device" in endpoint_called
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x_mode", ("timestamp", "index"))
|
||||
def test_on_async_readback_add_update(qtbot, mocked_client, x_mode):
|
||||
def test_on_async_readback_add_update(qtbot, mocked_client):
|
||||
"""
|
||||
Test that on_async_readback extends or replaces async data depending on metadata instruction.
|
||||
For 'timestamp' mode, new timestamps are appended to x_data.
|
||||
For 'index' mode, x_data simply increases by integer index.
|
||||
'Index' mode
|
||||
"""
|
||||
wf = create_widget(qtbot, Waveform, client=mocked_client)
|
||||
wf.scan_item = create_dummy_scan_item()
|
||||
@ -543,7 +541,7 @@ def test_on_async_readback_add_update(qtbot, mocked_client, x_mode):
|
||||
c.setData([0, 1, 2], [10, 11, 12])
|
||||
|
||||
# Set the x_axis_mode
|
||||
wf.x_axis_mode["name"] = x_mode
|
||||
wf.x_axis_mode["name"] = "index"
|
||||
|
||||
############# Test add ################
|
||||
|
||||
@ -554,10 +552,7 @@ def test_on_async_readback_add_update(qtbot, mocked_client, x_mode):
|
||||
x_data, y_data = c.get_data()
|
||||
assert len(x_data) == 5
|
||||
# Check x_data based on x_mode
|
||||
if x_mode == "timestamp":
|
||||
np.testing.assert_array_equal(x_data, [0, 1, 2, 1001, 1002])
|
||||
else: # x_mode == "index"
|
||||
np.testing.assert_array_equal(x_data, [0, 1, 2, 3, 4])
|
||||
np.testing.assert_array_equal(x_data, [0, 1, 2, 3, 4])
|
||||
|
||||
np.testing.assert_array_equal(y_data, [10, 11, 12, 100, 200])
|
||||
|
||||
@ -566,11 +561,7 @@ def test_on_async_readback_add_update(qtbot, mocked_client, x_mode):
|
||||
metadata2 = {"async_update": {"max_shape": [None], "type": "replace"}}
|
||||
wf.on_async_readback(msg2, metadata2)
|
||||
x_data2, y_data2 = c.get_data()
|
||||
if x_mode == "timestamp":
|
||||
np.testing.assert_array_equal(x_data2, [555])
|
||||
else:
|
||||
|
||||
np.testing.assert_array_equal(x_data2, [0])
|
||||
np.testing.assert_array_equal(x_data2, [0])
|
||||
|
||||
np.testing.assert_array_equal(y_data2, [999])
|
||||
|
||||
|
Reference in New Issue
Block a user