Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions datalab/gui/plothandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from plotpy.items import CurveItem, GridItem, LegendBoxItem, MaskedXYImageItem
from plotpy.plot import PlotOptions
from qtpy import QtWidgets as QW
from qwt import QwtScaleDraw
from qwt import QwtDateTimeScaleDraw, QwtScaleDraw
from sigima.objects import ImageObj, SignalObj, TypeObj

from datalab.adapters_metadata import GeometryAdapter, TableAdapter
Expand Down Expand Up @@ -725,8 +725,12 @@ def refresh_plot(
if has_datetime and datetime_format is not None:
self.plot.set_axis_datetime("bottom", format=datetime_format)
else:
# Restore default scale draw (remove datetime formatting)
self.plot.setAxisScaleDraw(self.plot.get_axis_id("bottom"), QwtScaleDraw())
# Restore default scale draw only when leaving the datetime mode:
# replacing it on every refresh could misalign the axis ticks with
# the grid and the curves (see Issue #457)
axis_id = self.plot.get_axis_id("bottom")
if isinstance(self.plot.axisScaleDraw(axis_id), QwtDateTimeScaleDraw):
self.plot.setAxisScaleDraw(axis_id, QwtScaleDraw())


class ImagePlotHandler(BasePlotHandler[ImageObj, MaskedXYImageItem]):
Expand Down
102 changes: 102 additions & 0 deletions datalab/tests/features/signal/xaxis_scale_draw_unit_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.

"""
X axis scale draw unit tests
----------------------------

The X axis of the signal view keeps its scale draw when the view is refreshed, so
that its ticks stay aligned with the grid and the curves (the scale draw is only
replaced when leaving the date/time mode).
"""

# guitest: show

from __future__ import annotations

from datetime import datetime, timedelta

import numpy as np
import pytest
from plotpy.plot import BasePlot
from qwt import QwtDateTimeScaleDraw
from sigima.objects import SignalObj, create_signal

from datalab.tests import datalab_test_app_context

# X bounds which are not graduations of the axis once autoscaled (as for the
# 'step.npy' test file): end labels do not overflow the axis ends
X_MIN, X_MAX = 3.1e-7, 4.08e-7


def _create_step_signal() -> SignalObj:
"""Create a signal whose X axis bounds are not graduations"""
x = np.linspace(X_MIN, X_MAX, 500)
return create_signal("Step", x, np.tanh((x - 3.15e-7) * 1e8))


def _create_datetime_signal() -> SignalObj:
"""Create a signal with a date/time X axis"""
start = datetime(2025, 1, 1)
timestamps = [start + timedelta(seconds=i) for i in range(100)]
obj = create_signal("Date/time", np.arange(100.0), np.sin(np.arange(100.0) / 10))
obj.set_x_from_datetime(timestamps, unit="s")
return obj


def _x_axis_ends(plot: BasePlot) -> tuple[list[float], list[float]]:
"""Return the ends of the X axis scale and of the X canvas map, in canvas
coordinates"""
widget = plot.axisWidget(plot.xBottom)
offset = widget.x() - plot.canvas().x()
smap = widget.scaleDraw().scaleMap()
cmap = plot.canvasMap(plot.xBottom)
return (
sorted((smap.p1() + offset, smap.p2() + offset)),
sorted((cmap.p1(), cmap.p2())),
)


def test_refresh_keeps_x_scale_draw() -> None:
"""Refreshing the signal view keeps the scale draw of the X axis"""
with datalab_test_app_context(console=False, exec_loop=False) as win:
panel = win.signalpanel
plot = panel.plothandler.plot
panel.add_object(_create_step_signal())
scale_draw = plot.axisScaleDraw(plot.xBottom)
panel.manual_refresh()
assert plot.axisScaleDraw(plot.xBottom) is scale_draw
panel.add_object(_create_step_signal())
assert plot.axisScaleDraw(plot.xBottom) is scale_draw


def test_x_axis_aligned_with_canvas() -> None:
"""The X axis ticks are aligned with the grid and the curves after loading"""
with datalab_test_app_context(console=False, exec_loop=False) as win:
panel = win.signalpanel
plot = panel.plothandler.plot
panel.add_object(_create_step_signal())
scale_ends, canvas_ends = _x_axis_ends(plot)
assert scale_ends == pytest.approx(canvas_ends, abs=0.5)
panel.manual_refresh()
scale_ends, canvas_ends = _x_axis_ends(plot)
assert scale_ends == pytest.approx(canvas_ends, abs=0.5)


def test_datetime_x_axis_restored() -> None:
"""The date/time X axis formatting is removed when showing regular signals"""
with datalab_test_app_context(console=False, exec_loop=False) as win:
panel = win.signalpanel
plot = panel.plothandler.plot
panel.add_object(_create_datetime_signal())
assert isinstance(plot.axisScaleDraw(plot.xBottom), QwtDateTimeScaleDraw)
panel.add_object(_create_step_signal())
scale_draw = plot.axisScaleDraw(plot.xBottom)
assert not isinstance(scale_draw, QwtDateTimeScaleDraw)
panel.manual_refresh()
assert plot.axisScaleDraw(plot.xBottom) is scale_draw


if __name__ == "__main__":
test_refresh_keeps_x_scale_draw()
test_x_axis_aligned_with_canvas()
test_datetime_x_axis_restored()
3 changes: 3 additions & 0 deletions doc/locale/fr/LC_MESSAGES/release_notes/release_1.04.po
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ msgstr "Correction du sous-échantillonnage automatique des signaux (**Préfére
msgid "Fixed changes of the auto downsampling and line width settings only applying to the curves of the selected signals: the other curves kept the former settings, even once selected again. These settings now apply to all curves as soon as the Settings dialog is closed"
msgstr "Correction des modifications des préférences de sous-échantillonnage automatique et d'épaisseur de trait qui ne s'appliquaient qu'aux courbes des signaux sélectionnés : les autres courbes conservaient les anciennes préférences, même une fois sélectionnées à nouveau. Ces préférences s'appliquent désormais à toutes les courbes dès la fermeture de la boîte de dialogue des préférences"

msgid "Fixed the X axis ticks being shifted relative to the vertical grid lines and the curves after opening a signal or changing the selection, for signals whose X axis does not start and end on a graduation (e.g., `step.npy` from the Sigima test data): the shift remained until the view was panned or zoomed. The X axis now stays aligned with the grid and the curves (fixes [Issue #457](https://github.com/DataLab-Platform/DataLab/issues/457))"
msgstr "Correction des graduations de l'axe X qui étaient décalées par rapport aux lignes verticales de la grille et aux courbes après l'ouverture d'un signal ou un changement de sélection, pour les signaux dont l'axe X ne commence et ne se termine pas sur une graduation (par exemple, `step.npy` des données de test de Sigima) : le décalage persistait jusqu'à un déplacement ou un zoom de la vue. L'axe X reste désormais aligné avec la grille et les courbes (corrige [Issue #457](https://github.com/DataLab-Platform/DataLab/issues/457))"

msgid "**HDF5 import:**"
msgstr "**Import HDF5 :**"

Expand Down
1 change: 1 addition & 0 deletions doc/release_notes/release_1.04.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ See the [HDF5 browser guide](../features/common/h5browser.rst) for scientific ob

* Fixed auto downsampling of signals (**Settings > Visualization > Signals**) only starting above 5 times the configured maximum number of points: with the default value of 100,000 points, signals of a few hundred thousand points were drawn in full, which slowed down the display. Signals with more points than the maximum are now downsampled so that at most this number of points is drawn, and the Settings dialog and the documentation now give the actual default value (100,000 instead of 10,000) (fixes [Issue #455](https://github.com/DataLab-Platform/DataLab/issues/455))
* Fixed changes of the auto downsampling and line width settings only applying to the curves of the selected signals: the other curves kept the former settings, even once selected again. These settings now apply to all curves as soon as the Settings dialog is closed
* Fixed the X axis ticks being shifted relative to the vertical grid lines and the curves after opening a signal or changing the selection, for signals whose X axis does not start and end on a graduation (e.g., `step.npy` from the Sigima test data): the shift remained until the view was panned or zoomed. The X axis now stays aligned with the grid and the curves (fixes [Issue #457](https://github.com/DataLab-Platform/DataLab/issues/457))

**HDF5 import:**

Expand Down
Loading